我使用Adafruit的Arduino Uno和nRF8001主板通过蓝牙连接到Android手机。我将使用它来锁定和解锁锁,我需要确保只有经过验证的设备才能启动锁定和解锁。我已经搜索了一堆,我很难找到一个明确的例子来说明我应该怎么做才能验证连接设备。目前我已将Arduino连接到锁定,每当Android手机连接时,都可以锁定和解锁。
我想到的过程如下:
[编辑] 我已经完成了更多的研究和工作,并从security.stackexchange的建议中决定使用AES进行加密。我正在使用this Arduino library和this 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代码似乎涉及更多,如创建密钥和盐。这两个库都非常通用,我不知道如何使它们以相同的方式加密。
我有几个问题希望能帮助我解决这个问题:
Arduino代码中的PBE迭代计数在哪里?我不是真的 看到图书馆里的任何东西。我需要自己实现吗?一世 看到&#34; test_vectors&#34;图书馆的一个例子 以下一点代码。这是迭代吗?
for (int j = 0 ; j < 1000 ; j++)
{
succ = aes.encrypt (plain, cipher) ;
aes.copy_n_bytes (plain, cipher, 16) ;
}
答案 0 :(得分:1)
如果要将加密消息从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 () ;
}
}
<强>爪哇强>
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输出
将代码放入Encryptor3.java,然后从命令行
macbookproz:aes_cbc_128 matteo$ javac Encryptor3.java
macbookproz:aes_cbc_128 matteo$ java Encryptor3
message (hex): 6bc1bee22e409f96e93d7e117393172a
key (hex): 2b7e151628aed2a6abf7158809cf4f3c
iv (hex): 000102030405060708090A0B0C0D0E0F
match (hex): 7649abac8119b246cee98e9b12e9197d
Encrypted (hex): 7649abac8119b246cee98e9b12e9197d
Decrypted (hex): 6bc1bee22e409f96e93d7e117393172a