2016-07-30 3 views
2
에서 페이로드를 디코딩 한 후 동일한 세션 키를 얻는하지

내가 인코딩 후 동일한 세션 키를 받고 암호를 사용하는 기능보다 사용하여 디코딩하고 있지 않다 ++ 라이브러리 : 192 바이트의는 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; 
} 

미행 원본과 일치되지 않아요 세션 키의 바이트

이 문제에 대해 도움을 줄 수 있습니까?

미리 감사드립니다.

+0

씨크립자를 사용하여 시드 크기를 결정하는 대답이 업데이트되었습니다. 나는'RSAPublicKey :: MaxImage()'가'RSAES < OAEP> :: Encryptor :: FixedMaxPlaintextLength()'보다 크기가 크다고 믿는다. 클라이언트와 서버 모두에서'seed.resize' 다음에 시드 바이트를 사용했다면 문제가 발생하지 않을 것입니다. – jww

답변

0

나는 인코딩 후 동일한 세션 키를 받고 기능

난 당신이 당신이 필요에 가까운 생각

이하로 사용하여 디코딩하고 있지 않다. 또한 당신이하는 방식에 개선의 기회가 있습니다. 개선 된 방법을 보여 드리며 기존 방법에도 적용 할 수 있습니다.

향상된 방법은 단순히 FixedMaxPlaintextLength, CiphertextLength 및 일부 친구를 사용하여 크기를 결정합니다. 또한 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 

피어 암호화 시드 블록을 수신하면, 그들이 해독한다. 방법은 다음과 같습니다.


당신은 암호화 또는 AES 암호 해독 할

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); 
, 당신은 키, IV 및 아마도 HMAC을 유도해야합니다 result.isValidCoding 반환 false이 경우

// 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); 

는 당신은 예외를 던져 수 키 (데이터를 인증하고 있습니까?). 당신이 당신의 데이터를 인증

// 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)); 

경우 다음과 HMAC 키를 유도 할 수있다.

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 : 그러나 일반적으로, 당신은 아마 작업의 Authenticated Encryption 모드를 사용해야합니다. 가지고 있지 않은 경우 hkdf.hWei Dai's GitHub (헤더 전용)에서 가져옵니다. 고유 한 레이블을 가진 기본 시드에서 파생함으로써 독립 유도라는 기술을 사용하고 있습니다.

Attacking and Repairing the WinZip Encryption Scheme에서 논의 된 것과 같은 간격을 피하기 위해 레이블과 버전 정보를 추가합니다. 또한 전체 FixedMaxPlaintextLength 쪽을 사용하여 메시지 길이와 관련된 일부 암호화 공격을 수행합니다.


Integrated Encryption Schemes (IES)을보고 싶을 수도 있습니다. 기본적으로 IES에서 Key Encapsulation Mechanism (KEM)을 해제했습니다. 데이터 캡슐화 메커니즘 (DEM)도 해제 될 수 있습니다.

KEM과 DEM을 빌리려면이 구성표를 사용할 수 있습니다. 이를 위해, 상기 암호화 ++ 위키 다음을 참조하십시오

  • Discrete Logarithm Integrated Encryption Scheme
  • 당신이 통합 암호화 구성표 중 하나를 사용하는 경우

    • Elliptic Curve Integrated Encryption Scheme
    • 는, 당신은 기본 수학 문제 변경됩니다. RSA는 소인수 분해입니다 ( IF), IES는 디피 - 헬만과 이산 로그 ( FF)된다.

      통합 암호화 체계를 사용하는 것이 좋습니다. 그것의 IND-CCA2은 매우 강력한 보안 개념입니다. 나는 당신의 본래 계획보다는 더 나은 안전 재산이다는 것을 믿는다.

    +0

    단계를 수행 한 후 세션 키 해독시이 예외가 발생합니다. ----------> 예외 발생 : NullRNG : 임의의 바이트를 생성 할 필요가없는 함수에만 NullRNG를 전달해야합니다. – user3752324

    +0

    감사합니다. – user3752324