Неверный размер блока AES Расшифровка SJCL

Попытка расшифровать AES с помощью RNCryptor-js, который использует SJCL. После регистрации всех шагов на каждом конце (другой конец — RNCryptor-python) ключи, соли , HMAC-хэши, все совпадает. Но когда я дохожу до последнего шага:

var aes = new sjcl.cipher.aes(encryption_key);
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]()
var decrypted = aes.decrypt(ciphertext, iv);

Я получаю сообщение об ошибке:

 sjcl.exception.invalid {toString: function, message: "invalid aes block size"}

Вот полный код:

ПБКДФ2:

this.KeyForPassword = function(password, salt) {

  var hmacSHA256 = function (password) {
      var hasher = new sjcl.misc.hmac(password, sjcl.hash.sha256);
      this.encrypt = function () {
          return hasher.encrypt.apply(hasher, arguments);
      };
  };
  return sjcl.misc.pbkdf2(password, salt, 10000, 32 * 8, hmacSHA256);
};

Расшифровка (принимает шестнадцатеричный ввод):

this.decrypt = function(password, message, options) {

  message = sjcl.codec.hex.toBits(message);

  options = options || {};

  var version = sjcl.bitArray.extract(message, 0 * 8, 8);
  var options = sjcl.bitArray.extract(message, 1 * 8, 8);

  var encryption_salt = sjcl.bitArray.bitSlice(message, 2 * 8, 10 * 8);
  var encryption_key = _this.KeyForPassword(password, encryption_salt, "decryption");

  var hmac_salt = sjcl.bitArray.bitSlice(message, 10 * 8, 18 * 8);
  var hmac_key = _this.KeyForPassword(password, hmac_salt, "decryption");

  var iv = sjcl.bitArray.bitSlice(message, 18 * 8, 34 * 8);

  var ciphertext_end = sjcl.bitArray.bitLength(message) - (32 * 8);
  var ciphertext = sjcl.bitArray.bitSlice(message, 34 * 8, ciphertext_end);

  var hmac = sjcl.bitArray.bitSlice(message, ciphertext_end);
  var expected_hmac = new sjcl.misc.hmac(hmac_key).encrypt(sjcl.bitArray.bitSlice(message, 0, ciphertext_end));

  if (! sjcl.bitArray.equal(hmac, expected_hmac)) {
    throw new sjcl.exception.corrupt("HMAC mismatch or bad password.");
  }

  var aes = new sjcl.cipher.aes(encryption_key);
  sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]()
  var decrypted = aes.decrypt(ciphertext, iv);

  return decrypted;
}

Ошибка возникает во предпоследнем операторе, где определено decrypted.

Я посмотрел на исключение sjcl, и похоже, что оно ищет ввод длиной 4, который, как я предполагаю, является WordArray. Я просто не понимаю, как получить правильный ввод. Как я уже сказал, зашифрованный текст, тег iv, hmac, соли правильно нарезаются на конце javascript. Может просто проблема с кодировкой.

Эта ошибка также, кажется, происходит только в json (формат: '{"key":"value"}'), когда я попробовал что-то вроде "Hello, world", я получил массив из 4 слов без ошибок.

Какие-либо предложения?


person internetwhy    schedule 19.09.2015    source источник
comment
Когда вы используете JSON, если вы настроили свой код для вывода ciphertext.length, что означает эта длина?   -  person WDS    schedule 19.09.2015
comment
@WDS, ciphertext.length вернул разную длину для разных json. Для более короткого у меня получилось 16, для более длинного: 24, для еще более длинного: 36.   -  person internetwhy    schedule 19.09.2015
comment
Если вместо этого я использую Crypto-JS для выполнения последнего шага расшифровки, я не получаю ошибки, но получаю пустой WordArray.   -  person internetwhy    schedule 19.09.2015
comment
Я немного не в себе, но кажется возможным, что функции шифрования и дешифрования могут обрабатывать только 1 блок за раз, и что вам нужно вручную разбить зашифрованный текст на отдельные блоки, разбить каждый блок на 4 слова, и передать их в функцию по 4 слова за раз. В .NET есть методы для обработки зашифрованного текста любой длины в одном наборе команд, но я предполагаю, что вам нужно написать свой собственный. В качестве теста попробуйте BitSlice уменьшить зашифрованный текст до 128 бит и передать его в функцию расшифровки. Посмотрите, расшифровывает ли это часть обычного текста.   -  person WDS    schedule 20.09.2015
comment
Хорошая идея. Попробовал разделить, и я получил массив слов, но по какой-то причине не могу его закодировать. Ни CryptoJS, ни sjcl Utf8, похоже, не работают.   -  person internetwhy    schedule 20.09.2015
comment
Извините, что я в тупике в этот момент. Если вы хотите выложить всю программу для обеих сторон, я был бы рад с ними повозиться и попытаться найти проблему. Но, к сожалению, в данный момент у меня нет идей.   -  person WDS    schedule 20.09.2015
comment
Спасибо, что предложили помощь! Вот python и javascript   -  person internetwhy    schedule 21.09.2015
comment
Чувак, мне жаль говорить, что мне повезло еще меньше, чем тебе. Сторона Python работала как шарм, но я не могу заставить JavaScript прекратить выдавать исключение Crypto.Js is undefined независимо от того, что я делаю.   -  person WDS    schedule 21.09.2015
comment
Данг. Вы видели html в javascript со ссылками на библиотеки? Еще раз спасибо, чувак.   -  person internetwhy    schedule 21.09.2015


Ответы (1)


 var decrypted = aes.decrypt(ciphertext, iv);

должно быть

 var decrypted = sjcl.mode.cbc.decrypt(aes, ciphertext, iv);

У меня также были проблемы с заполнением в cbc.js (ссылка на источник) и оказалось, что я не включил bitArray.js (ссылка), которая включает важную функцию xor (не путать с простым оператором ^).

Итак: включите bitArray.js

Вывод также должен быть закодирован:

return sjcl.codec.utf8String.fromBits(decrypted);
person internetwhy    schedule 02.10.2015
comment
Для тех, кто это читает: не забывайте, что параметры должны быть в битах: var kbits = sjcl.codec.arrayBuffer.toBits(new Uint8Array(key).buffer); var aes = новый sjcl.cipher.aes (кбит); var plainBinary = sjcl.mode.cbc.decrypt(aes, sjcl.codec.arrayBuffer.toBits(encryptedBinary.buffer), sjcl.codec.arrayBuffer.toBits(iv.buffer)); - person David; 16.02.2016