suculent / thinx-aes-lib

AES wrapper for ESP8266/ESP32/Arduino/nRF5x
Other
113 stars 39 forks source link

Encryption on ESP32 and decryption on nodejs doesn't match #39

Closed jonathan84clark closed 3 years ago

jonathan84clark commented 3 years ago

Hello,

I was wondering if I could get some help. What I need to do is encrypt a data string on the ESP32 and decrypt that string in Node.js but when I attempt to do this, the output doesn't match.

ESP32 key = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A message= username:password iv = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A encrypted output (ints) = 80 109 67 80 113 108 105 104 47 112 100 72 50 113 48 79 66 120 104 54 85 89 70 118 71 121 119 97 98 114 97 47

NodeJs (index.js example modified) key = '6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A' message = username:password iv = 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A encrypted output (str) = rEE18WTk+FDUD1o6KDxLkdVcENpBNPDTrcd4ZqjEgzE=

Am I asking for the wrong thing? Is the nodejs package totally different than the ESP32 library? One other option I am considering is porting the Arduino library code to Python (which is a little easier to work with than node.js) but that's a pretty big project and falls outside of the scope of what I need to do.

Thanks,

Jonathan L Clark

suculent commented 3 years ago

Sorry, I don't have a time to sort this out, even though it's probably a minor bug.

The TLS core is working and passing all the tests, so problem is somewhere in wrapper, usually the padding is different to OAEP as in https://github.com/suculent/thinx-aes-lib/issues/18.

I suggest using https://github.com/intrbiz/arduino-crypto https://github.com/intrbiz/arduino-crypto instead.

On 6. 1. 2021, at 17:33, Jonathan L Clark notifications@github.com wrote:

Hello,

I was wondering if I could get some help. What I need to do is encrypt a data string on the ESP32 and decrypt that string in Node.js but when I attempt to do this, the output doesn't match.

ESP32 key = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A message= username:password iv = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A encrypted output (ints) = 80 109 67 80 113 108 105 104 47 112 100 72 50 113 48 79 66 120 104 54 85 89 70 118 71 121 119 97 98 114 97 47

NodeJs (index.js example modified) key = '6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A' message = username:password iv = 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A encrypted output (str) = rEE18WTk+FDUD1o6KDxLkdVcENpBNPDTrcd4ZqjEgzE=

Am I asking for the wrong thing? Is the nodejs package totally different than the ESP32 library? One other option I am considering is porting the Arduino library code to Python (which is a little easier to work with than node.js) but that's a pretty big project and falls outside of the scope of what I need to do.

Thanks,

Jonathan L Clark

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/suculent/thinx-aes-lib/issues/39, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABWFR2W4JMYEVA7GDNQIJ3SYSGG7ANCNFSM4VXYQM3A.

klack commented 3 years ago

@suculent intrbiz/arduino-crypto also does not work atm:

https://github.com/intrbiz/arduino-crypto/issues/27

suculent commented 3 years ago

Just make sure you have data in same formats and with same settings (AES-128/CBC, Zero padding)... ESP32 key is byte array in C, but that needs to be constructed from base64, hex string or integer array in Node.js.

AES can be tricky as certain implementations (OpenSSL, Crypto-JS) embed/expect salt and IV in the encrypted blob.

NodeJS is somehow different to other implementations, but all of them have same AES algorithm in the core... otherwise it wouldn't ever work and this project would not be a github repository (that said, I had it working when I had time to develop it).

Using Cryptii.com, Text -> Block Cipher (AES-128 CBC)-> Bytes -> Base64 -> Text should be:

message: username:password key: 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a (16 bytes) IV: 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a 6a (16 bytes) Bytes: 3e 60 8f aa 58 a1 fe 97 47 da ad 0e 07 18 7a 51 0d 8c 76 20 29 dc e6 76 f9 2f 97 d5 73 c7 4d 59 Text: PmCPqlih/pdH2q0OBxh6UQ2MdiAp3OZ2+S+X1XPHTVk=

Using CryptoJS (NodeJS example modified using your values). All I had to change is the IV, KEY and way to parse them.

Returns following output (same to me):

base64_iv: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A ciphertext: PmCPqlih/pdH2q0OBxh6UYFvGywabra/+tC4+jJd4uw= Decrypted message: username:password Test passed.

Modified example with your values:

var CryptoJS = require("crypto-js");

var base64_iv  = '6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A';
var iv  = CryptoJS.enc.Hex.parse(base64_iv);

var AESKey = '6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A';
var key = CryptoJS.enc.Hex.parse(AESKey);

var message = "username:password";

// Encrypt
iv = CryptoJS.enc.Hex.parse(base64_iv); // resets IV back to initial state
var ebytes = CryptoJS.AES.encrypt( message, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.ZeroPadding
});
var ciphertext = ebytes.toString();
console.log("ciphertext: ", ciphertext);

// Decrypt
var bytes  = CryptoJS.AES.decrypt( ciphertext, key, {
  iv: iv,
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.ZeroPadding
});
var plaintext = bytes.toString(CryptoJS.enc.Base64);
var decoded_b64msg =  new Buffer(plaintext, 'base64').toString('ascii');

console.log("Decrypted message: ", decoded_b64msg);

if (decoded_b64msg == message) {
  console.log("Test passed.\n");
  process.exit(0);
} else {
  console.log("Test failed.\n");
  process.exit(1);
}

This covers the "truth" – Cryptii and Node.js/Crypto-JS having same results. Hope it helps for now.

M.

On 6. 1. 2021, at 17:33, Jonathan L Clark notifications@github.com wrote:

Hello,

I was wondering if I could get some help. What I need to do is encrypt a data string on the ESP32 and decrypt that string in Node.js but when I attempt to do this, the output doesn't match.

ESP32 key = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A message= username:password iv = 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A encrypted output (ints) = 80 109 67 80 113 108 105 104 47 112 100 72 50 113 48 79 66 120 104 54 85 89 70 118 71 121 119 97 98 114 97 47

NodeJs (index.js example modified) key = '6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A' message = username:password iv = 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A encrypted output (str) = rEE18WTk+FDUD1o6KDxLkdVcENpBNPDTrcd4ZqjEgzE=

Am I asking for the wrong thing? Is the nodejs package totally different than the ESP32 library? One other option I am considering is porting the Arduino library code to Python (which is a little easier to work with than node.js) but that's a pretty big project and falls outside of the scope of what I need to do.

Thanks,

Jonathan L Clark

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/suculent/thinx-aes-lib/issues/39, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABWFR2W4JMYEVA7GDNQIJ3SYSGG7ANCNFSM4VXYQM3A.

suculent commented 3 years ago

@jonathan84clark I think I was able to nail your issue down to padding, which was apparently missing in some of the examples. So if you call set_paddingmode((paddingMode)0) on the AESLib, it will set padding mode to CMS, which will result in compatibility with Cryptii/Node.js implementations where padding can't be set.

The default example with no padding settings results in 32 bytes decrypted (incl. padding) while it should return only 18 bytes of the cleartext. Once padding is properly set, it will generate same value as the CryptoJS/Cryptii.com and other implementations (see below).

You can check result in the example inside platformio/aes-test folder, which has "your" values and is configured for ESP32.

Its output is identical to node.js example above (keep in mind that AESLib returns data already encrypted using Base64 for transport):

readBuffer length: 18
Calling encrypt (string)...
Encrypted length = 44
CIPHERTEXT BYTES (in Base64): 
PmCPqlih/pdH2q0OBxh6UQ4tlk3rcriD4p05gTv+UWM=

Sorry it took so long.