簡體   English   中英

使用 RC4 和 base64 保護 arduino 和 PHP 之間的通信

[英]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;
};
;

經過多次嘗試但沒有成功,我最終得到了以下三個代碼:

  • Arduino 代碼實現了 RC4(改編自此C 代碼)並將加密結果編碼為 Base64
  • 解碼base64和解密RC4的PHP代碼
  • 用於測試 PHP 的 HTML(最終它將成為 ESP32 Webserver 的索引)。 注意力! 在 URL 中發送 Base64 可能很危險,因為字符'+' '/' '='可能會產生問題,因此請確保您在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM