【问题标题】:base64 encoding in javascript with bit shiftingjavascript中的base64编码与位移
【发布时间】:2026-01-25 03:05:02
【问题描述】:

我有以下解码/编码例程。但是,编码不能正常工作(它应该在控制台日志中打印“CMlaKA”而不是“ClaKA”)。我认为问题在于位移,但我不知道在哪里。

这里有一个jsfiddle来解释

https://jsfiddle.net/4yfrLv9y/16/

这是代码(程序在底部运行)

var consoleLine = "<p class=\"console-line\"></p>";

console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};

var Base64 = {
        _keyStr: ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=",

    encode : function (input) {
        var output = [],
            chr1, chr2, chr3, enc1, enc2, enc3, enc4,
            i = 0;
        while (i < input.length) {
            chr1 = input[i++];
            chr2 = input[i++];
            chr3 = input[i++];

            enc1 = chr1 & 0x3f;
            enc2 = (chr1 >> 6) | ((chr2 & 0x3c) << 2);
            enc3 = (chr2 >> 4) | ((chr3 & 0x3) << 4);
            enc4 = chr3 >> 2;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output.push([this._keyStr.charAt(enc1),
                         this._keyStr.charAt(enc2),
                         this._keyStr.charAt(enc3),
                         this._keyStr.charAt(enc4)].join(''));
        }

        return output.join('');
    },

    decodeAsArray: function (b) {
        var d = this.decode(b),
            a = [],
            c;
                //alert("decoded base64:" + d);
        for (c = 0; c < d.length; c++) {
            a[c] = d.charCodeAt(c)
        }
                //alert("returning a");
        return a
    },

    decode: function( input ) {
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;

        do {
            enc1 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc2 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc3 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc4 = this._keyStr.indexOf(input.charAt(i++)) ;

            chr1 = (enc1 | ((enc2 & 3) << 6));
            chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << 4);
            chr3 = (enc3 >> 4) | (enc4 << 2);

            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
                        }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);

        return (output);
    }

};

basedecode();

function basedecode(){
//Converts 'CMlaKa to CcnK by base64'
    var decoded = "CMlaKA"
    //67 99 110 75 0 0  - This is the Byte Array, or ArrayBuffer of CcnK
    decoded = Base64.decode(decoded)
    console.log(decoded);
}

baseencode();

function baseencode(){
    var encoded = [67,99,110,75];// byte array of CcnK
    console.log(Base64.encode(encoded) + ' ---- Should be CMlaKA not ClaKA== - why is it different?'); 
}

【问题讨论】:

标签: javascript base64 decode encode arraybuffer


【解决方案1】:

我找不到你的实现算法,但是在wikipedia找到了这个 并纠正你的

var consoleLine = "<p class=\"console-line\"></p>";

console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};

var Base64 = {
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",

    encode : function (input) {
        var output = [],
            chr1, chr2, chr3, enc1, enc2, enc3, enc4,
            i = 0;
        while (i < input.length) {
            chr1 = input.charCodeAt(i);
            chr2 = input.charCodeAt(i+1);
            chr3 = input.charCodeAt(i+2);
            i+=3;

                        /* enc1 = chr1 && 0x3f;
                        enc2 = (chr1 >> 6) | ((chr2 & 0x3c) << 4);
                        enc3 = (chr2 >> 4) | ((chr3 & 0x3) << 2);
                        enc4 = chr3 >> 2; */

            var _24c = (chr1 << 16) + (chr2 << 8) + chr3;
            //n = [(n >>> 18) & 63, (n >>> 12) & 63, (n >>> 6) & 63, n & 63];
            enc1 = _24c >>> 18 & 63
            enc2 = _24c >>> 12 & 63
            enc3 = _24c >>> 6 & 63
            enc4 = _24c & 63


           /**  if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
             */
            output.push([this._keyStr.charAt(enc1),
                         this._keyStr.charAt(enc2),
                         this._keyStr.charAt(enc3),
                         this._keyStr.charAt(enc4)].join(''));
        }

        return output.join('');
    },

    decodeAsArray: function (b) {
        var d = this.decode(b),
            a = [],
            c;
                //alert("decoded base64:" + d);
        for (c = 0; c < d.length; c++) {
            a[c] = d.charCodeAt(c)
        }
                //alert("returning a");
        return a
    },

    decode: function( input ) {
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;

        do {
            enc1 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc2 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc3 = this._keyStr.indexOf(input.charAt(i++)) ;
            enc4 = this._keyStr.indexOf(input.charAt(i++)) ;

            chr1 = (enc1 | ((enc2 & 3) << 6));
            chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << 4);
            chr3 = (enc3 >> 4) | (enc4 << 2);

            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
                        }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);

        return (output);
    }

};

// basedecode();

function basedecode(){
//Converts 'CMlaKa to CcnK by base64'
    var decoded = "CMlaKA"
    //67 99 110 75 0 0  - This is the Byte Array, or ArrayBuffer of CcnK
    decoded = Base64.decode(decoded)
    console.log(decoded);
}

// baseencode();

function baseencode(){
    var encoded = [67,99,110,75];// byte array of CcnK
    console.log(Base64.encode(encoded) + ' ---- Should be CMlaKA not +la+A== - where do the + and = signs come from?'); 
}

function hashAndAssert(string_to_hash, result) {
    var hash = Base64.encode(string_to_hash);
  return '' + (hash == result) + ', expected: ' + result + '; output: ' + hash;
}

function unitTest() {
    console.log('#1 Passed ' + hashAndAssert('', ''))
  console.log('#2 Passed ' + hashAndAssert('foo', 'Zm9v'))
  console.log('#1 Passed ' + hashAndAssert('foobar', 'Zm9vYmFy'))
}

unitTest();

【讨论】:

  • _24c 是来自 3 个 8bit 字符的 24bit 字符。
  • 恐怕这不是我正在寻找的解决方案。最终结果应该是“CMlaKA”,这是因为发生了位移。我的版本非常接近“ClaKA”,但仍然不太正确。如果您移动位移位(正如您在答案中所做的那样),base64 编码将完全不同,当它需要相同时。
【解决方案2】:

您的代码中有几个错误,它们不仅涉及编码方法,还涉及解码方法。

首先,您使用了错误的密钥字符串。根据*Wikipedia - Base64'A'等于'0',而不是'.'就像你的例子一样。

这将阻止您根据公共网站检查您的代码的有效性。

这是“标准”密钥字符串:

_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

最后的'='是用来填充的,转换时不要直接使用

然后,您的字节移位代码有问题。 您以错误的方向计算 base64 值。您应该查看 Wikipedia 链接以了解应将哪些字节视为每个 base64 值。

这是解码器的固定 sn-p:

chr1 = enc1 << 2 | ((enc2 & 0xc0) >> 6);
chr2 = ((enc2 & 0x0f) << 4) | ((enc3 & 0x3c) >> 2);
chr3 = ((enc3 & 0x03) << 6) | enc4;

这里是一个固定的编码器sn-p:

enc1 =  (chr1 & 0xfc) >> 2;
enc2 = ((chr1 & 0x03) << 4) | ((chr2 & 0xf0) >> 4);
enc3 = ((chr2 & 0x0f) << 2) | ((chr3 & 0xc0) >> 6);
enc4 =   chr3 & 0x3f;

此外,您必须修剪输出值(在编码器中),因为它们位于无限容器中,因此:

enc1 = enc1 & 0x3f;
enc2 = enc2 & 0x3f;
enc3 = enc3 & 0x3f;

假设您进行了所有这些更改,如果解码器的输入为“CMlaKA”,则输出为 [12,217,155,44,16],然后编码器将返回正确答案。

【讨论】:

  • 嗨,他们的密钥字符串(我对它的理解)是您可以输入密码以使用您自己的密钥加密 base64 的地方。在上面的例子中,只有一个额外的点,这并不重要。编码/解码应该是一样的。
  • @Ke。 Base64 没有加密。它只是将二进制数据转换为 safe ASCII 文本
  • 就像@GRiMe2D 所说,base64 加密是个坏主意!此外,“。”如果您尝试将这些值与“标准”解码器/编码器进行比较以进行验证,这一点很重要,因为标准值的索引(例如字母“A”)会发生偏移。
  • 在我的情况下,点需要能够正确解码 base64。它与问题无关,_keyStr 变量中包含的内容也无关紧要。如果位移不正确,编码和解码仍然不会相同。这就是我试图克服的问题,这里给出的编辑没有得到所需的“CMlaKA”输出。
  • 很遗憾,如果您无法解释为什么结果应该是“CMlaKA”,我无法帮助您。一路上可能还有其他我无法验证的错误。我这里介绍的移位方法与网站base64encode.org相比是正确的