c++ - Arduino 中的 CBC 加密

标签 c++ encryption

一直在编写一些代码来加密 wifi 网络的 SSID,然后将其存储在 TI 的 CC3200 MCU 闪存上的文件中。该程序是用 Energia 编写的,这是一个与 Arduino IDE 相同的 IDE。

加密函数(列出 here)接受 uint8_t 数组,它看起来像这样:

void AES128_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
void AES128_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);

这是一系列事件:

SSID 存储在一个字符数组中 > 被加密并存储在 enc_ssid 缓冲区中 > 文件操作从这里开始,删除一个现有文件,然后创建一个新文件 > 写入 enc_ssid 到文件 > 从文件中读回,然后解密为另一个字符数组。

问题是,当它从文件中读回时,我在我的串行监视器上看到奇怪的字符(输出也贴在这个问题的末尾)。我做错了什么?

代码:

Serial.begin(115200);
SerFlash.begin(); // Begin the file system library. This also calls WiFi.init().

uint8_t keys[] = {0x18, 0x92, 0xe5, 0xfe, 0x5e, 0x02, 0x92, 0x23, 0x23, 0x9c, 0x9a, 0xfd, 0x59, 0xaf, 0x55, 0x23}; 
uint8_t iv[] = {0xfe, 0x0d, 0x44, 0x18, 0xb3, 0xea, 0xc5, 0x0d, 0xfe, 0xe5, 0xa3, 0x6a, 0x25, 0x72, 0xf1, 0x71};

char ssid[] = "ABCDEFGH";
len_ssid = (sizeof(ssid)/sizeof(ssid[0]));
Serial.print("SSID length: "); Serial.println(len_ssid);
Serial.println();

uint8_t enc_ssid[len_ssid];
char dec_ssid[len_ssid];
uint8_t str_ssid[len_ssid];

// Encrypt the SSID buffer.
AES128_CBC_encrypt_buffer(enc_ssid, (uint8_t*)ssid, len_ssid, keys, iv);

for (int i=0; i<len_ssid; i++)
{
    Serial.print("enc_ssid["); Serial.print(i); Serial.print("]: "); Serial.println(enc_ssid[i]);
}
Serial.println();

// Delete the old SSID file and create a new one.
SerFlash.del("/user/ssid2.txt");
Serial.print("\nDeleting /user/ssid2.txt, return code: "); Serial.println(SerFlash.lastErrorString());
Serial.flush();

// Creates a 32 byte file called ssid2.txt. Returns 0 if successful or a negative number if unsuccessful.
retVal = SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_CREATE(32, _FS_FILE_OPEN_FLAG_COMMIT));
if (retVal >= 0)
{
  Serial.println("Success creating new ssid file!");
  SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_WRITE);
  SerFlash.write(enc_ssid, len_ssid);
  SerFlash.close();

  // Verify that the file has indeed been written.
  SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_READ);
  str_ssid[0] = '\0'; // Init str_ssid in case readBytes doesn't actually do anything (and returns 0)
    size_t read_length = SerFlash.readBytes(str_ssid, len_ssid);
    Serial.print("Read ");
  Serial.print(read_length);
  Serial.println(" bytes from /user/ssid2.txt - contents: ");
  //Serial.println(str_ssid);
  for (int i=0; i<len_ssid; i++)
  {
        Serial.print("file["); Serial.print(i); Serial.print("]: "); Serial.println(str_ssid[i], DEC);
  }
  SerFlash.close();
}
else
{
  Serial.print("Error creating SSID2 file. Error code: "); Serial.println(SerFlash.lastErrorString());
}

// Decrypt the SSID buffer.
AES128_CBC_decrypt_buffer((uint8_t*)dec_ssid, str_ssid, len_ssid, keys, iv);

Serial.println();
for (int i=0; i<len_ssid; i++)
{
    Serial.print("decrypted["); Serial.print(i); Serial.print("]: "); Serial.println(dec_ssid[i]);
}

这是我看到的串行输出。可以看出,解密 应该显示 ABCDEFGH 但显示奇怪的字符。

SSID length: 9

enc_ssid[0]: 243
enc_ssid[1]: 97
enc_ssid[2]: 109
enc_ssid[3]: 34
enc_ssid[4]: 188
enc_ssid[5]: 209
enc_ssid[6]: 8
enc_ssid[7]: 136
enc_ssid[8]: 34

Deleting /user/ssid2.txt, return code: SL_FS_OK
Success creating new ssid file!
Read 9 bytes from /user/ssid2.txt - contents: 

file[0]: 243
file[1]: 97
file[2]: 109
file[3]: 34
file[4]: 188
file[5]: 209
file[6]: 8
file[7]: 136
file[8]: 34

decrypted[0]: 7
decrypted[1]: A
decrypted[2]: A
decrypted[3]: ¨
decrypted[4]: Æ
decrypted[5]: 
decrypted[6]: B
decrypted[7]: 
decrypted[8]: É

最佳答案

您的问题可能源于以下事实:您只尝试加密八个字节,AES128 在 128 位(16 字节)粒度上工作,并且库不为您填充。在库开头的评论中有这个:

NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)
    You should pad the end of the string with zeros if this is not the case.

查看库,看起来库确实支持加密/解密不是 16B 倍数的数据量,但输出缓冲区必须是 16B 的倍数,以便这才能正常工作(因为作者仍​​然为您添加填充)。无论如何,AES128_CBC_encrypt_buffer 的代码以 BlockCopy(output, input); 开头,它试图从 input 复制整个 block (16 字节)到输出。由于您只传递八个字节的缓冲区,这将导致发生未定义的行为,这可以解释您所看到的情况。

简而言之,使您的加密/解密缓冲区长 16 个字节,并手动将最后八个字节设置为零。

关于c++ - Arduino 中的 CBC 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38131926/

相关文章:

c++ - 查找字符串中某个字符的所有出现

C++ 简单编译错误

c++ - 链接到动态库的静态库中的 undefined symbol

php - 使用 Ruby 的 md5 复制 PHP 5 中的 md5 raw_output 标志(原始字节)

c# - 如何使用 AES 在一个程序中加密,在另一个程序中解密

c++ - 尝试使用 dev-C++ 创建 .exe 时出现错误 255

C++:指数中的最后一位 - 错误答案

azure - 由于Azure表存储不支持加密,因此在其中存储敏感信息是否安全?

security - XOR 加密有什么问题?

algorithm - 作业的简单加密算法。无法正常解密