【问题标题】:Secure communication between arduino and PHP using RC4 and base64使用 RC4 和 base64 在 arduino 和 PHP 之间进行安全通信
【发布时间】:2013-09-14 15:53:00
【问题描述】:

我正在尝试在 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);  
    }  
  ?>  

【问题讨论】:

    标签: php encryption arduino base64 rc4-cipher


    【解决方案1】:

    我遇到了同样的问题,我可以确认您在 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];
        }
    

    【讨论】:

    • 感谢分享,检查我对我上次工作实施的评论
    【解决方案2】:

    这是我正在使用的当前实现

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

    【讨论】:

      【解决方案3】:

      经过多次尝试都没有成功,我最终得到了以下三个代码:

      • Arduino 代码实现了 RC4 (adapted from this C code) 并将加密结果编码为 Base64
      • 解码base64和解密RC4的PHP代码
      • HTML 来测试 PHP(最终它将成为 ESP32 Webserver 的索引)。注意力!在 URL 中发送 Base64 可能很危险,因为字符 '+' '/' '=' 可能会产生问题,因此请确保您阅读此帖子 Base64 in url 并且可能有问题的字符替换为 '.' '_' '-'

      在撰写本文时,我正在为 ESP32 版本 2.0.0 使用 Arduino 内核,请考虑如果您不使用此版本的 Base64.h,则可能存在不兼容问题 (more details here)

      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 网络服务器上的代码 (more info here)

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多