AES加密:使用Arduino加密,使用Java解密
我想用Arduino加密文本,用Java解密。我从中尝试了此代码,但没有成功 我在Arduino上使用它进行加密,在Java端使用Java加密扩展(JCE)框架 这是Arduino代码:AES加密:使用Arduino加密,使用Java解密,java,encryption,arduino,cryptography,aes,Java,Encryption,Arduino,Cryptography,Aes,我想用Arduino加密文本,用Java解密。我从中尝试了此代码,但没有成功 我在Arduino上使用它进行加密,在Java端使用Java加密扩展(JCE)框架 这是Arduino代码: #include <AESLib.h> //replace the ( with < to compile (forum posting issue) #include <Base64.h> void setup() { Serial.begin(9600); uint
#include <AESLib.h> //replace the ( with < to compile (forum posting issue)
#include <Base64.h>
void setup() {
Serial.begin(9600);
uint8_t key[] = {50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50};
//expressed in 16 unsigned in characters, be careful not to typecast this as a char in a decrypter
//16- 50's (uint8) is the way to express 16 2's in ASCII, the encryption matches to what will show up on <a href="http://aesencryption.net/" target="_blank" rel="nofollow">http://aesencryption.net/</a>
char data[] = "0123456789012345";
//The message to encrypt, 16 chars == 16 bytes, no padding needed as frame is 16 bytes
char encryptedData[100];
int *size;
Serial.print("Message:");
Serial.println(data);
aes128_enc_single(key, data);
Serial.print("encrypted:");
Serial.println(data);
int inputLen = sizeof(data);
int encodedLen = base64_enc_len(inputLen);
char encoded[encodedLen];
base64_encode(encoded, data, inputLen);
Serial.print("encrypted(base64):"); //used
Serial.println(encoded);
Serial.println("***********Decrypter************");
int input2Len = sizeof(encoded);
int decodedLen = base64_dec_len(encoded, input2Len);
char decoded[decodedLen];
base64_decode(decoded, encoded, input2Len);
Serial.print("encrypted (returned from Base64):");
Serial.println(decoded);
Serial.print("decrypted:");
Serial.println(decoded);
}
void loop() {
}
#include "mbedtls/aes.h"
#include <Arduino.h>
#include <HTTPClient.h>
#include <base64.h>
void makeUpdateAPICall()
{
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(serverName);
// Specify content-type header
http.addHeader("Content-Type", "text/plain");
http.addHeader("Authorization", "Bearer XXXXXXXX [whatever your web token is]");
http.addHeader("X-Content-Type-Options", "nosniff");
http.addHeader("X-XSS-Protection", "1; mode=block");
//AES Encrypt
esp_aes_context aesOutgoing;
unsigned char key[32] = "1234567812345678123456781234567" ;
key[31] = '8'; // we replace the 32th (index 31) which contains '/0' with the '8' char.
char *input = "Tech tutorials x";
unsigned char encryptOutput[16];
mbedtls_aes_init(&aesOutgoing);
mbedtls_aes_setkey_enc(&aesOutgoing, key, 256);
int encryptAttempt = mbedtls_aes_crypt_ecb(&aesOutgoing, MBEDTLS_AES_ENCRYPT, (const unsigned char *)input, encryptOutput);
USE_SERIAL.println();
USE_SERIAL.println("MBEDTLS_AES_EBC encryption result:\t ");
USE_SERIAL.print(encryptAttempt); //0 means that the encrypt/decrypt function was successful
USE_SERIAL.println();
mbedtls_aes_free(&aesOutgoing);
int encryptSize = sizeof(encryptOutput) / sizeof(const unsigned char);
USE_SERIAL.println("Size of AES encrypted output: ");
USE_SERIAL.println(encryptSize);
//Base 64 Encrypt
int inputStringLength = sizeof(encryptOutput);
int encodedLength = Base64.decodedLength((char *)encryptOutput, inputStringLength);
char encodedCharArray[encodedLength];
Base64.encode(encodedCharArray, (char *)encryptOutput, inputStringLength);
//Send to server
USE_SERIAL.print("Sending to server.");
int httpResponseCode = http.POST(encodedCharArray);
String payload = "{}";
if (httpResponseCode > 0)
{
//Retrieve server response
payload = http.getString();
}
// Free resources
http.end();
}
WiFi.disconnect();
}
有什么想法吗?
谢谢 大约一周后,我就可以让它正常工作了——使用Arduino与其他系统集成的文档是垃圾:) 工作代码:
#include <AESLib.h> //replace the ( with < to compile (forum posting issue)
#include <Base64.h>
void setup() {
Serial.begin(9600);
uint8_t key[] = {50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50};
//expressed in 16 unsigned in characters, be careful not to typecast this as a char in a decrypter
//16- 50's (uint8) is the way to express 16 2's in ASCII, the encryption matches to what will show up on <a href="http://aesencryption.net/" target="_blank" rel="nofollow">http://aesencryption.net/</a>
char data[] = "0123456789012345";
//The message to encrypt, 16 chars == 16 bytes, no padding needed as frame is 16 bytes
char encryptedData[100];
int *size;
Serial.print("Message:");
Serial.println(data);
aes128_enc_single(key, data);
Serial.print("encrypted:");
Serial.println(data);
int inputLen = sizeof(data);
int encodedLen = base64_enc_len(inputLen);
char encoded[encodedLen];
base64_encode(encoded, data, inputLen);
Serial.print("encrypted(base64):"); //used
Serial.println(encoded);
Serial.println("***********Decrypter************");
int input2Len = sizeof(encoded);
int decodedLen = base64_dec_len(encoded, input2Len);
char decoded[decodedLen];
base64_decode(decoded, encoded, input2Len);
Serial.print("encrypted (returned from Base64):");
Serial.println(decoded);
Serial.print("decrypted:");
Serial.println(decoded);
}
void loop() {
}
#include "mbedtls/aes.h"
#include <Arduino.h>
#include <HTTPClient.h>
#include <base64.h>
void makeUpdateAPICall()
{
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(serverName);
// Specify content-type header
http.addHeader("Content-Type", "text/plain");
http.addHeader("Authorization", "Bearer XXXXXXXX [whatever your web token is]");
http.addHeader("X-Content-Type-Options", "nosniff");
http.addHeader("X-XSS-Protection", "1; mode=block");
//AES Encrypt
esp_aes_context aesOutgoing;
unsigned char key[32] = "1234567812345678123456781234567" ;
key[31] = '8'; // we replace the 32th (index 31) which contains '/0' with the '8' char.
char *input = "Tech tutorials x";
unsigned char encryptOutput[16];
mbedtls_aes_init(&aesOutgoing);
mbedtls_aes_setkey_enc(&aesOutgoing, key, 256);
int encryptAttempt = mbedtls_aes_crypt_ecb(&aesOutgoing, MBEDTLS_AES_ENCRYPT, (const unsigned char *)input, encryptOutput);
USE_SERIAL.println();
USE_SERIAL.println("MBEDTLS_AES_EBC encryption result:\t ");
USE_SERIAL.print(encryptAttempt); //0 means that the encrypt/decrypt function was successful
USE_SERIAL.println();
mbedtls_aes_free(&aesOutgoing);
int encryptSize = sizeof(encryptOutput) / sizeof(const unsigned char);
USE_SERIAL.println("Size of AES encrypted output: ");
USE_SERIAL.println(encryptSize);
//Base 64 Encrypt
int inputStringLength = sizeof(encryptOutput);
int encodedLength = Base64.decodedLength((char *)encryptOutput, inputStringLength);
char encodedCharArray[encodedLength];
Base64.encode(encodedCharArray, (char *)encryptOutput, inputStringLength);
//Send to server
USE_SERIAL.print("Sending to server.");
int httpResponseCode = http.POST(encodedCharArray);
String payload = "{}";
if (httpResponseCode > 0)
{
//Retrieve server response
payload = http.getString();
}
// Free resources
http.end();
}
WiFi.disconnect();
}
现在正在处理退货流程
使用以下代码调用Java端:
final String decryptedText=AES.decrypt(encryptedStr,“1234567881234567812345678812345678”);
System.out.println(“解密的AES ECB字符串:”);
System.out.println(解密文本);
想为任何发现自己和他/她在同一条船上的可怜的懒汉提供这个:)
希望这有帮助 您尝试对base64进行解码和解密的字符串是
Ouril+UTDF8htLzEhiRj7wA=
,它在base64解码后为17个字节,后面有一个0字节。前面打印的字符串是Ouril+UTDF8htLzEhiRj7w==
,除了尾随的字节外,它是相同的(在base 64解码后),并且是正确的长度(16字节)。但是为什么在使用arduino和Java在base 64编码后,我得不到相同的结果呢?对于Arduino,我得到了:Ouril+UTDF8htLzEhiRj7wA=
而对于Java,我得到了Ouril+UTDF8htLzEhiRj7w==
,我该如何纠正?谢谢Arduino输出引入了一个额外的字节。我不熟悉Arduino语言本身,但快速看一下,它是C/C++的一个子集。C以“空终止”其字符串而闻名(即,为了指示具有任意长度的字符串的结尾,它添加了一个包含值0x00
)的字节)。在Java代码中,您需要将输入密码文本修剪为0x00
字节之前的字节。此外,如果输入的明文和密文不是16字节的精确倍数(AES的块大小),ECB
是最差的密码块模式(相当于在大多数情况下不加密),则您选择的AES/ECB/NoPadding
将出现严重问题。查看上的Wikipedia条目并选择一个更好的选项(GCM建议用于AEAD属性)。您也可以在源代码处解决此问题,并且仅在Arduino中将密码文本的内容编码到空字节,但我对该语言了解不够,无法确定是否有简单的方法可以做到这一点。在编码之前,您可能只需要从char[]
中修剪最后一个字节。这对于固定大小的加密输出没有多大用处,所有将密钥作为字符串的把戏都不是必需的:如果您将其保留为OP,则不会出现尾随空问题。@user207421您是完全正确的。然而,我的示例的目的只是提供Arduino和Java之间AES集成的可行方法。那里真的没有文档(至少我能找到)。我的产品代码使用padding、AES-CBC和从服务器上的安全位置提取密钥。从一个安全的位置提取密钥&另一件事更复杂,但诀窍是当解密/加密部分来自其他系统/语言时,让它们工作起来。希望这能帮助某人克服这个障碍。
public static String decrypt(String strToDecrypt, String key) {
byte[] encryptionKeyBytes = key.getBytes(); Cipher cipher; try { cipher = Cipher.getInstance("AES/ECB/NoPadding"); SecretKey secretKey = new SecretKeySpec(encryptionKeyBytes, "AES"); cipher.init(Cipher.DECRYPT_MODE, secretKey); return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt.getBytes("UTF-8")))); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }