17943

Not getting same session key after decoding payload under RSA

I am not getting same session key after encoding and decoding it using below functions which uses crypto++ library:

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; }

Tailing of 192 bytes are not getting matched with original session key's bytes.

Can some one help me on this ?

Thanks in advance.

Answer1:

I am not getting same session key after encoding and decoding it using below functions

I think you are close to what you need. There's also an opportunity for improvement in the way you are doing it. I'll show you the improved way, and you can apply it to the existing method as well.

The improved way simply uses FixedMaxPlaintextLength, CiphertextLength and some friends to determine sizes. It also uses a technique from Integrated Encryption Schemes (IES).

First, transport the raw seed bytes, and not the {key, iv} pair. Then, when you need the {key, iv} pair, you derive the bytes you need from the seed bytes. Your derivation should include a usage label and a version number.

Second, the open question: how many bytes do you transport as seed bytes. That answer is FixedMaxPlaintextLength() or MaxPreimage() (I don't recall which). That's the size of the plaintext that can be encrypted under the scheme, and it depends on things like the modulus size and the padding scheme.

A lot of the code below is discussed at RSA Encryption Schemes and other places on the Crypto++ wiki. But its not readily apparent you need to visit them because you are still learning some of the techniques.

<hr>

The following generates a random seed and encrypts it under the public key.

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 <hr>

When the peer receives the encrypted seed block, they must decrypt it. Here's how to do it.

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

You could even thrown an exception if result.isValidCoding returns 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); <hr>

When you want to encrypt or decrypt with AES, you need to derive a key, iv and possibly an hmac key (are you authenticating the data?).

// 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 you authenticate your data, then you can derive an HMAC key with the following. But generally speaking, you should probably use an Authenticated Encryption mode of operation:

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. If you don't have it, then grab hkdf.h from Wei Dai's GitHub (its header-only). By deriving from a base seed with unique labels, you are using a technique called independent derivation.

You add the labels and the version information to avoid gaps like discussed in Attacking and Repairing the WinZip Encryption Scheme. Also, using the entire FixedMaxPlaintextLength side steps some cryptographic attacks related to message length.

<hr>

You might also want to look at Integrated Encryption Schemes (IES). We basically lifted the Key Encapsulation Mechanism (KEM) from IES. There's a Data Encapsulation Mechanism (DEM) that could be lifted, too.

If you are going to borrow the KEM and the DEM, then you may as well use the scheme. For that, see the following on the Crypto++ wiki:

    <li>Elliptic Curve Integrated Encryption Scheme</li> <li>Discrete Logarithm Integrated Encryption Scheme</li> </ul>

    If you use one of the Integrated Encryption Schemes, then you are changing the underlying mathematical problem. RSA is Integer Factorization (<strong>IF</strong>), while IES is Diffie-Hellman and Discrete Logs (<strong>FF</strong>).

    Using an Integrated Encryption Scheme is a good choice. Its IND-CCA2, which is a very strong notion of security. I believe it has better security properties than your original scheme.

Recommend

  • Vim key mapping works in command editor, not in .vimrc - why?
  • Permissions error when using cli in Jboss wildfly and docker
  • Python script in a browser
  • Why use CDN(Content Delivery Network‎)? [duplicate]
  • applying background to first, and every third row in a dynamically generated table
  • Looking for datastructure that maintains a size & purges older elements in the process
  • Is there any kind of jQuery.browser fallback?
  • How ignore any files using HHVM proxygen rewrite rules?
  • Linq to SQL left outer join using Lambda syntax and joining on 2 columns (composite join key)
  • Is it ok to submit a build to the app store for testing when a previous build is waiting for review?
  • ZF2 Event before not_found_template
  • Acts as Tree with Multiple Models
  • How to prompt user that edits have been made upon changing pages or sorting in Kendo Grid
  • Aspect advising other aspects
  • SQL Server Like Query not case sensitive
  • Select count of rows that have a certain number of rows in a related table
  • Price range slider for my website
  • Positioning children objects in scene (car wheels hierarchy)
  • AWS-SES: Handling Bounces for Invalid ISPs
  • Is there a Windows socket API call / option to “block” a range of ports à la SO_EXCLUSIVEADDRUSE
  • How to turn (A, B, C) into (AB, AC, BC) with Pig?
  • jQuery - resize an elements height to match window without refreshing, on window resize
  • apply a javascript function to draggable copy
  • Yii2: Finding file and getting path in a directory tree
  • Android changing fragment order inside FragmentPagerAdapter
  • WPF ICommand CanExecute(): RaiseCanExecuteChanged() or automatic handling via DispatchTimer?
  • How solve “Qt: Untested Windows version 10.0 detected!”
  • Reduction and collapse clauses in OMP have some confusing points
  • Create DicomImage from scratch using Dcmtk
  • Groovy: Unexpected token “:”
  • MongoDb aggregation
  • How to use remove-erase idiom for removing empty vectors in a vector?
  • Spring security and special characters
  • Javascript Callbacks with Object constructor
  • Trying to switch camera back to front but getting exception
  • How can I use Kendo UI with Razor?
  • WPF Applying a trigger on binding failure
  • Free memory of cv::Mat loaded using FileStorage API
  • Angular 2 constructor injection vs direct access
  • Programmatically clearing map cache