spaniakos / AES

AES for microcontrollers (Arduino & Raspberry pi)
http://spaniakos.github.io/AES/
GNU Affero General Public License v3.0
126 stars 56 forks source link

Not AES-128 CBC Standards compliant - Doc Bug? #13

Closed psychogony closed 7 years ago

psychogony commented 7 years ago

include I am not well versed with AES.

Not sure if this is a code bug, or a documentation issue.

The code header states 'This is an AES implementation that uses only 8-bit byte operations on the cipher state.' Internally the implementation uses an eight byte / 64bit iv (repeated twice for 128bits). While it is able to decrypt its own data fine, it does not interopt with other third party AES-128 implementations.

eg. For a 'gamed iv' that should work across targets and with data that doesn't need padding.

uint8_t iv[]  = 
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

uint8_t key[] = 
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 
  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };

uint8_t in[]  = 
{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
  0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
  0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
  0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
  0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b,
  0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
  0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 
  0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };

uint8_t out[sizeof(in)];
// spaniakos/AES
AES aes;
aes.do_aes_encrypt(
  in,
  sizeof(in),
  out,
  &key[0],
  128,
  iv
);

output => 
{ 0xfd, 0xe6, 0x05, 0x00, 0x35, 0x0e, 0xd2, 0xf7,
  0x6e, 0x35, 0xd4, 0x81, 0xb4, 0x54, 0xe4, 0x88,
  0xee, 0xe8, 0xed, 0x2a, 0x9d, 0xe7, 0x1e, 0xda,
  0x98, 0x62, 0x62, 0xe3, 0xdc, 0x75, 0xfa, 0x70,
  0xc2, 0x28, 0xbc, 0x17, 0xf4, 0xe7, 0xc9, 0xd9, 
  0xa8, 0xbf, 0x2c, 0x35, 0xcf, 0xff, 0x13, 0x80,
  0x1b, 0x04, 0x9f, 0xcf, 0xfc, 0x07, 0x3f, 0x10,
  0x32, 0xa1, 0x89, 0xae, 0xa0, 0xb8, 0x47, 0xd2 };

kokke/Tiny-AES128-C, (php) openssl and (php) mcrypt all produce the same output. However this output is slightly different from spaniakos/AES

// kokke/Tiny-AES128-C
AES128_CBC_encrypt_buffer(out, in, sizeof(in), key, iv);
// php mcrypt
$encryptedData = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $in, MCRYPT_MODE_CBC, $iv);
// php openssl
define('AES_128_CBC', 'aes-128-cbc');
$encryptedData = openssl_encrypt($in, AES_128_CBC, $key, OPENSSL_ZERO_PADDING  | OPENSSL_RAW_DATA, $iv);

'Expected' output (result from all other implementations tested)

output =>
{ 0xfd, 0xe6, 0x05, 0x00, 0x35, 0x0e, 0xd2, 0xf7,
  0x6e, 0x35, 0xd4, 0x81, 0xb4, 0x54, 0xe4, 0x88,
  0xee, 0xe8, 0xed, 0x2a, 0x9d, 0xe7, 0x1e, 0xda,
  0x98, 0x62, 0x62, 0xe3, 0xdc, 0x75, 0xfa, 0x70,
  0xc2, 0x28, 0xbc, 0x17, 0xf4, 0xe7, 0xc9, 0xd9,
  0xa8, 0xbf, 0x2c, 0x35, 0xcf, 0xff, 0x13, 0x80,
  0xbb, 0xcd, 0x91, 0x2d, 0xb7, 0xa4, 0x8e, 0xbf,
  0x2e, 0x96, 0x42, 0x84, 0x39, 0xfa, 0x46, 0x19 };
spaniakos commented 7 years ago

Hm... Come you maybe include the sketch so i can test the library? Thank you

On Apr 13, 2017 07:58, "Beau Hardy" notifications@github.com wrote:

include I am not well versed with AES.

Not sure if this is a code bug, or a documentation issue.

The code header states 'This is an AES implementation that uses only 8-bit byte operations on the cipher state.' Internally the implementation uses an eight byte / 64bit iv (repeated twice for 128bits). While it is able to decrypt its own data fine, it does not interopt with other third party AES implementations.

eg. For a 'gamed iv' that should work across targets and with data that doesn't need padding.

uint8_t iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6 };

uint8_t in[] = { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };

uint8_t out[sizeof(in)];

// spaniakos/AES AES aes; aes.do_aes_encrypt( in, sizeof(in), out, &key[0], 128, iv );

output => { 0xfd, 0xe6, 0x05, 0x00, 0x35, 0x0e, 0xd2, 0xf7, 0x6e, 0x35, 0xd4, 0x81, 0xb4, 0x54, 0xe4, 0x88, 0xee, 0xe8, 0xed, 0x2a, 0x9d, 0xe7, 0x1e, 0xda, 0x98, 0x62, 0x62, 0xe3, 0xdc, 0x75, 0xfa, 0x70, 0xc2, 0x28, 0xbc, 0x17, 0xf4, 0xe7, 0xc9, 0xd9, 0xa8, 0xbf, 0x2c, 0x35, 0xcf, 0xff, 0x13, 0x80, 0x1b, 0x04, 0x9f, 0xcf, 0xfc, 0x07, 0x3f, 0x10, 0x32, 0xa1, 0x89, 0xae, 0xa0, 0xb8, 0x47, 0xd2 };

kokke/Tiny-AES128-C, (php) openssl and (php) mcrypt all produce the same output. However this output is slightly different from spaniakos/AES

// kokke/Tiny-AES128-C AES128_CBC_encrypt_buffer(out, in, sizeof(in), key, iv);

// php mcrypt $encryptedData = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $in, MCRYPT_MODE_CBC, $iv);

// php openssl define('AES_128_CBC', 'aes-128-cbc'); $encryptedData = openssl_encrypt($in, AES_128_CBC, $key, OPENSSL_ZERO_PADDING | OPENSSL_RAW_DATA, $iv);

'Expected' output (result from all other implementations tested)

output => { 0xfd, 0xe6, 0x05, 0x00, 0x35, 0x0e, 0xd2, 0xf7, 0x6e, 0x35, 0xd4, 0x81, 0xb4, 0x54, 0xe4, 0x88, 0xee, 0xe8, 0xed, 0x2a, 0x9d, 0xe7, 0x1e, 0xda, 0x98, 0x62, 0x62, 0xe3, 0xdc, 0x75, 0xfa, 0x70, 0xc2, 0x28, 0xbc, 0x17, 0xf4, 0xe7, 0xc9, 0xd9, 0xa8, 0xbf, 0x2c, 0x35, 0xcf, 0xff, 0x13, 0x80, 0xbb, 0xcd, 0x91, 0x2d, 0xb7, 0xa4, 0x8e, 0xbf, 0x2e, 0x96, 0x42, 0x84, 0x39, 0xfa, 0x46, 0x19 };

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/spaniakos/AES/issues/13, or mute the thread https://github.com/notifications/unsubscribe-auth/ABnM6pA4JjThQNetz20Xi8wb02ktZeoiks5rvatqgaJpZM4M8Ql1 .

psychogony commented 7 years ago

Hi - Thank you for getting back to me.

I am not sure I can give you a sketch. The problem involves multiple pieces of software running on multiple pieces of hardware:

What I am really asking is:

I have spent more than a day trying to solve this problem. Right now I am using https://github.com/kokke/Tiny-AES128-C/ This library seems to create encrypted data that (php) openssl and (php) libmcrypt can decrypt/read. Unfortunately Tiny-AES128-C also uses much more RAM (not optimised).

Trying to clarify repo steps:

  1. Install library https://github.com/spaniakos/AES/

  2. Using 'iv', 'key' and 'in' bytes from above comment

  3. AES aes; aes.do_aes_encrypt(in, sizeof(in), out, &key[0], 128, iv);

  4. Print array 'out'

  5. Install library https://github.com/kokke/Tiny-AES128-C/

  6. Using 'iv', 'key' and 'in' bytes from above comment

  7. AES128_CBC_encrypt_buffer(out, in, sizeof(in), key, iv);

  8. Print array 'out'

The two outputs are different (look closely at last 16 bytes)

  1. Run the equivalent encrypt command on php using openssh
  2. print array out

Output bytes from php openssl is same as kokke/Tiny-AES128-C, different from spaniakos/AES

  1. Run the equivalent encrypt command on php using mcrypt
  2. Print array out

Output bytes from php mcrypt is same as kokke/Tiny-AES128-C, different from spaniakos/AES

Problem relates to background yield() on ESP8266? spaniakos/AES/ misses a block round on last 16 bytes when compared to other implementations?

spaniakos commented 7 years ago

I will check about the problemand tell you.

On Apr 13, 2017 12:30 PM, "Beau Hardy" notifications@github.com wrote:

Hi - Thank you for getting back to me.

I am not sure I can give you a sketch. The problem involves multiple pieces of software running on multiple pieces of hardware:

  • ESP8266 (running arduino + spaniakos/AES) sending encrypted data to a web server
  • Web server (running php + openssl | mcrypt) trying to decrypt the data that the ESP8266 sent it

What I am really asking is:

  • If https://github.com/spaniakos/AES/ should produce the same encrypted bits as other AES-128 CBC implementations (comment about 8byte blocks).
  • If I have missed a function call/parameter that will make spaniakos/AES produce the same encrypted bits as other AES-128 CBC implementations.

I have spent more than a day trying to solve this problem. Right now I am using https://github.com/kokke/Tiny-AES128-C/ This library seems to create encrypted data that (php) openssl and (php) libmcrypt can decrypt/read. Unfortunately Tiny-AES128-C also uses much more RAM (not optimised).

Trying to clarify repo steps:

1.

Install library https://github.com/spaniakos/AES/ 2.

Using 'iv', 'key' and 'in' bytes from above comment 3.

AES aes; aes.do_aes_encrypt(in, sizeof(in), out, &key[0], 128, iv); 4.

Print array 'out' 5.

Install library https://github.com/kokke/Tiny-AES128-C/ 6.

Using 'iv', 'key' and 'in' bytes from above comment 7.

AES128_CBC_encrypt_buffer(out, in, sizeof(in), key, iv); 8.

Print array 'out'

The two outputs are different (look closely at last 16 bytes)

  1. Run the equivalent encrypt command on php using openssh
  2. print array out

Output bytes from php openssl is same as kokke/Tiny-AES128-C, different from kokke/spaniakos/AES/

  1. Run the equivalent encrypt command on php using mcrypt
  2. Print array out

Output bytes from php mcrypt is same as kokke/Tiny-AES128-C, different from kokke/spaniakos/AES/

Problem relates to background yield() on ESP8266? spaniakos/AES/ misses a block round on last 16 bytes when compared to other implementations?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/spaniakos/AES/issues/13#issuecomment-293839907, or mute the thread https://github.com/notifications/unsubscribe-auth/ABnM6jXPQhDjPi6xWLi3Cxo0ydUbh6tmks5rvesqgaJpZM4M8Ql1 .

Dzitu commented 7 years ago

Hello @psychogony, This library does PKCS#7 padding before encryption. TinyAES and PHP mcrypt, if I see correctly, does ZeroBytePadding. In PHP OpenSSL code you have explicitly chosen ZeroBytePadding. That should explain why last block differs. I tested this library against cryptopp in CBC mode with PKCS#7 and it works well. Hope that helps!

Also see #16 where one byte of plaintext was ignored. I was comparing my version with that change in. That will affect your example as well.

spaniakos commented 7 years ago

this is not a complete AES framework will full interoperability. it still has a long way in order for it to be fully compatible with openssl library. the main focus was speed and efficiency as it was build for encrypting communication over nRF24L01+ antennas, so the communication can have security.

i am compiling a framework for easy usage. if you cant to contribute with an php interface for decrypting the communication, you are more than welcome. or if you want you can add ZeroBytePadding function and i will help you integrate them to the library.

Thank you for the support!!