Я пытаюсь реконструировать протокол из реализации javascript, и я застрял на метод шифрования AES. Я программирую это на C ++, с помощью библиотеки Crypto ++. Он использует библиотеку SJCL и вызывает ciphertext = (new sjcl.cipher.aes(key)).encrypt(plaintext)
, Из документации SJCL я вижу, что это низкоуровневый интерфейс. ciphertext
, key
, а также plaintext
все 4-элементные массивы 32-битных целых чисел. Насколько я знаю и мог найти в Google, Crypto ++ предоставляет только высокоуровневые интерфейсы. Есть ли способ заставить Crypto ++ делать то, что делает SJCL? Кроме того, что именно это делает encrypt
метод сделать?
http://bitwiseshiftleft.github.com/sjcl/doc/symbols/sjcl.cipher.aes.html
Редактировать: я заметил преобразованный код JavaScript plantext
от строки до целых, и я думаю, что я пробовал каждую комбинацию изменения порядка байтов каждой переменной. Во всяком случае, я перепробовал все комбинации, которые имели смысл. Я также пытался создать массивы int32_t
и инициализируем их тем, что было введено в эту строку javascript. Вот что я получил сейчас:
void crypto()
{
SecByteBlock key(16);
int32_t plain[4] = { 0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56 }, cipher[4];
int32_t* keyBuf = (int32_t*) key.BytePtr();
keyBuf[0] = 1885434739;
keyBuf[1] = 2003792484;
keyBuf[2] = 0;
keyBuf[3] = 0;
cout << "plain = [" << plain[0] << ", " << plain[1] << ", " << plain[2] << ", " << plain[3] << "]\n";
cout << "key = [" << keyBuf[0] << ", " << keyBuf[1] << ", " << keyBuf[2] << ", " << keyBuf[3] << "]\n";
ECB_Mode<AES>::Encryption e;
e.SetKey(key, key.size());
StringSource((const byte*) plain, 16, true, new StreamTransformationFilter( e, new ArraySink((byte*)cipher, 16) ) );
cout << "cipher = [" << cipher[0] << ", " << cipher[1] << ", " << cipher[2] << ", " << cipher[3] << "]\n";
}
function crypto()
{
var key = [1885434739, 2003792484, 1885434739, 2003792484];
var plain = [0x93C467E3,0x7DB0C7A4,0xD1BE3F81,0x0152CB56];
console.log("plain = "+plain);
console.log("key = "+key);
var cipher = (new sjcl.cipher.aes(key)).encrypt(plain);
console.log("cipher = "+cipher);
}
Вот вывод версии C ++:
plain = [2479122403, 2108737444, 3518906241, 22203222]
key = [1885434739, 2003792484, 1885434739, 2003792484]
cipher = [3437909595, 1341853431, 2532744872, 2416113380]
и JavaScript:
plain = 2479122403,2108737444,3518906241,22203222
key = 1885434739,2003792484,1885434739,2003792484
cipher = -1974659585,-1567997661,-1863224381,-318378846
Да, вы должны использовать целые числа в качестве байтовых массивов с прямым порядком байтов. Поэтому старший байт должен быть слева. Затем вы получите 16-байтовый ввод / вывод для 128-битного AES. Вы можете использовать Crypto ++ или другие библиотеки криптографии более высокого уровня в режиме ECB для выполнения шифрования / дешифрования блока.
Обратите внимание, что SJCL aes
Класс реализует только примитив. Он используется в SJCL как реализация одного из куб.см или же ocb2 режимы шифрования. Эти режимы, в свою очередь, используются вспомогательной библиотекой, но — если я правильно помню — тот сразу переходит к использованию кодирования / декодирования JSON, что может оказаться для вас слишком большим шагом.
Других решений пока нет …