Я не могу понять, как генерируются последние 16 байтов.Если я решу игнорировать последние 16 байтов в расшифровке, Crypto ++ выбрасывает InvalidCiphertext
error
Последние 16 байтов заполнены.Заполнение добавляется фильтром StreamTransformationFilter
;см. Ссылка на класс StreamTransformationFilter в руководстве.Хотя не очевидно, DEFAULT_PADDING
- это PKCS_PADDING
для ECB_Mode
и CBC_Mode
.Это NO_PADDING
для других режимов, таких как OFB_Mode
и CTR_Mode
.
Необходимо указать NO_PADDING
только для фильтров шифрования и дешифрования.Однако вы должны убедиться, что открытый текст и зашифрованный текст кратны размеру блока, что равно 16 для AES.
Вы можете обойти ограничение размера блока, переключившись на другой режим, например CTR_Mode
.Но тогда вы должны быть очень осторожны с повторным использованием ключа или IV, что может быть затруднительно из-за используемой вами схемы получения пароля.
Вместо:
CBC_Mode<AES>::Encryption encryptor;
...
StreamTransformationFilter stfenc(encryptor, new Redirector(outSink));
Использование:
CBC_Mode<AES>::Encryption encryptor;
...
StreamTransformationFilter stfenc(encryptor, new Redirector(outSink), NO_PADDING);
Также см. CBC_Mode в вики Crypto ++.Вас также может заинтересовать Authenticated Encryption в вики.
Для этого вы также можете:
#ifndef CRYPTOPP_NO_GLOBAL_BYTE
namespace CryptoPP
{
using byte = unsigned char;
}
#endif
CRYPTOPP_NO_GLOBAL_BYTE
определяется после C ++ 17 std::byte
Исправления .Если CRYPTOPP_NO_GLOBAL_BYTE
не определено, то byte
находится в глобальном пространстве имен (Crypto ++ 5.6.5 и более ранние).Если определено CRYPTOPP_NO_GLOBAL_BYTE
, то byte
находится в пространстве имен CryptoPP
(Crypto ++ 6.0 и более поздних версий).
Для этого:
std::ofstream testOut("./test.enc", std::ios::binary);
FileSink outSink(testOut);
Вы также можете сделать:
FileSink outSink("./test.enc");
Для этого:
SHA256().CalculateDigest(passHash, (byte*) password.data(), password.size());
std::memcpy(key, passHash, AES::DEFAULT_KEYLENGTH);
std::memcpy(iv, passHash+AES::DEFAULT_KEYLENGTH, AES::BLOCKSIZE);
Вы можете рассмотреть возможность использования HKDF
в качестве функции деривации.Используйте один пароль, но две разные метки, чтобы обеспечить независимое получение.Одной меткой может быть строка "AES key derivation version 1"
, а другой меткой может быть "AES iv derivation version 1"
.
Метка будет использоваться в качестве параметра info
для DeriveKey
.Вам просто нужно вызвать его дважды, один раз для ключа и один раз для iv.
unsigned int DeriveKey (byte *derived, size_t derivedLen,
const byte *secret, size_t secretLen,
const byte *salt, size_t saltLen,
const byte *info, size_t infoLen) const
secret
- пароль.Если у вас есть salt
, используйте его.В противном случае HKDF использует соль по умолчанию.
Также см. HKDF на вики-сайте Crypto ++.
Наконец, относительно этого:
Вы можете обойти ограничение размера блока, переключившись на другой режим, например CTR_Mode.Но тогда вы должны быть очень осторожны с повторным использованием ключа или IV, что может быть затруднительно из-за используемой вами схемы получения пароля.
Вы также можете рассмотреть Интегрированную схему шифрования, например Схема интегрированного шифрования эллиптической кривой .Это IND-CCA2 , что является сильным понятием безопасности.Все, что вам нужно, упаковано в схему шифрования.
В соответствии с ECIES каждый пользователь получает пару открытого / закрытого ключей.Затем большой случайный секрет используется в качестве начального числа для ключа AES, ключа iv и mac.Открытый текст зашифрован и аутентифицирован.Наконец, семя зашифровано под открытым ключом пользователя.Пароль все еще используется, но он используется для расшифровки закрытого ключа.