gpt4 book ai didi

android - Arduino 到 Android 的安全蓝牙连接

转载 作者:行者123 更新时间:2023-11-29 01:36:27 32 4
gpt4 key购买 nike

我正在使用 Adafruit 的 Arduino Uno 和 nRF8001 板通过蓝牙连接到 Android 手机。我将使用它来锁定和解锁锁,我需要确保只有经过验证的设备才能启动锁定和解锁。我搜索了很多,但找不到一个明确的例子来说明我应该如何验证连接设备。目前,我将 Arduino 连接到锁上,只要连接 Android 手机,就可以锁定和解锁。

我想到的过程如下。

  1. Android 尝试连接到 Arduino
  2. Arduino 看到请求并向 Android 设备发送一个随机字符串
  3. Android 使用共享 key 加密字符串并将其发送回 Arduino
  4. Arduino 解密加密的字符串并验证它是否与它发送的原始字符串相匹配,如果它继续进行并连接/继续锁定或解锁。

[编辑]我做了很多研究和工作,根据 security.stackexchange 的建议,我决定使用 AES 进行加密。我正在使用 this Arduino librarythis Android library 我对在 Arduino 和 Android 编程中使用的两个库应该使用什么配置感到有点困惑。

我设置的 Arduino 代码用于测试加密和解密:

#include <AES.h>

AES aes ;

byte key[] =
{
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
} ;

byte plain[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
} ;

byte my_iv[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
} ;

char PassString[] = "This is hard to believe but true";
char Message[] = "We, the Fairies, blithe and antic Of dimensions not gigantic, Th";

byte cipher [4*N_BLOCK] ;
byte check [4*N_BLOCK] ;

int bits = 128;
int blocks = 4;

void loop ()
{}


void setup ()
{
Serial.begin (9600) ;
Serial.println ("Starting encryption...") ;

byte iv [N_BLOCK] ;

// Pass the key into the byte array
for (int i = 0; i < 32; i++) {
key[i] = PassString[i];
}

print_value ("KEY = ", key, 256) ;

for (int i = 0; i < 64; i++) {
plain[i] = Message[i];
}

// Set Key
byte succ = aes.set_key (key, bits) ;

// Encrypt
for (byte i = 0 ; i < 16 ; i++)
iv[i] = my_iv[i] ;
succ = aes.cbc_encrypt (plain, cipher, blocks, iv) ;

// Decrypt
for (byte i = 0 ; i < 16 ; i++)
iv[i] = my_iv[i] ;
succ = aes.cbc_decrypt (cipher, check, blocks, iv) ;

// Prints the plain, ciper, decrypted, and IV
for (byte ph = 0 ; ph < (blocks == 1 ? 3 : 4) ; ph++)
{
for (byte i = 0 ; i < (ph < 3 ? blocks*N_BLOCK : N_BLOCK) ; i++)
{
byte val = ph == 0 ? plain[i] : ph == 1 ? cipher[i] : ph == 2 ? check[i] : iv[i] ;
Serial.print (val>>4, HEX) ; Serial.print (val&15, HEX) ; Serial.print (" ") ;
}
Serial.println () ;
}

}

char * hex = "0123456789abcdef" ;
void print_value (char * str, byte * a, int bits)
{
Serial.print (str) ;
bits >>= 3 ; //bits goes from decimal 128 to decimal 16
for (int i = 0 ; i < bits ; i++)
{
// of ex. 0xb9 prints b then 9
byte b = a[i] ;
Serial.print (hex [b >> 4]) ;
Serial.print (hex [b & 15]) ;
}
Serial.println () ;
}

我的 Android 程序几乎是从上面的链接中逐字记录的。

我可以让他们都加密和解密他们自己的消息,但他们的设置似乎非常不同,无法相互加密。 Android 代码似乎涉及更多内容,例如创建 key 和盐。这两个库都非常通用,我不确定如何让它们以相同的方式加密。

我有几个问题希望能帮助我解决这个问题:

  1. Arduino 代码中的“ block ”与 Android 有什么关系实现?
  2. 根据我读到的内容,从 Arduino 上解密密文我需要发送 Android、密文、IV 和 PBE迭代次数。这是正确的吗?
  3. Android 代码获取我的 key 并使用一堆 SecretKeys 函数我认为将其随机化并使其更安全。如果我有将 key 存储在 Arduino 上,我需要为此操心吗?
  4. Arduino 代码中的 PBE 迭代计数在哪里?我真的不看图书馆里的任何东西。我需要自己实现吗?我在库的“test_vectors”示例中看到了一个部分下面的代码。这是迭代吗?

    for (int j = 0 ; j < 1000 ; j++)
    {
    succ = aes.encrypt (plain, cipher) ;
    aes.copy_n_bytes (plain, cipher, 16) ;
    }

最佳答案

如果你想从 Android 向 Arduino 发送加密消息,你必须确保你在两端使用相同的参数。

我从 Vladimir Klykov 中提取了一些测试向量然后使用 Arduino(使用 AES library )和 Java 进行加密和解密。

两个库都可以设置为 CBC,在两端使用 16 字节的十六进制向量,你不会有填充问题。

Arduino

#include <AES.h>

AES aes ;

//2b7e151628aed2a6abf7158809cf4f3c
byte key[] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
};

//6bc1bee22e409f96e93d7e117393172a
byte plain[] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
};

//000102030405060708090A0B0C0D0E0F
byte my_iv[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
};

byte cipher [N_BLOCK] ;
byte check [N_BLOCK] ;

void loop ()
{
}

void setup ()
{
Serial.begin (115200) ;

while (!Serial) ;
Serial.println ("Ready") ;

Serial.print("N_BLOCK: ") ;
Serial.println (N_BLOCK) ;

prekey (128, 2) ;
}

void prekey (int bits, int blocks)
{
byte iv [N_BLOCK] ;

long t0 = micros () ;
byte succ = aes.set_key (key, bits) ;
long t1 = micros()-t0 ;
Serial.print ("set_key ") ; Serial.print (bits) ; Serial.print (" ->") ; Serial.print ((int) succ) ;
Serial.print (" took ") ; Serial.print (t1) ; Serial.println ("us") ;
t0 = micros () ;
if (blocks == 1)
succ = aes.encrypt (plain, cipher) ;
else
{
for (byte i = 0 ; i < 16 ; i++)
iv[i] = my_iv[i] ;
succ = aes.cbc_encrypt (plain, cipher, blocks, iv) ;
}
t1 = micros () - t0 ;
Serial.print ("encrypt") ; Serial.print (" ->") ; Serial.print ((int) succ) ;
Serial.print (" took ") ; Serial.print (t1) ; Serial.println ("us") ;

t0 = micros () ;
if (blocks == 1)
succ = aes.decrypt (cipher, plain) ;
else
{
for (byte i = 0 ; i < 16 ; i++)
iv[i] = my_iv[i] ;
succ = aes.cbc_decrypt (cipher, check, blocks, iv) ;
}
t1 = micros () - t0 ;
Serial.print ("decrypt") ; Serial.print (" ->") ; Serial.print ((int) succ) ;
Serial.print (" took ") ; Serial.print (t1) ; Serial.println ("us") ;

for (byte ph = 0 ; ph < 5 ; ph++)
{
Serial.print(ph == 0 ? "plain: " : ph == 1 ? "key: " : ph == 2 ? "iv: " : ph == 3 ? "enc: " : "dec: ") ;
for (byte i = 0 ; i < (blocks-1)*N_BLOCK ; i++)
{
byte val = ph == 0 ? plain[i] : ph == 1 ? key[i] : ph == 2 ? my_iv[i] : ph == 3 ? cipher[i] : check[i] ;
Serial.print (val>>4, HEX) ; Serial.print (val&15, HEX) ;
}
Serial.println () ;
}
}

Java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.math.*;

public class Encryptor3 {

public static byte[] hexStringToByteArray(String hexInputString){
byte[] bts = new byte[hexInputString.length() / 2];

for (int i = 0; i < bts.length; i++) {
bts[i] = (byte) Integer.parseInt(hexInputString.substring(2*i, 2*i+2), 16);
}

return bts;
}

public static String byteArrayToString(byte[] byteArray) {
StringBuilder str = new StringBuilder();

for (int i = 0; i < byteArray.length; i++) {
str.append((char) byteArray[i]);
}

return str.toString();
}

public static String byteArrayToHexString(byte[] arg) {
int l = arg.length * 2;
return String.format("%0"+l+"x", new BigInteger(1, arg));
}

public static byte[] encrypt(byte[] key1, byte[] key2, byte[] value) {
try {
IvParameterSpec iv = new IvParameterSpec(key2);
SecretKeySpec skeySpec = new SecretKeySpec(key1, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

byte[] encrypted = cipher.doFinal(value);

return encrypted;

} catch (Exception ex) {
ex.printStackTrace();
}

return null;
}

public static byte[] decrypt(byte[] key1, byte[] key2, byte[] encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(key2);
SecretKeySpec skeySpec = new SecretKeySpec(key1, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

byte[] original = cipher.doFinal(encrypted);

return original;

} catch (Exception ex) {
ex.printStackTrace();
}

return null;
}

public static String toHex(String arg) {
int l = arg.length() * 2;

return String.format("%0"+l+"x", new BigInteger(1, arg.getBytes()));
}

public static String HexStringToString (String arg) {
StringBuilder output = new StringBuilder();
for (int i = 0; i < arg.length(); i+=2) {
String str = arg.substring(i, i+2);
output.append((char)Integer.parseInt(str, 16));
}

return output.toString();
}


public static void main(String[] args) {
// source: http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
String message = "6bc1bee22e409f96e93d7e117393172a"; // 16 byte = 128 bit key
//String message = toHex("Hello00000000000");
String key1 = "2b7e151628aed2a6abf7158809cf4f3c";
String iv = "000102030405060708090A0B0C0D0E0F";
String match = "7649abac8119b246cee98e9b12e9197d";

System.out.print("message (hex): "); System.out.println(message);
System.out.print("key (hex): "); System.out.println(key1);
System.out.print("iv (hex): "); System.out.println(iv);
System.out.print("match (hex): "); System.out.println(match);
System.out.println();

byte[] enc_message_ba = encrypt(hexStringToByteArray(key1), hexStringToByteArray(iv), hexStringToByteArray(message));
System.out.print("Encrypted (hex): "); System.out.println(byteArrayToHexString(enc_message_ba));
System.out.println();

byte[] dec_message_ba = decrypt(hexStringToByteArray(key1), hexStringToByteArray(iv), enc_message_ba);
System.out.print("Decrypted (hex): "); System.out.println(byteArrayToHexString(dec_message_ba));
}
}

Arduino 输出

在Arduino中安装AES库并照常运行

Ready
N_BLOCK: 16
set_key 128 ->0 took 596us
encrypt ->0 took 1136us
decrypt ->0 took 1548us
plain: 6BC1BEE22E409F96E93D7E117393172A
key: 2B7E151628AED2A6ABF7158809CF4F3C
iv: 000102030405060708090A0B0C0D0E0F
enc: 7649ABAC8119B246CEE98E9B12E9197D
dec: 6BC1BEE22E409F96E93D7E117393172A

Java 输出

将代码放在 Encryptor.java 中,然后从命令行

javac Encryptor.java 
java Encryptor
message (hex): 6bc1bee22e409f96e93d7e117393172a
key (hex): 2b7e151628aed2a6abf7158809cf4f3c
iv (hex): 000102030405060708090A0B0C0D0E0F
match (hex): 7649abac8119b246cee98e9b12e9197d

Encrypted (hex): 7649abac8119b246cee98e9b12e9197d

Decrypted (hex): 6bc1bee22e409f96e93d7e117393172a

关于android - Arduino 到 Android 的安全蓝牙连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27652105/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com