【问题标题】:how to encrypt and decrypt data between php and android如何在php和android之间加密和解密数据
【发布时间】:2018-09-28 10:38:26
【问题描述】:

这些是我用来在基于 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;
        }
    }
}

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);
    }
}
?>

【问题讨论】:

  • 当您说“android”时,您可能指的是“java”。您需要了解 java 和 php 的人来查看您的问题。我建议你添加“java”标签。
  • 不要修剪你的解密数据。有时它会删除填充。
  • @t.m.adam 哇!没错 :) 非常非常感谢
  • 您知道,您的代码不安全。它使用固定的 IV。在适当的情况下,很容易检索明文。
  • @LukeJoshuaPark 谢谢,我是初学者,你有什么建议?

标签: java php encryption


【解决方案1】:

有几点:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-04-04
    • 2012-06-26
    • 2011-09-30
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多