2017-01-29 303 views
0

我确定我在做错解码和解密,但我不知道究竟是什么。ESP8266 AES加密 - 解密

#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

正如回收商指出的那样,返回的字符串缺少终止符。但是,您可以将其仅添加到带有char消息[msg.length()+ 1]的已解码缓冲区中;在解密。但是我发现你的程序非常困惑。请避免不必要的转换(为什么消息应该是一个字符串?为什么你必须来回转换为字符串?最重要的是:为什么将明文转换为base64?) – frarugi87

+0

generate_random_unit8'随机怎么样? – dandavis

+0

是的,这整个代码搞砸了..从一个PoC的博客复制它。 –

回答

1

如果你编码,你应该用\ 0来结束字符串,所以在解码数据中,\ 0也存在,printf可以正确地结束于\ 0。

修复程序将为 int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length()+1); 这确保隐含的\ 0字节被包括在内。编译器自动将它添加到msg字符串中。

试试吧!

0

我终于找到了什么事..

base64_decode(message, (char *)out, b64data.length());

应该

base64_decode(message, (char *)out, 75); - 编码数据的长度 - 1

至少在PoC工作。

0

我最近自己也有同样的问题,我花了几个小时试图弄清楚这一点。伊万诺夫,你对编码数据的长度有一个很好的观点。主要问题在于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] = '\0'; 
     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); 
}