Шифрование и дешифрование по частям, похоже, не работают - PullRequest
1 голос
/ 11 апреля 2020

Рассмотрим код:

const CryptoJS = require("crypto-js");

var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");

// encrypt
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });

var ciphertextPart1 = aesEncryptor.process("Message Part 1");
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
var ciphertextPart4 = aesEncryptor.finalize();

// decrypt
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });

var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
var plaintextPart5 = aesDecryptor.finalize();

console.log(plaintextPart5.toString());

Источник: https://cryptojs.gitbook.io/docs/#ciphers

Возможно, я не прав, но Я ожидал, что сообщения будут расшифрованы .

На самом деле вывод:

61676520506172742033

Я понятия не имею, что означает этот вывод и откуда он берется.

Если я распечатываю другую часть, та же проблема :

console.log(plaintextPart4.toString());

Вывод:

7373616765205061727420324d657373

Обсуждение

В одном комментарии говорится, что я ошибаюсь в своем предположении о том, как работает метод, хороший ответ тоже может меня поправить! Из моих исследований я знаю разницу между односторонним шифрованием и частями: для меня нет никакого смысла в том, как оно на самом деле работает, это кажется ошибкой. Моя идея заключается в том, что вы можете продолжать добавлять сообщения для шифрования, как мы можем сделать с хешированием, в случае хеширования (из того же вышеупомянутого источника), кажется, работает, почему бы и не шифровать?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Честно говоря, я ожидал, что этот пример сработает, поскольку он взят из официальной документации, и они ничего не упоминают.

Полная документация - редкое чудовище.

для меня не имеет смысла, как это на самом деле работает, кажется, ошибка

Это работает так:

const CryptoJS = require("crypto-js");

const original_message = " ...0, ...1, ...2, ...3, ...4, ...5, ...6, ...7, ...8, ...9, ...The End!"

var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv  = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");

const aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });
const aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });

const fragment_size = 25
const e_acc = []
for(let i = 0 ; i*fragment_size < original_message.length ; ++i ) {
  const slice = original_message.slice(i*fragment_size, i*fragment_size + fragment_size)
  console.log("slice to encrypt", slice)
  e_acc.push(aesEncryptor.process(slice));
}
e_acc.push(aesEncryptor.finalize());

let message = ""
for(let i = 0 ; i !== e_acc.length ; ++i ) {
  message += aesDecryptor.process(e_acc[i]).toString(CryptoJS.enc.Utf8)
  console.log("intermidiate message", message) 
}
message += aesDecryptor.finalize().toString(CryptoJS.enc.Utf8)
console.log("full message", message) 

[... ] предполагается, что это уловка, что вы можете добавлять информацию по частям
[...] Моя идея заключается в том, что вы можете продолжать добавлять сообщения для шифрования

И вы можете, единственное, что это - вы не можете расшифровать части сообщений, которые не заполняют блок. Вы можете получить только столько, сколько уместится в цепочку из полных блоков.

Рассмотрите код

const sum1 = solver.process("1+22+3")
const sum2 = solver.process("03")
const sum3 = solver.finalize()

Здесь вы можете получить промежуточное звено sum1 - сумма 1 и 22. Но вы не можете сразу добавить 3, потому что, как вы можете видеть позже, на самом деле это не 3, а 303. То же самое с sum2 - solver пока не знают, следует ли добавить 303 или, возможно, оно станет 3031234.... Поэтому единственное, что может solver сделать, - это запомнить 3, а затем 303, но не использовать его. Пока вы не позвоните finalize.

aesEncryptor похоже на solver, но гораздо сложнее.

Давайте вернемся к aesDecryptor и почему все plaintextPart* содержат только части сообщения .. Зачем вам в первую очередь «прогрессивное шифрование»? Возможно, потому что вы отправляете фрагменты через net? Ключевое слово: фрагментов - они преднамеренно не содержат все предыдущие части сообщения, поскольку они могут весить гигабайты!

в случае хеширования [...], похоже, работает, почему бы не использовать шифрование?

Хеширование - это совсем другое. Вы не можете ожидать, что AES имеет все те же свойства, что и хеширование, так как вы не можете ожидать, что хеширование имеет все те же свойства, что и, например, суммирование.

1 голос
/ 12 апреля 2020

Метод .process возвращает все новые фрагменты зашифрованного текста, которые были сгенерированы путем обработки открытого текста, заданного в качестве аргумента .process, вместе с любым открытым текстом, оставшимся от более ранней операции шифрования.

В этом В этом случае алгоритм шифрования является AES. В частности, это AES-128, потому что ключ, используемый для создания шифратора, имеет длину 128 бит. AES-128 использует открытый текст в 128-битных (16-байтовых) блоках и испускает 128-битный (16 байт) зашифрованного текста для каждого блока открытого текста. Эта основанная на блоках обработка дает результаты, которые вы не понимали.

Что происходит с вашей программой:

var ciphertextPart1 = aesEncryptor.process("Message Part 1");

Зашифрователю дается 14 байтов ввода. Этого недостаточно, чтобы позволить ему генерировать блок зашифрованного текста, поэтому .process возвращает пустой результат зашифрованного текста, который вы храните в ciphertextPart1. Шифратор хранит необработанные 14 байтов внутри.

var ciphertextPart2 = aesEncryptor.process("Message Part 2");

Это дает шифратору еще 14 байтов. Он добавляет их к 14 байтам, оставшимся от предыдущего вызова, поэтому теперь он имеет в общей сложности 28 необработанных байтов. Он обрабатывает столько байтов, сколько может. То есть он обрабатывает первые 16 из этих байтов («Message Part1Me») и возвращает блок зашифрованного текста для тех 16 байтов, которые вы храните в cipherText2. Шифратор теперь содержит 12 необработанных байтов.

var ciphertextPart3 = aesEncryptor.process("Message Part 3");

Это дает шифратору еще 14 байтов. Теперь у него 26 необработанных байтов. Он обрабатывает первые 16 из этих байтов («ssage Part2Mess») и возвращает блок зашифрованного текста для тех 16 байтов, которые вы храните в cipherText3. Шифратор теперь содержит 10 необработанных байтов.

var ciphertextPart4 = aesEncryptor.finalize();

Это заставляет шифратор обрабатывать любые необработанные байты. Он может работать только с 16-байтовыми блоками, поэтому он добавляет 6 байтов заполнения к оставшимся 10 необработанным открытым текстовым байтам («возрастная часть 3»), шифрует этот блок и возвращает зашифрованный текст для этого блока. Вы сохраняете этот блок зашифрованного текста как ciphertextPart4.

И теперь вы расшифровываете блоки зашифрованного текста.

var plaintextPart1 = aesDecryptor.process(ciphertextPart1);

cipherTextPart1 был пустым блоком, поэтому plaintextPart1 будет пустым и, очевидно, расшифровщик не будет хранить необработанный зашифрованный текст.

var plaintextPart2 = aesDecryptor.process(ciphertextPart2);

cipherTextPart2 содержал зашифрованную версию первых 16 байт открытого текста, поэтому plaintextPart2 будет содержать «Message Part 1Me». Ввод зашифрованного текста был ровно 16 байтов, поэтому расшифровщик не содержит необработанного зашифрованного текста.

var plaintextPart3 = aesDecryptor.process(ciphertextPart3);

cipherTextPart3 содержал зашифрованную версию следующих 16 байтов открытого текста, поэтому plaintextPart3 будет содержать "ssage Часть 2 И снова расшифровщик не содержит необработанного зашифрованного текста.

var plaintextPart4 = aesDecryptor.process(ciphertextPart4);

cipherTextPart4 содержал зашифрованную версию последних 10 байтов открытого текста, поэтому plaintextPart3 будет содержать «age Part 3». В расшифровщике не осталось необработанного зашифрованного текста.

var plaintextPart5 = aesDecryptor.finalize();

В расшифровщике не осталось необработанного зашифрованного текста, поэтому finalize не нужно выполнять, а plaintextPart5 будет пустым.

...