如何在php和android之间加密和解密数据

时间:2018-04-18 09:00:08

标签: java php encryption

这些是用于在基于php的服务器和Android应用程序之间加密和解密数据的类。

有时php解密类不起作用:

例如,当我在android中加密“abc”或“zdf”或“091360532561524369510”时,php类无法解密来自android客户端的加密数据。

你能检查一下这些课程吗? java class:

import java.security.NoSuchAlgorithmException;

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

public class ApiCrypter
{
    private String iv= "0123456789012345";
    private String secretkey= "9876543210987654";
    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;

    public ApiCrypter()
    {
        ivspec = new IvParameterSpec(iv.getBytes());
        keyspec = new SecretKeySpec(secretkey.getBytes(), "AES");

        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public byte[] encrypt(String text) throws Exception
    {
        if(text == null || text.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] encrypted = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        }
        catch (Exception e) {
            throw new Exception("[encrypt] " + e.getMessage());
        }
        return encrypted;
    }

    public byte[] decrypt(String code) throws Exception
    {
        if(code == null || code.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] decrypted = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(hexToBytes(code));
        }
        catch (Exception e) {
            throw new Exception("[decrypt] " + e.getMessage());
        }
        return decrypted;
    }

    public static String bytesToHex(byte[] data)
    {
        if (data==null) {
            return null;
        }
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16) {
                str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            }
            else {
                str = str + java.lang.Integer.toHexString(data[i]&0xFF);
            }
        }
        return str;
    }

    public static byte[] hexToBytes(String str) {
        if (str==null) {
            return null;
        }
        else if (str.length() < 2) {
            return null;
        }
        else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i=0; i<len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            }
            return buffer;
        }
    }
}

PHP类:

<?php
class ApiCrypter
{
    private $iv  = '0123456789012345';
    private $key = '9876543210987654';

    public function __construct() 
    {
    }

    public function encrypt($str)
    { 
        $str = $this->pkcs5_pad($str);   
        $iv = $this->iv; 
        $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); 
        mcrypt_generic_init($td, $this->key, $iv);
        $encrypted = mcrypt_generic($td, $str); 
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td); 
        return bin2hex($encrypted);
    }

    public function decrypt($code)
    { 
        $code = $this->hex2bin($code);
        $iv = $this->iv; 
        $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); 
        mcrypt_generic_init($td, $this->key, $iv);
        $decrypted = mdecrypt_generic($td, $code); 
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td); 
        $ut =  utf8_encode(trim($decrypted));
        return $this->pkcs5_unpad($ut);
    }

    protected function hex2bin($hexdata)
    {
        $bindata = ''; 
        for ($i = 0; $i < strlen($hexdata); $i += 2) {
            $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
        } 
        return $bindata;
    } 

    protected function pkcs5_pad ($text)
    {
        $blocksize = 16;
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    protected function pkcs5_unpad($text)
    {
        $pad = ord($text{strlen($text)-1});
        if ($pad > strlen($text))
        {
            return false; 
        }
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad)
        {
            return false;
        }
        return substr($text, 0, -1 * $pad);
    }
}
?>

1 个答案:

答案 0 :(得分:0)

几件事:

  1. 每条消息的IV应当不同,且不可预测;从来没有硬编码。
  2. 不要在PHP中使用mcrypt。

这是解决问题的最简单方法:

  1. 获取libsodium in both languages。如果将PHP升级到7.2或更高版本,则应该自动获得Sodium扩展名(除非您的OS供应商做错了事)。
  2. 使用<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <header> <div class="Top"> <a class="active" href="#home">Home</a> <a href="#about">About</a> <a href="#contact">Contact</a> <a href="#profile">Profile</a> <input type="text" placeholder="Search.."> </div> <div style="padding-left:16px"> </div> </header> <nav> </nav> <main> </main> <aside> </aside> <footer> <center><sub id="sub2">Contact Me:</sub></center> <center><sub id="sub1">foo@example.com</sub></center> </footer> </body> </html>(或您语言中的等效API)进行加密,使用crypto_secretbox()进行解密。

这比学习使用CBC模式,初始化矢量,填充方案,RNG和密文完整性的正确方法要简单得多。