简体   繁体   English

AES 加密:使用 Arduino 加密并使用 Java 解密

[英]AES Encryption : Encrypt using Arduino and decrypt using Java

I want to encrypt a text using Arduino and decrypt it using Java.我想使用 Arduino 加密文本并使用 Java 解密它。 I tried this code from this link but without success.我从这个链接尝试了这段代码,但没有成功。

I am using this Arduino library for encryption on the Arduino and the Java Cryptographic Extension (JCE) framework for the Java side.我在Arduino上使用这个Arduino 库进行加密,并在 Java 端使用 Java Cryptographic Extension (JCE) 框架。

This the Arduino code:这是 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() {
}

This is the Java code:这是Java代码:

package main;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

public class ForTest {
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        String message= "0123456789012345";//Message to encode  
        String key = "2222222222222222";  
        // 128 bit key  -this key is processed as ASCII values  
        System.out.println("Processing 3.0 AES-128 ECB Encryption/Decryption Example");
        System.out.println("++++++++++++++++++++++++++++++++");
        System.out.println("Original Message: " + message);
        System.out.println("Key: " + key);
        System.out.println("key in bytes: "+key.getBytes("UTF-8"));
        System.out.println("==========================");           
        //Encrypter
        SecretKeySpec skeySpec_encode = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher_encode  = Cipher.getInstance("AES/ECB/NoPadding");
        //          Cipher cipher_encode = Cipher.getInstance("AES/ECB/PKCS5PADDING"); //AES-CBC with IV encoding, ECB is used without the IV, example shown on <a href="http://aesencryption.net/" target="_blank" rel="nofollow">http://aesencryption.net/</a> 
        cipher_encode.init(Cipher.ENCRYPT_MODE, skeySpec_encode);
        byte[] encrypted = cipher_encode.doFinal(message.getBytes());
        System.out.println("Encrypted String (base 64): "
                + DatatypeConverter.printBase64Binary(encrypted));
        //encode without padding: Base64.getEncoder().withoutPadding().encodeToString(encrypted));
        //encode with padding:  Base64.getEncoder().encodeToString(encrypted));
        String base64_encrypted = DatatypeConverter.printBase64Binary(encrypted);
        //Decrypter
        SecretKeySpec skeySpec_decode = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher_decode  = Cipher.getInstance("AES/ECB/NoPadding");
        //          Cipher cipher_decode = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        cipher_decode.init(Cipher.DECRYPT_MODE, skeySpec_decode);
        System.out.println("length: "+"Ouril+UTDF8htLzE".length());
        byte[] decrypted_original = cipher_decode.doFinal(DatatypeConverter.parseBase64Binary("Ouril+UTDF8htLzEhiRj7wA="));
        String decrypt_originalString = new String(decrypted_original);
        System.out.println("Decrypted String: " + decrypt_originalString);
    }
}

In Java when I try to decrypt the encoded String by Arduino I get this:在 Java 中,当我尝试通过 Arduino 解密编码的字符串时,我得到了这个:

Processing 3.0 AES-128 ECB Encryption/Decryption Example
++++++++++++++++++++++++++++++++
Original Message: 0123456789012345
Key: 2222222222222222
key in bytes: [B@2a139a55
==========================
Encrypted String (base 64): Ouril+UTDF8htLzEhiRj7w==
length: 16
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
    at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1016)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:960)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at main.ForTest.main(ForTest.java:46)

Any ideas?有任何想法吗? Thanks!谢谢!

I was able to get this working after like a week - working Arduino documentation on integration with other systems is crap : )大约一个星期后我就可以开始工作了——关于与其他系统集成的工作 Arduino 文档是废话:)

Working Arduino code:工作 Arduino 代码:

#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();
}

Working Java code:工作Java代码:

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;
}

Working on the return process now.

You call the Java side with this code:

final String decryptedText = AES.decrypt(encryptedStr, "12345678123456781234567812345678"); System.out.println("Decrypted AES ECB String: "); System.out.println(decryptedText);

Wanted to provide this for any poor slob who finds him/herself in the same boat : )想为任何发现自己在同一条船上的可怜的懒鬼提供这个:)

Hope this helps!希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM