2016-07-30 29 views
2
下進行解碼的有效載荷之後

我沒有編碼後得到相同的會話密鑰,並使用下面的功能,它使用密碼譯碼它++庫:沒有得到相同的會話密鑰的RSA

CryptoPP::RSA::PrivateKey RSA_master_privKey; 
CryptoPP::RSA::PublicKey RSA_master_pubKey; 

std::string generate_Master_Keys() 
{ 
    std::string rsaParams; 
    try { 
     CryptoPP::InvertibleRSAFunction parameters; 
     RSA_master_privKey = CryptoPP::RSA::PrivateKey(parameters); 
     RSA_master_pubKey = CryptoPP::RSA::PublicKey(parameters); 
    } 
    catch (const CryptoPP::Exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
     b_success = false; 
    } 
    return rsaParams; 
} 

PAES_KEY_WITH_IV create_session_key(void) 
{ 
    CryptoPP::AutoSeededX917RNG<CryptoPP::AES> rng; 
    PAES_KEY_WITH_IV aes_info = new AES_KEY_WITH_IV; 
    try { 
     aes_info->key.resize(CryptoPP::AES::DEFAULT_KEYLENGTH); 
     rng.GenerateBlock(aes_info->key, aes_info->key.size()); 
     aes_info->iv.resize(CryptoPP::AES::BLOCKSIZE); 
     rng.GenerateBlock(&aes_info->iv[0], aes_info->iv.size()); 
    } 
    catch (const CryptoPP::Exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
     b_success = false; 
    } 
    return (aes_info); 
} 

std::string encrypt_session_key(PAES_KEY_WITH_IV pKey) 
{ 
    std::string ciphered; 
    CryptoPP::SecByteBlock block(pKey->key.size()); 
    try { 
     CryptoPP::RSAES< CryptoPP::OAEP<CryptoPP::SHA> >::Encryptor enc(RSA_master_pubKey); 
     enc.Encrypt(rng, pKey->key, pKey->key.size(), block); 
     ciphered.assign((char *)block.BytePtr(), 192); 
    } 
    catch (const CryptoPP::Exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
     b_success = false; 
    } 
    return ciphered; 
} 

PAES_KEY_WITH_IV decrypt_session_key(std::string & ciphered) 
{ 
    CryptoPP::SecByteBlock rec(ciphered.size()); 
    CryptoPP::SecByteBlock block((const byte *)ciphered.data(), ciphered.size()); 
    PAES_KEY_WITH_IV pKey = new AES_KEY_WITH_IV; 
    try { 
     CryptoPP::RSAES< CryptoPP::OAEP<CryptoPP::SHA> >::Decryptor dec(RSA_master_privKey); 
     dec.Decrypt(rng, block, block.size(), rec); 

     pKey->key = rec; 
    } 
    catch (const CryptoPP::Exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
     b_success = false; 
    } 
    return pKey; 
} 

192個字節尾礦沒有得到與原始匹配會話密鑰的字節。

有人可以幫我嗎?

在此先感謝。

+0

我更新了使用Encryptor確定種子大小的答案。我相信'RSAPublicKey :: MaxImage()'會大於'RSAES < OAEP> :: Encryptor :: FixedMaxPlaintextLength()',它可能遭受無聲截斷。如果您在客戶端和服務器上的'seed.resize'之後使用了種子字節,那麼您就不會遇到問題。 – jww

回答

0

我沒有得到編碼後相同的會話密鑰,並使用以下功能

我覺得你接近你所需要的對其進行解碼。這樣做也有改進的機會。我會告訴你改進的方法,你也可以將它應用到現有的方法中。

改進的方法只是簡單地使用FixedMaxPlaintextLengthCiphertextLength和一些朋友來確定尺寸。它也使用Integrated Encryption Schemes (IES)的技術。

首先,傳輸原始種子字節,而不是{key, iv}對。然後,當您需要{key, iv}對時,您可以從種子字節中獲取所需的字節。您的派生應該包含使用標籤和版本號。

其次,未解決的問題:您作爲種子字節傳輸了多少個字節。那答案是FixedMaxPlaintextLength()MaxPreimage()(我不記得是哪個)。這是可以在該方案下加密的明文的大小,並且取決於諸如模數大小和填充方案之類的事情。

下面的許多代碼在RSA Encryption Schemes和Crypto ++ wiki上的其他地方討論過。但是,由於您仍然在學習一些技巧,因此您不需要訪問它們。


下面生成一個隨機種子,並在公共密鑰下進行加密。

RSA_master_pubKey = RSA::PublicKey(parameters); 
RSAES< OAEP<SHA> >::Encryptor enc(RSA_master_pubKey); 
SecByteBlock seed(enc.FixedMaxPlaintextLength()); 

AutoSeededX917RNG<AES> rng; 
rng.GenerateBlock(seed, seed.size()); 

SecByteBlock block(enc.CiphertextLength(seed.size())));  
size_t req = enc.Encrypt(rng, seed, seed.size(), block); 
block.resize(req); 

// Transport block to peer as session seed 

當對端接收加密的種子塊,它們必須進行解密。以下是如何做到這一點。

// Received from peer 
SecByteBlock block(...); 

RSAES< OAEP<SHA> >::Decryptor dec(RSA_master_privKey); 
size_t req = dec.MaxPlaintextLength(block.size()); 

SecByteBlock seed(req); 
DecodingResult result = dec.Decrypt(rng, block, block.size(), seed); 
seed.resize(result.isValidCoding ? result.messageLength : 0); 

你甚至可以拋出一個異常,如果result.isValidCoding回報false

DecodingResult result = dec.Decrypt(rng, block, block.size(), seed); 
if (!result.isValidCoding) 
    throw Exception(OTHER_ERROR, "Failed to decrypt seed bytes"); 

seed.resize(result.messageLength); 

當您要加密或AES解密,你需要導出密鑰,IV和可能的HMAC鍵(你是否認證數據?)。

// Random seed from above 
SecByteBlock seed; 

HKDF<SHA256> kdf; 
SecByteBlock aesKey(AES::DEFAULT_KEYLENGTH); 
SecByteBlock aesIV(AES::BLOCKSIZE); 

const byte aesLabel[] = "AES encryption key, version 1"; 
kdf.Derive(aesKey, aesKey.size(), seed, seed.size(), NULL, 0, aesLabel, COUNTOF(aesLabel)); 

const byte ivLabel[] = "AES initialization vector, version 1"; 
kdf.Derive(aesIV, aesIV.size(), seed, seed.size(), NULL, 0, ivLabel, COUNTOF(ivLabel)); 

IF您驗證您的數據,那麼你就可以得到與以下HMAC密鑰。但一般來說,你應該使用Authenticated Encryption操作模式:

const byte hmacLabel[] = "HMAC authentication key, version 1"; 
kdf.Derive(hmacKey, hmacKey.size(), seed, seed.size(), NULL, 0, hmacLabel, COUNTOF(hmacLabel)); 

HKDF was added at 5.6.3 or 5.6.4。如果你沒有它,那麼從Wei Dai's GitHub(僅限其標題)抓取hkdf.h。通過從具有獨特標籤的基礎種子派生而來,您正在使用一種稱爲獨立派生的技術。

您可以添加標籤和版本信息以避免在Attacking and Repairing the WinZip Encryption Scheme中討論的差距。另外,使用整個FixedMaxPlaintextLength旁邊的步驟來處理與消息長度有關的一些加密攻擊。


你可能也想看看Integrated Encryption Schemes (IES)。我們基本上從IES中解除了密鑰封裝機制(KEM)。還有一個數據封裝機制(DEM)可以被解除。

如果你打算借用KEM和DEM,那麼你也可以使用這個方案。爲此,請參閱加密+維基如下:

如果使用集成加密方案中的一種,那麼你就改變了基本的數學問題。 RSA是整數分解(IF),而是IES的Diffie-Hellman和離散日誌(FF)。

使用集成加密方案是一個不錯的選擇。它的IND-CCA2,這是一個非常強大的安全概念。我相信它比你原來的方案有更好的安全屬性。

+0

按照你的步驟,我解密會話密鑰得到這個異常。 ---------->發生異常:NullRNG:NullRNG應該只傳遞給不需要生成隨機字節的函數 – user3752324

+0

感謝從你的評論中解決 – user3752324