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

X F*_* Fa 5 php java encryption

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

有时 php 解密类不起作用:

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

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

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

Sco*_*ski 1

有几件事:

  1. 每条消息的 IV 应该是不同的并且是不可预测的;从不硬编码。
  2. 不要在 PHP 中使用 mcrypt。

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

  1. 获取两种语言的 libsodium。如果您将 PHP 升级到 7.2 或更高版本,您应该自动获得 Sodium 扩展(除非您的操作系统供应商做错了什么)。
  2. 使用crypto_secretbox()(或您语言中的等效 API)进行加密、crypto_secretbox_open()解密。

这比学习正确的方法来处理 CBC 模式、初始化向量、填充方案、RNG 和密文完整性更简单。