Search code examples
c++cryptographycrypto++

String to SecByteBlock Conversion Issues


I'm having an issue with allocating a new key for 3 key Triple DES in crypto++.

I've generated a new key as a string but need to allocate it to SecByteBlock for use in Crypto++.

Currently I generate a random key using the PRNG at the start, but when I attempt to change the key using string output from DES_EDE3, it appears to use the same key.

I think the issue is with the conversion between string and SecByteBlock, or the allocation to SecByteBlock as shown below.

Any help would be greatly appreciated!

SecByteBlock GENERATOR::setKey(string keyString){

    SecByteBlock replacementKey(24);

    replacementKey= SecByteBlock(reinterpret_cast<const byte*>(keyString.data()), keyString.size());
    return newKey = replacementKey;
}

Solution

  • I attempt to change the key using string output from DES_EDE3, it appears to use the same key

    It almost sounds like you are trying to use 3-DES as a PRF keyed with a password. If so, use HKDF. Its designed for these types of expand-then extract operations.

    HKDF is available in Crypto++ 5.6.3 and above. If you need it for a downlevel client, then copy the header where you need it.


    SecByteBlock GENERATOR::setKey(string keyString){
    
        SecByteBlock replacementKey(24);
    
        replacementKey= SecByteBlock(reinterpret_cast<const byte*>(keyString.data()), keyString.size());
        return newKey = replacementKey;
    }
    

    Though you size replacementKey to 24, it could be resized by the assignment replacementKey= SecByteBlock(...).

    You might want to try the following:

    SecByteBlock GENERATOR::setKey(const string& keyString)
    {    
        SecByteBlock key((const byte*)keyString.data(), keyString.size());
    
        if(key,size() < DES_EDE3::KEYLENGTH)
            key.CleanGrow(DES_EDE3::KEYLENGTH);
        else
            key.resize(DES_EDE3::KEYLENGTH);
    
        return key;
    }
    

    CleanGrow sizes the memory block to DES_EDE3::KEYLENGTH and backfills the block with 0's as needed. resize will truncate to DES_EDE3::KEYLENGTH if its too large.

    You could also do something like:

    SecByteBlock key(DES_EDE3::KEYLENGTH);
    size_t s = STDMIN(key.size(), keyString.size());
    
    memcpy(key.data(), keyString.data(), s);
    if(s < DES_EDE3::KEYLENGTH)
        memset(key.data()+s, 0, DES_EDE3::KEYLENGTH-s);
    

    -----

    To combine the first two, you might consider this:

    SecByteBlock GENERATOR::setKey(const string& keyString)
    {
        // Block is unintialized
        SecByteBlock key(DES_EDE3::KEYLENGTH);
    
        HKDF<SHA256> kdf;
        kdf.Derivekey(key.data(), key.size(), (const byte*)keyString.data(), keyString.size(), NULL, 0);
    
        return key;
    }
    

    -----

    You can output a SecByteBlock with code like:

    SecByteBlock b = GENERATOR::setKey(...);
    ...
    
    cout << "Derived key: "
    ArraySource as(b.data(), b.size(), true, new HexEncoder(new FileSink(cout)));
    cout << endl;
    

    The following with encode it using Base64:

    ArraySource as(b.data(), b.size(), true, new Base64Encoder(new FileSink(cout)));