如果我想加密數據,使用Crypto ++庫並且用戶定義的密碼短於32字節,該怎麼辦?
使用密鑰導出函數(KDF)來消化密碼。現代的是Krawczyk和Eronen的HKDF,使用Extract-then-Expand模型。該論文位於Cryptographic Extraction and Key Derivation: The HKDF Scheme。
您應該考慮將它用於IV。而不是派生32個字節(AES::MAX_KEYLENGTH
),而是派生48個字節(AES::MAX_KEYLENGTH+AES::BLOCKSIZE
)。然後,您的設計中的IV可用於KDF的salt
參數。
也許是這樣的:
#include <iostream>
#include <string>
using namespace std;
#include "cryptlib.h"
#include "aes.h"
#include "sha.h"
#include "hkdf.h"
#include "modes.h"
#include "filters.h"
using namespace CryptoPP;
int main(int argc, char* argv[])
{
SecByteBlock key(AES::MAX_KEYLENGTH+AES::BLOCKSIZE);
string password("passwordFromUser"), iv("<random value>"), message("encryptMe");
string encrypted, recovered;
try
{
HKDF<SHA256> hkdf;
hkdf.DeriveKey(key, key.size(), (const byte*)password.data(), password.size(), (const byte*)iv.data(), iv.size(), NULL, 0);
///////////////////////////////////////////////////////////////////////
CTR_Mode<AES>::Encryption encryption;
encryption.SetKeyWithIV(key, AES::MAX_KEYLENGTH, key+AES::MAX_KEYLENGTH);
StringSource encryptor(message, true,
new StreamTransformationFilter(encryption,
new StringSink(encrypted))
);
///////////////////////////////////////////////////////////////////////
CTR_Mode<AES>::Decryption decryption;
decryption.SetKeyWithIV(key, AES::MAX_KEYLENGTH, key+AES::MAX_KEYLENGTH);
StringSource decryptor(encrypted, true,
new StreamTransformationFilter(decryption,
new StringSink(recovered))
);
cout << "Message: " << message << endl;
cout << "Recovered: " << recovered << endl;
}
catch(const Exception& ex)
{
cerr << ex.what() << endl;
return 1;
}
return 0;
}
當使用上述的加密方法,你必須追蹤{iv,message}
對。由於密碼有效地修復了AES密鑰,因此需要使用IV來確保每條消息的唯一性。
如果什麼用戶選擇的密碼長度超過32字節?在我的情況下,密碼會被截斷,這聽起來並不正確。
KDF爲您處理它。無論多少或多少,它都會提取熵。
StringSource encryptor(textToEncrypt, true,
new StreamTransformationFilter(encryption,
new StringSink(verschluesselterText),
StreamTransformationFilter::NO_PADDING
)
沒有必要指定填充模式。另請參閱BlockPaddingScheme的文檔。
你應該非常小心CTR模式。 CTR模式異或是純文本的密鑰流。如果有人在不同的消息上重用他們的密碼,那麼它可能恢復導致明文恢復的密鑰流。
如果ivText
對於每條消息都是唯一的,那麼您應該將其添加到您的KDF以確保每條消息具有唯一的密鑰流。添加IV作爲HKDF的salt
參數。這裏,「唯一」表示如果我有一條消息「Hello World」,那麼每次我加密消息時IV都不同。
如果 IV確實只是「Iv16BytesOfText ...」(即它的固定值),那麼就沒有什麼特別的了。只需從用戶密碼中獲取額外的16個字節。然後,爲了避免密鑰流xor攻擊,切換到CBC等模式。
最後,您應該使用CCM,EAX或GCM模式。現在,你只有保密。通常你也想要真實性。爲了獲得真實性,您經常選擇Authenticated Encryption操作模式。
你是如何解決這個問題的? – jww