#encryption #cryptography #cryptojs #jsencrypt
#шифрование #криптография #cryptojs #jsencrypt
Вопрос:
У меня есть API для вызова, где я должен зашифровать свои данные с помощью заполнения RSA / ECB / PKCS1 и AES / CBC / PKCS5PADDING.
Sample Data: {"KEY":"VALUE"}
Шаг.1:
I have to generate a random number of 16 digit. eg: '1234567890123456'
Шаг.2:
Do RSA/ECB/PKCS1Padding to random number and base64Encode the result. we get "encrypted_key"
Шаг.3:
Concatenate random number amp; data:
DATA = 1234567890123456{"KEY":"VALUE"}
Шаг.4:
Do AES/CBC/PKCS5Padding on DATA (from Step 3) using random number(1234567890123456) as KEY amp; Base64Encoded random number as IV. we get "ENCRYPTED_DATA"
Итак, для шага 1 я использую JSEncrypt
библиотеку javascript.
для шага 4 я использую CrytoJS.AES.encrypt()
функцию. Я почти уверен, что моя функция JSEncrypt работает нормально, поскольку клиент может ее расшифровать, но клиент не может расшифровать мои данные. Я чувствую, что совершаю ошибку при использовании CryptoJS
.
Может ли кто-нибудь правильно подсказать мне, как использовать библиотеку.
То, что я делаю, это:
KEY = '1234567890123456'
IV = MTIzNDU2Nzg5MDEyMzQ1Ng== (result of btoa('1234567890123456') )
DATA = "1234567890123456{"KEY":"VAL"}"
cryptedData = Crypto.AES.encrypt(DATA, KEY, {iv: IV, mode: CryptoJS.mode.CBC,padding:CryptoJS.pad.Pkcs7})
Мне сказали использовать PKCS5Padding
шифрование AES / CBC (шаг 4), но, похоже, AES
это не поддерживает PKCS5Padding
, но PKCS7Padding
.
Я думаю, что я совершаю ошибку в том, как я передаю KEY amp; IV CryptoJS
.
Любая помощь будет принята с благодарностью.
Ответ №1:
Для начала давайте посмотрим, почему вы выполняете упражнение. RSA предназначен для кодирования только ограниченного объема данных. Итак, мы используем «гибридное шифрование», когда данные шифруются с использованием симметричного шифра со случайным ключом, а сам ключ шифруется с использованием RSA
Шифрование работает с двоичными данными, для безопасной передачи двоичных данных данные кодируются в печатную форму (hex или base64)
Шаг.1: Я должен сгенерировать случайное число из 16 цифр
Мы видим 16 цифр 0-9. На самом деле это небезопасно. Генерируя 16 цифр, вы получите ключ 10 ^ 16, что равно приблизительно 2 ^ 53 (если я ошибся в математике, пожалуйста, прокомментируйте).
Вам нужно сгенерировать 16 случайных байтов (цифры 0-256, что дает ключ 2 ^ 128). Это ваш DEK (ключ шифрования данных).
Вы можете закодировать DEK в печатную форму, в шестнадцатеричной кодировке он будет содержать 32 символа.
Шаг.2:
хорошо, теперь вы получаете зашифрованный encoded_encryption_key
Шаг 3, шаг 4
И здесь вы должны понимать, что вы делаете.
- зашифруйте ДАННЫЕ, используя DEK (не закодированное случайное число в двоичной форме), вы получите encrypted_data. Вы можете закодировать результат в encoded_encrypted_data
- объедините зашифрованный ключ и зашифрованные данные. Вам решать, кодировать ли его до или после кодирования. Я предлагаю вам выполнить конкатенацию encoded_encryption_key и encoded_encrypted_data с некоторым разделителем, потому что, если длина ключа RSA изменяется, длина encoded_encryption_key также изменяется. Обязательно обсудите с клиентом, какой именно формат ожидается.
Примечания:
- IV должен иметь длину 16 байт для AES, а для CryptoJS я считаю, что он должен быть шестнадцатеричным, поэтому использование btoa может быть не лучшей идеей. Я считаю, что CryptoJS просто урезает значение до 16 байт, но формально это неверно.
- Шифр CBC нуждается в какой-то проверке целостности, я предлагаю добавить к результату некоторый HMAC или подпись (в противном случае кто-то может изменить зашифрованный текст, и вы не сможете обнаружить подделку)
но, похоже, что AES поддерживает не PKCS5Padding, а PKCS7Padding.
Действительно, AES поддерживает Pkcs7. Pkcs5 функционально такой же, но определен в 64 блоках. Обозначение все еще используется в Java как наследие DES encryption.
Комментарии:
1. Большое спасибо за подробное объяснение! Я ценю это!