1

When using DefaultEncryptorWithMAC in CryptoPP at it's heart it seems to use this Mash Function

// The purpose of this function Mash() is to take an arbitrary length input
// string and *deterministicly* produce an arbitrary length output string such
// that (1) it looks random, (2) no information about the input is
// deducible from it, and (3) it contains as much entropy as it can hold, or
// the amount of entropy in the input string, whichever is smaller.

static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
{
    if (BytePrecision(outLen) > 2)
        throw InvalidArgument("Mash: output legnth too large");

    size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
    byte b[2];
    SecByteBlock buf(bufSize);
    SecByteBlock outBuf(bufSize);
    DefaultHashModule hash;

    unsigned int i;
    for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
    {
        b[0] = (byte) (i >> 8);
        b[1] = (byte) i;
        hash.Update(b, 2);
        hash.Update(in, inLen);
        hash.Final(outBuf+i);
    }

    while (iterations-- > 1)
    {
        memcpy(buf, outBuf, bufSize);
        for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
        {
            b[0] = (byte) (i >> 8);
            b[1] = (byte) i;
            hash.Update(b, 2);
            hash.Update(buf, bufSize);
            hash.Final(outBuf+i);
        }
    }

    memcpy(out, outBuf, outLen);
}

According to this page http://www.cryptopp.com/wiki/DefaultEncryptorWithMAC

DefaultEncryptorWithMAC uses 2-key Triple DES as the default encryptor, and SHA1 as the default hash for the MAC. The block cipher is operated in CBC Mode. The password is mashed rather than derived using a Password Based Key Derivation Function. Each run through the DefaultEncryptorWithMAC produces a different result due to the use of a salt based on time and clock.

I'm trying to read this encrypted string with another library and am really struggling ie do the equivalent operation of DefaultDecryptorWithMAC (http://www.cryptopp.com/wiki/DefaultDecryptorWithMAC)

If I put my secret key through and online SHA1 encrypted I don't get the same result as the Mash function above ?

According to the above webpage it seems to suggest it's using standard encryption techiques I have been unable to decry-pt the result with anything else

Hopefully someone here has experience decrypting the result of these function from this library

Thanks in advance

jww
  • 97,681
  • 90
  • 411
  • 885
user3173234
  • 11
  • 1
  • 5
  • Thanks for the reply. I'm trying to use the Chilkat library (http://www.chilkatsoft.com/refdoc/xChilkatCrypt2Ref.html) to be able to read something encrypted with DefaultEncryptorWithMAC But although I obviously know the secret key the whole salt/clock/mashing thing is making it almost impossible for me to decrypt a string that has been encrypted with the above method. Is there any pseudo code of the algorithm for mash and the rest of DefaultEncryptorWithMAC anywhere ? – user3173234 Dec 12 '14 at 13:03
  • As a compliment to the author, this already reads as pseudo code to me. I therefore retracted my earlier comment. Maybe you could just step through the code using a debugger and try to replicate it using chilkat? If you get stuck you could post here again. Currently it is unclear what you are asking (appart from sample code, which is off topic). – Maarten Bodewes Dec 12 '14 at 13:16
  • "Maybe you could just step through the code using a debugger and try to replicate it using chilkat?" That's what i'm trying to do but i'm not really a c++ developer. ie it's not my first language. What am I trying to do at a top level ? take the result of this `encryptor = new DefaultEncryptorWithMAC(passphrase, new Base64Encoder(new StringSink(ls), false));' and only knowing that and the passphrase in effect be able to do this `decryptor = new Base64Decoder(new DefaultDecryptorWithMAC(passphrase, new StringSink(ls)));` to get back the original string – user3173234 Dec 12 '14 at 13:26
  • Perhaps someone here would be kind enough to give me a leg up using the above chilkat link and perhaps this one http://www.example-code.com/cpp/encryption.asp that shows various C++ encryption examples using their library to decrypt a string created with DefaultEncryptorWithMAC and I could then convert it into the specialist language i'm using (Dataflex) – user3173234 Dec 12 '14 at 13:42

1 Answers1

0

From the comments:

I obviously know the secret key the whole salt/clock/mashing thing is making it almost impossible for me to decrypt a string that has been encrypted with the above method.

If you look at the code for DefaultEncryptorWithMAC (h file and cpp file), you will see that the output has more stuff than just the data encrypted under a mashed password. So its not enough to derive the "secret key" in the mash function and key the DES_EDE2 cipher and operate it in CBC mode.

Looking at the function DefaultEncryptor::FirstPut (which inherits from ProxyFilter) on line 83, there is preamble written. The preamble is the salt and a key check. So the layout of the encrypted data is:

[SALT][KEYCHECK][ENCRYPTED DATA]

SALT is calculated based on DefaultHashModule::DIGESTSIZE; but only 8 bytes is written. Then, the KEYCHECK is calculated based on DefaultHashModule::DIGESTSIZE; but only Default_BlockCipher::Encryption::BLOCKSIZE is written.

When it comes time to decrypt, you strip off the salt and use it to re-derive the IV. You strip off the key check and validate the key you derived. Then you key a decryptor with the derived key and iv.

jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks _very_ much for your detailed reply. I can see the `Default_BlockCipher::Encryption::BLOCKSIZE` is 8 and `DefaultHashModule::DIGESTSIZE` is 20. Having taken the first 8 chars of the encrypted string (salt) what process do I use to get to the IV ? Should the result of this match the next 20 chars of the encrypted string in some way ? Do I then pass the IV and my secret key to a DES_EDE2 process to decrypt the final portion of the string ? Thanks again jww – user3173234 Dec 15 '14 at 09:47
  • I've been trying my hardest with this and have made some good progress but am now stuck. The DefaultDecryptor::CheckKey in the above cpp file is what i've been trying to match and I have successfully got the same values in my own code for salt, keycheck, check, key, IV. The bit I am stuck with is this bit of code ` decryptor->Put(keyCheck, BLOCKSIZE); decryptor->ForceNextPut(); decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);` I can't see what it does to the keycheck value in the Put ? also the Get appears just to copy one part of the string withing itself and then check it is the same ?? TIA – user3173234 Jan 07 '15 at 14:07
  • OK I'm almost,almost there I can now decrypt a string that was encoded with Crypto++ However I can't quite create a string that can be decrypted using Crypto++. The problem is [ENCRYPTED DATA] as referred to above has what looks like an SHA-1 hash of something as it's last 20 bytes. If i'm decoding I just ignore it but obviously CP++ must be checking it in someway as it gives me an error. After a couple of educated guesses as to how those last 20 bytes are calculated I still can't get it to work. Hopefully someone can help me to nudge me over the finishing line ! Thanks very much in advance – user3173234 Jan 08 '15 at 15:45
  • Please note I'm not talking about [KEYCHECK] above which I have successfully calculated and have working. Thanks again – user3173234 Jan 08 '15 at 15:46
  • It appears that it (this magic last 20 chars value) involves the secret key and the base data you wish to encrypt (as you would expect!) but it can't involve the salt etc random values as it is always the same. I've tried many SHA-1 combinations of just the secret key as the HMAC, the first 16 of the single mashed secret as the HMAC etc but as yet can't find the combination that matches with what DefaultEncryptorWithMAC does. I really need to get over the finish line on this one so any help would be greatly appreciated. Thanks – user3173234 Jan 12 '15 at 14:03
  • OK cracked it. The last 20 chars are HMAC SHA-1 hash of the original value you want to encode where the HMAC is the first 16 of a single mashed version of the secret key. The Mash function can be seen in the Crypto++ source – user3173234 Jan 13 '15 at 13:31