我确定我做错了解码和解密,但我不知道到底是什么。
#include "AES.h"
#include "Base64.h"
AES aes;
// Our AES key. Note that is the same that is used on the Node-Js side but as hex bytes.
byte key[] = {0x7e, 0x4e, 0x42, 0x38, 0x43, 0x63, 0x4f, 0x4c, 0x23, 0x4a, 0x21, 0x48, 0x3f, 0x7c, 0x59, 0x72};
// The unitialized Initialization vector
byte iv[N_BLOCK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// Our message to encrypt. Static for this example.
String msg = "{"data":{"value":300}, "SEQN":700 , "msg":"IT WORKS!!" }";
uint8_t generate_random_unit8()
{
uint8_t really_random = *(volatile uint8_t *)0x3FF20E44;
return really_random;
}
// Generate a random initialization vector
void generate_iv(byte *vector)
{
for (int i = 0; i < N_BLOCK; i++)
{
vector[i] = (byte)generate_random_unit8();
}
}
void encrypt()
{
char b64data[200];
byte cipher[1000];
byte iv[N_BLOCK];
generate_iv(iv);
base64_encode(b64data, (char *)iv, N_BLOCK);
String IV_base64 = String(b64data);
Serial.println(" IV b64: " + IV_base64);
int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length());
Serial.println(" The lenght is: " + String(b64len));
// Encrypt! With AES128, our key and IV, CBC and pkcs7 padding
aes.do_aes_encrypt((byte *)b64data, b64len, cipher, key, 128, iv);
Serial.println("Cipher size: " + String(aes.get_size()));
base64_encode(b64data, (char *)cipher, aes.get_size());
Serial.println("Encrypted data in base64: " + String(b64data));
decrypt(b64data, IV_base64, aes.get_size());
}
void decrypt(String b64data, String IV_base64, int size)
{
char data_decoded[200];
char iv_decoded[200];
byte out[200];
char temp[200];
b64data.toCharArray(temp, 200);
base64_decode(data_decoded, temp, b64data.length());
IV_base64.toCharArray(temp, 200);
base64_decode(iv_decoded, temp, IV_base64.length());
aes.do_aes_decrypt((byte *)data_decoded, size, out, key, 128, (byte *)iv_decoded);
char message[msg.length()];
base64_decode(message, (char *)out, b64data.length());
printf("Out %s n", message);
}
void setup_aes()
{
aes.set_key(key, sizeof(key)); // Get the globally defined key
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
encrypt();
delay(1000);
}
解码的消息应{"data":{"value":300}, "SEQN":700 , "msg":"IT WORKS!!"
。但是我越来越{"data":{"value":300}, "SEQN":700 , "msg":"IT WORKS!!" }�������������������������
.我会假设字符长度不正确?
如果编码,则应使用 \0 完成字符串,因此在解码数据中,\0 也存在,并且 printf 可以正确以 \0 结尾。
修复将是 int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length()+1);
这可确保包含隐式 \0 字节。编译器会自动将其添加到 msg 字符串中。
试试吧!
我最近自己也遇到了同样的问题,我花了几个小时试图解决这个问题。伊万诺夫,你对编码数据的长度有一个很好的观点。主要问题基本上是当AES加密功能创建额外的填充并且解密功能无法删除它时。
这与字符串的空终止或缺少终止符的事实无关。实际上,只需从解密字符串中省略最后 5 个填充即可解决问题。
编辑 这实际上不仅仅是从末尾省略 5 个字符。由于我发现乱码或填充的数量因原始 JSON 的长度而异,因此通过检测 JSON 字符串的末尾来修剪字符串更有意义。
我正在提供我的(更新的)工作代码以供参考。我希望这对任何也有这个问题的人有所帮助!祝你的项目好运!
#include "AES.h"
#include "Base64.h"
AES aes;
// Our AES key. Same in NodeJS but in hex bytes
byte key[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
// The unitialized Initialization vector (16-bit)
byte iv[N_BLOCK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// NodeMCU side raw message
String msg = "{"x":10, "y":20, "z":30 "lamp_stat":"ON This is a sentence. Testing testing testing"}";
uint8_t generate_random_unit8()
{
uint8_t really_random = *(volatile uint8_t *)0x3FF20E44;
return really_random;
}
// Generate a random initialization vector
void generate_iv(byte *vector)
{
for (int i = 0; i < N_BLOCK; i++)
{
vector[i] = (byte)generate_random_unit8();
}
}
void encrypt()
{
char b64data[200];
byte cipher[1000];
byte iv[N_BLOCK];
generate_iv(iv);
base64_encode(b64data, (char *)iv, N_BLOCK);
String IV_base64 = String(b64data);
Serial.println(" IV b64: " + IV_base64);
int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length());
Serial.println(" The lenght is: " + String(b64len));
// Encrypt! With AES128, our key and IV, CBC and pkcs7 padding
aes.do_aes_encrypt((byte *)b64data, b64len, cipher, key, 128, iv);
Serial.println("Cipher size: " + String(aes.get_size()));
base64_encode(b64data, (char *)cipher, aes.get_size());
Serial.println("Encrypted data in base64: " + String(b64data));
//decrypt(b64data, IV_base64, aes.get_size());
}
void decrypt(String b64data, String IV_base64, int lsize)
{
char data_decoded[300];
char iv_decoded[300];
byte out[300];
char temp[300];
b64data.toCharArray(temp, 300);
base64_decode(data_decoded, temp, b64data.length());
IV_base64.toCharArray(temp, 300);
base64_decode(iv_decoded, temp, IV_base64.length());
aes.do_aes_decrypt((byte *)data_decoded, lsize, out, key, 128, (byte *)iv_decoded);
char message[msg.length()];
base64_decode(message, (char *)out, aes.get_size());
for (int i = 0; i < aes.get_size(); i++)
{
char curChar = (char)message[i];
if (curChar != '}')
temp[i] = curChar;
else
{
temp[i] = curChar;
temp[i+1] = ' ';
break;
}
}
String result = String((char *)temp);
Serial.println(result);
}
void setup_aes()
{
aes.set_key(key, sizeof(key)); // Get the globally defined key
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
encrypt();
decrypt("ipYk12VCYyD+aJ7KL7lO8L5zOq71XvsLzp650gKBFgQor7GHs98QpQSjQOZdhCwggq2Ehf4nVNwTeK3VjtqMVJRGBw9YViARXCTOGqctjFc=", "+eNzSlRRPi0YZhrp5ctpnA==", 83);
delay(8000);
}
我终于发现了问题所在。
base64_decode(message, (char *)out, b64data.length());
应该是
base64_decode(message, (char *)out, 75);
- 编码数据的长度 - 1
至少 PoC 有效。