AES Problem

66 views
Skip to first unread message

Robert F.

unread,
Mar 18, 2011, 10:24:45 PM3/18/11
to cryptop...@googlegroups.com

Hello, I'm having some AES encryption/decryption problems. The issue comes
into play with certian IV's.

My IV's are completely randomized for security, however, I'm not sure If I'm
loading them in/out correctly.

I get the: StreamTransformationFilter: ciphertext length is not a multiple
of block size error.


CODE:

int xxz568::AESEncrypt(std::string key, std::string input, std::string
&output) {
byte keyB[32], ivB[AES::BLOCKSIZE];
std::string hashKey = sha1(key).substr(0, 32);
memcpy(keyB, hashKey.c_str(), 32);
//
memcpy(ivB, generateRandLen(), 16);
//
std::string hold, final, hexVec, decVec;
HexEncode((const char *)ivB, hexVec);
cout << "IV: " << ivB << " | " << hexVec << endl;
output = hexVec.substr(0, 32);
//convert output back to binary for usage as the initVector
HexDecode(output, decVec);
//store dec Vec in the iv slot
memcpy(ivB, decVec.c_str(), 16);
StringSink* sink = new StringSink(hold);
CBC_Mode<AES>::Encryption aes(keyB, sizeof(keyB), ivB);
StreamTransformationFilter* aes_enc = new StreamTransformationFilter(aes,
sink);
StringSource cipher(input, true, aes_enc);
//convert to a hash
HexEncode(hold, final);
output += final;
//
return 1;
}

int xxz568::AESDecrypt(std::string key, std::string input, std::string
&output) {
std::string bin, store2, init, test;
HexDecode(input, bin);
cout << "DEC: " << bin << endl;
try{
byte keyB[32], iv[AES::BLOCKSIZE];
std::string hashKey = sha1(key).substr(0, 32);
memcpy(keyB, hashKey.c_str(), 32);
//obtain IV
init.assign(bin.substr(0, 16));
memcpy(iv, init.c_str(), 16);
HexEncode(init, test);
store2.assign(bin.substr(16, bin.length()));
cout << "IV: " << init << " | " << test << endl;
//
StringSink* sink = new StringSink(output);
CBC_Mode<AES>::Decryption aes(keyB, sizeof(keyB), iv);
StreamTransformationFilter* aes_enc = new
StreamTransformationFilter(aes, sink);
StringSource cipher(store2, true, aes_enc);
}
catch(CryptoPP::Exception e) {
cout << e.GetWhat() << endl;
output = "Decrypt Error:";
output.append(e.GetWhat());
}
return 1;
}

byte * xxz568::generateRandLen() {
AutoSeededRandomPool rng;
byte randLen[16];
rng.GenerateBlock(randLen, 16);
//
return randLen;
}

int xxz568::HexEncode(std::string input, std::string &output) {
CryptoPP::StringSource foo(input, true,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(output), false));
return 1;
}

int xxz568::HexDecode(std::string input, std::string &output) {
CryptoPP::StringSource foo(input, true,
new CryptoPP::HexDecoder(
new CryptoPP::StringSink(output)));
return 1;
}
--
View this message in context: http://old.nabble.com/AES-Problem-tp31186698p31186698.html
Sent from the Crypto++ Users mailing list archive at Nabble.com.

Geoff Beier

unread,
Mar 18, 2011, 11:49:03 PM3/18/11
to Robert F., cryptop...@googlegroups.com
Note: This is just based on squinting at your code for a few seconds.
I didn't try to compile it.

1. It looks as though you might be using a truncated SHA1 hash of a
password as an AES key. That's a serious security hole and there's no
good reason to do that. Please use a PBKDF. If I'm reading this wrong
or you don't understand this comment, please reply with an explanation
of what you're doing, because I don't understand your code and all my
commentary is likely off the mark.

2. Don't hex decode into a string unless what was encoded was a proper
string to begin with. If i'm reading your code right, I'd predict that
any time one of your randomly generated IV bytes is a zero, you're
getting uninitialized memory in your IV and (possibly) failing. It's
not a lock that you'll fail every time, but I'd suspect that every
time you fail there's a zero in that buffer.

For the sake of illustration, let's imagine a 4-byte random IV:

// unsigned char[] ivB = { 0xba, 0xdf, 0x00, 0x0d};
HexEncode((const char *)ivB, hexVec);
// hexVec = "badf00d";
HedDecode(hexVec,decVec)
// decVec = "ºß";
// the bytes in decVec will be {0xba, 0xdf, 0x00, UNDEFINED}
// because 0x00 is the terminator for an ASCII string
memcpy(ivB,decVec.c_str(),4);
// ivB will now be {0xba, 0xdf, 0x00, 0x??} where ?? comes from
whatever uninitialized memory was there after the internal
representation. Ideally, this should crash, but that's probabilistic,
not deterministic.

Hope this helps,

Geoff

Robert F.

unread,
Mar 19, 2011, 9:48:42 PM3/19/11
to cryptop...@googlegroups.com

The purpose of using the trimmed sha1 is because the key is defined by the
user, I'm using the AES algo for username/password purposes.

I'm not quite sure what is meant in #1, can you provide an example?

As for #2, all data output must be in hex, ASCII is not allowed by the
program. So, how would I go about fixing this to be correct? Would usage of
Base64 Encoding over the IV/String work? because B64 is acceptable.
--
View this message in context: http://old.nabble.com/AES-Problem-tp31186698p31192117.html

Geoff Beier

unread,
Mar 20, 2011, 7:52:38 PM3/20/11
to Robert F., cryptop...@googlegroups.com
On Sat, Mar 19, 2011 at 21:48, Robert F. <rfri...@phantomdev.net> wrote:
>
> The purpose of using the trimmed sha1 is because the key is defined by the
> user, I'm using the AES algo for username/password purposes.
>
I suggest that you carefully examine the set of assumptions that lead
you from "the key is defined by the user" to "I should use a truncated
sha-1 hash of the user-defined key as my AES key." Nothing about the
key being defined by the user makes what you're doing necessary :-).

> I'm not quite sure what is meant in #1, can you provide an example?
>

I'm on a mobile at the moment and it's too cumbersome for me to
search, copy and paste. Just grep -i pbkdf validat*.cpp within the
crypto++ source distribution. You'll find an example of using one.

> As for #2, all data output must be in hex, ASCII is not allowed by the
> program. So, how would I go about fixing this to be correct? Would usage of
> Base64 Encoding over the IV/String work? because B64 is acceptable.

It doesn't matter how you encode the output or IV. Encode them in
whatever way is suitable for your transport. That's not the problem.
The problem is decoding them into string types that aren't meant to
hold arbitrary binary data. (Sorry... I thought my commented snippet
illustrated that.) Decode them into an array of bytes instead. The
SecByteBlock type in crypto++ should be convenient for this kind of
thing.

Good luck.

Geoff

Robert F.

unread,
Mar 22, 2011, 9:23:50 PM3/22/11
to cryptop...@googlegroups.com

I understand what you're saying for #2 now, the hexEncoding of the IV works
fine, it's just the decoding that causing the problems when it hits 0x00.

So, I need to know how to use my current hexDecode function to instead of
outputting to a std::String, to be a CryptoPP::SecByteBlock, how can I
adjust my current code to fit this?

I've never used a PBKDF before, nor can find anything in the validat# files
to help me, is there any sample code out there that can help me do so,
keeping in mind that AES-256 requires the 32 bit key length.
--
View this message in context: http://old.nabble.com/AES-Problem-tp31186698p31216023.html

Robert F.

unread,
Mar 23, 2011, 5:43:38 PM3/23/11
to cryptop...@googlegroups.com

Updated this program, but now it's worse. All decryptions fail with the first
error mentioned, I have not yet implemented the PBKDF due to the fact that I
have no idea where to start on it, but I have tried to switch the hexDecode
into a byte loading process, yet encryption is failing again. I think It's
probably a stupid mistake of mine, but I can't seem to find it. Encryption
function has not changed.


int xxz568::AESDecrypt(std::string key, std::string input, std::string
&output) {

std::string store2, init, hexDec;
CryptoPP::SecByteBlock test;
test.Grow(16);
try{
byte keyB[32];


std::string hashKey = sha1(key).substr(0, 32);
memcpy(keyB, hashKey.c_str(), 32);
//obtain IV

init.assign(input.substr(0, 16));
HexDecodeintoByte(init, test, 16);
cout << "Byte Decoded: " << test << endl;
//obtain the remaining piece
store2.assign(input.substr(16, input.length()));
HexDecode(store2, hexDec);
cout << "Finishing Decode: " << store2 << " -> DECD: " << hexDec << endl;


//
StringSink* sink = new StringSink(output);

CBC_Mode<AES>::Decryption aes(keyB, sizeof(keyB), test);


StreamTransformationFilter* aes_enc = new
StreamTransformationFilter(aes, sink);

StringSource cipher(hexDec, true, aes_enc);


}
catch(CryptoPP::Exception e) {
cout << e.GetWhat() << endl;
output = "Decrypt Error:";
output.append(e.GetWhat());
}
return 1;
}

int xxz568::HexDecodeintoByte(std::string input, CryptoPP::SecByteBlock
&output, int size) {


CryptoPP::StringSource foo(input, true,
new CryptoPP::HexDecoder(

new CryptoPP::ArraySink(output, size)));
return 1;
}
--
View this message in context: http://old.nabble.com/AES-Problem-tp31186698p31224154.html

Geoff Beier

unread,
Mar 24, 2011, 9:23:09 PM3/24/11
to Crypto++ Users
I meant to send this to the list too, so others could point out any
errors or omissions, etc., and so there'd be something for the
archives :-). Sorry about that.

Reply used to naturally go to the list, I thought. Now it seems
Reply-all is required?

Geoff


---------- Forwarded message ----------
From: Geoff Beier <geoff...@gmail.com>
Date: Thu, Mar 24, 2011 at 01:07
Subject: Re: AES Problem
To: "Robert F." <rfri...@phantomdev.net>


You'll need to change your encryption function too. You've got a round
trip through your old hex encode/decode routines in there.

I whacked together a quick and dirty sample that starts off with a
password and generates a random salt and IV. It uses PBKDF2 to derive
a key suitable for AES from the password and salt, then uses CBC mode
to encrypt a message with that derived key.

It then encodes ciphertext, salt and IV using the Hex Encoder and
prints them. Then it decodes salt and IV, re-runs the key derivation
function with the decoded salt and IV, uses that re-generated key to
decrypt the encoded ciphertext that it just printed.

I did compile and execute the code, but it was put together *very*
quickly and lacks error checking, etc. It should make it easy to
understand how the key derivation function works and how these filters
all hang together.

My sample is here:
http://pastebin.com/sVq5JneG

That code is as-is, no warranties. You can, of course, do what you
want with that code. I'd particularly encourage you to read it
carefully, understand it, find and fix any bugs, and write up your
understanding in the crypto++ wiki so others can find it easily :-)

When I run the test program that I get from compiling that program,
here is its output:
http://pastebin.com/NwjBdPhw

Good luck, and I hope this helps.

Geoff

Jeffrey Walton

unread,
Mar 27, 2011, 3:02:47 AM3/27/11
to Crypto++ Users


On Mar 24, 9:23 pm, Geoff Beier <geoffbe...@gmail.com> wrote:
> I meant to send this to the list too, so others could point out any
> errors or omissions, etc., and so there'd be something for the
> archives :-). Sorry about that.
>
> Reply used to naturally go to the list, I thought. Now it seems
> Reply-all is required?
>
Take a look at Gmail Labs (Gmail -> Settings -> Lab) and the "Reply To
All" default setting.

Jeff

Robert F.

unread,
Apr 5, 2011, 10:32:44 AM4/5/11
to cryptop...@googlegroups.com

This bit of code worked fine, just needed minor adjustments to suit my needs
for my program, but all in all it works great.

Thanks!

> --
> You received this message because you are subscribed to the "Crypto++
> Users" Google Group.
> To unsubscribe, send an email to
> cryptopp-user...@googlegroups.com.
> More information about Crypto++ and this group is available at
> http://www.cryptopp.com.
>
>

--
View this message in context: http://old.nabble.com/AES-Problem-tp31186698p31324770.html

Reply all
Reply to author
Forward
0 new messages