2016-05-05 2 views
0

У меня есть следующая процедура декодирования/кодирования. Однако кодировка не работает должным образом (она должна печатать «CMlaKA», а не «ClaKA» в журнале консоли). Я думаю, проблема связана с сдвигом бит, но я не могу сказать, где.кодировка base64 в javascript с сдвигом бит

Вот 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: ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=", 

    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?'); 
} 
+0

Если вы поддерживаете ниже IE10, зачем переписывать функции base64, когда они уже существуют в браузере? https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64 –

+0

Я не использую JS в браузере ... –

ответ

0

Я не мог найти ваш алгоритм реализации, но нашел это один в wikipedia и исправлены ваши

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

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

var Base64 = { 
     _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/", 

    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(); 
+1

'_24c' - это 24-битный символ из 3' 8bit' символов , – GRiMe2D

+0

Боюсь, это не то решение, которое я ищу. Конечным результатом должно быть «CMlaKA». Причина этого в том, что происходит смещение бит. Моя версия очень близка «ClaKA», но это все еще не совсем верно. Если вы перемещаете бит, смещающийся (как вы это делали в своем ответе), кодировка base64 будет совершенно иной, когда она должна быть одинаковой. –

0

В коде есть пара ошибок, и они связаны не только с методом кодирования, но и с декодированием.

Прежде всего, вы используете плохую строку ключа. Accoring to Wikipedia Wikipedia - Base64 'A' равно '0', а не '.' как в вашем примере.

Это не позволит вам проверить ваш код на общедоступных веб-сайтах.

Это «стандартный» ключ строки:

_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/=", 

«=» в конце концов, для заполнения и не должны использоваться непосредственно в процессе преобразования

Тогда вы получили проблема с вашим байтовым кодом. Вы вычисляете значения base64 в неправильном направлении. Вы должны посмотреть ссылку Википедии, чтобы узнать, какие байты следует рассматривать как каждое значение base64.

Здесь фиксированный фрагмент для декодера:

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

Здесь фиксированный фрагмент для кодера:

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; 

Предполагая, что вы внесли все эти изменения, если входной сигнал t он декодер «CMlaKA», выход - [12,217,155,44,16], после чего кодер вернет правильный ответ.

+0

Привет, они ключевой строки (мое понимание этого), где вы можете поместить пароль для шифрования base64 с помощью собственного ключа. В приведенном выше примере есть только дополнительная точка, которая на самом деле не имеет значения. Кодирование/декодирование должно быть одинаковым. –

+0

@Ke. 'Base64' ** не ** шифрует. Это просто преобразование двоичных данных в * безопасный * текст ASCII – GRiMe2D

+0

Так же, как @ GRiMe2D сказал, шифрование base64 - плохая идея! Более того, «.» является существенным, если вы попытаетесь сравнить значения с «стандартным» декодером/кодировщиком для проверки, так как индексы стандартных значений, такие как буква «А», сдвинуты. –

Смежные вопросы