[英]Secure communication between arduino and PHP using RC4 and base64
我正在嘗試在 Arduino 和 PHP 之間進行適度安全的通信。 由於 Arduino 電源不足,我無法使用 SSL。 所以我想使用 RC4 來加密來自 PHP 的數據,然后接收到 Arduino 並解密。 還從 Arduino 加密並發送到 PHP。
問題是從 PHP 發送的加密數據,在 Arduino 中不一致。
在 PHP 上,我在 base64 中獲得 HesshwkfFk8Q,在 Arduino 中我在 base64 中獲得 nZcwrlpZEr0V。 當它們應該相等時不同的結果。
我想我有一個錯誤的 Arduino RC4 實現。 我正在使用這個https://github.com/adamvr/arduino-base64
這是代碼:
阿杜諾
#include <Base64.h>
unsigned char S[256];
char has[512];
#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
void rc4(char *key, char *data){
int i,j;
for (i=0;i<256;i++){
S[i] = i;
}
j = 0;
for (i=0;i<256;i++){
j = (j+S[i]+key[i%strlen(key)]) %256;
S_SWAP(S[i],S[j]);
}
i = j = 0;
for (int k=0;k<strlen(data);k++){
i = (i+1) %256;
j = (j+S[i]) %256;
S_SWAP(S[i],S[j]);
has[k] = data[k]^S[(S[i]+S[j]) %256];
}
has[strlen(data)+1] = '\0';
}
void setup() {
Serial.begin(9600);
char key[] = "Hello";
char sdata[] = "secretMsg";
rc4(key,sdata);
Serial.print("Encrypted : ");
char out[100];
base64_encode(out,has,strlen(has));
Serial.println(out);
char out2[100];
base64_decode(out2,out,strlen(out));
rc4(key,out2);
Serial.print("Decrypted : ");
Serial.println(has);
}
void loop(){
}
PHP
<?php
$key = 'Hello';
$msg = 'secretMsg';
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
?>
我遇到了同樣的問題,我可以向您確認您在 Arduino 中的 RC4 函數是錯誤的,您可以改用它:
unsigned char S[256];
unsigned int i, j;
void swap(unsigned char *s, unsigned int i, unsigned int j) {
unsigned char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
/* KSA */
void rc4_init(unsigned char *key, unsigned int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;
for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}
/* PRGA */
unsigned char rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);
return S[(S[i] + S[j]) & 255];
}
這是我正在使用的當前實現
#define SWAP(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
class RC4
{
public:
RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
virtual ~RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
char *Encrypt(char *pszText,const char *pszKey)
{
i=0, j=0,n = 0;
ilen = (int)strlen(pszKey);
for (m = 0; m < 256; m++)
{
*(key + m)= *(pszKey + (m % ilen));
*(sbox + m) = m;
}
for (m=0; m < 256; m++)
{
n = (n + *(sbox+m) + *(key + m)) &0xff;
SWAP(*(sbox + m),*(sbox + n));
}
ilen = (int)strlen(pszText);
for (m = 0; m < ilen; m++)
{
i = (i + 1) &0xff;
j = (j + *(sbox + i)) &0xff;
SWAP(*(sbox+i),*(sbox + j));
k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
if(k == *(pszText + m))
k = 0;
*(pszText + m) ^= k;
}
return pszText;
}
char *Decrypt(char *pszText,const char *pszKey)
{
return Encrypt(pszText,pszKey) ;
}
private:
unsigned char sbox[256];
unsigned char key[256],k;
int m, n, i, j, ilen;
};
;
經過多次嘗試但沒有成功,我最終得到了以下三個代碼:
'+' '/' '='
可能會產生問題,因此請確保您在 url 中閱讀這篇文章Base64並且可能有問題的字符被替換為'.' '_' '-'
'.' '_' '-'
在撰寫本文時,我正在將 Arduino 內核用於 ESP32 2.0.0 版,請考慮如果您不使用此版本的 Base64.h,則可能存在不兼容性( 更多詳細信息請點擊此處)
Arduino代碼
#include <stdio.h>
#include <string.h>
#include "base64.h"
typedef unsigned long ULONG;
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
int i =0, j = 0;
char k[256] = {0};
unsigned char tmp = 0;
for (i=0;i<256;i++) {
s[i] = i;
k[i] = key[i%Len];
}
for (i=0; i<256; i++) {
j=(j+s[i]+k[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for(k=0;k<Len;k++) {
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s[256] = {0}; //S-box
char key[256] = "Hello";
char pData[512] = "secretMsg";
ULONG len = strlen(pData);
printf("key : %s\n", key);
printf("raw : %s\n", pData);
rc4_init(s,(unsigned char *)key,strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("encrypt : %s\n", pData);
base64 b;
String encoded = b.encode((unsigned char *)pData, strlen(pData));
Serial.println(encoded);
rc4_init(s,(unsigned char *)key, strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("decrypt : %s\n",pData);
return 0;
}
void setup(){
Serial.begin(115200);
main();
}
void loop(){
}
PHP代碼
<?php
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
if(isset($_POST['base'])) {
$key = 'Hello';
$msg_revealed = $_POST['base'];
rc4_decrypt($key, base64_decode($msg_revealed)) //decode form base64 and decrypt
$msg = 'secretMsg'; //for testing
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
}
?>
用於測試的 HTML 代碼以及最終將托管在 ESP32 網絡服務器上的代碼( 更多信息在這里)
<html >
<head>
<title>test Base64</title>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='generator' content='Geany 1.36' />
</head>
<body>
<form action='https://www.yourwebsite.com/base64.php' method='post' id='downloadForm'>
<input hidden name='base' value='PASS_THE_URL_BASE64_ENCRYPTED_STRING_HERE'>
</form>
<div style='text-align: center;'><button type='button' class='btn btn-danger' onclick='sendBaseForm()'>TEST</button></div>
</body>
<script>
function sendBaseForm(){
document.getElementById('downloadForm').submit();
}
</script>
</html>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.