简体   繁体   English

使用Java和PHP的AES CBC 128位加密

[英]AES CBC 128 bit encryption using Java and PHP

I have recently used the AES CBC 128 algorithm in Java in order to cipher data. 我最近在Java中使用了AES CBC 128算法来加密数据。 Now I need to rebuild that algorithm in PHP, but I have no idea how, because PHP algorithms on the internet return different results. 现在,我需要用PHP重建该算法,但是我不知道该怎么做,因为互联网上的PHP算法返回不同的结果。 Maybe you can help me. 也许你可以帮我。

This is the Java-code to encrypt: 这是要加密的Java代码:

private SecretKeySpec secretKey;
private IvParameterSpec ivSpec;

public void setKey(String myKey) {
    MessageDigest sha = null;
    try {
        byte[] key = myKey.getBytes("UTF-8");
        sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);
        secretKey = new SecretKeySpec(key, "AES");

        byte[] iv = new String("1010101010101010").getBytes("UTF-8");
        ivSpec = new IvParameterSpec(iv);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

public String encrypt(String strToEncrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        return Base64.encode(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public String decrypt(String strToDecrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        return new String(cipher.doFinal(Base64.decode(strToDecrypt)));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static void main(String[] args) {

    AESText aes = new AESText();
    final String secretKey = "com.secure.test.projectjasdS/FjkGkGhkGjhG786Vjfg=tjGFGH";
    aes.setKey(secretKey);

    String originalString = "test set se ts et set s et se";
    String encryptedString = aes.encrypt(originalString);
    String decryptedString = aes.decrypt(encryptedString);

    System.out.println("origin: " + originalString);
    System.out.println("encrypted: " + encryptedString);
    System.out.println("decrypted: " + decryptedString);
}

This is my php code: 这是我的PHP代码:

    protected $key;
    protected $method = 'AES-128-CBC';
    protected $iv = '1010101010101010';
    protected $option = OPENSSL_CIPHER_AES_128_CBC;

    function __construct($key)
    {
        $this->key = $key;
    }

    public function encrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $enc = openssl_encrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return base64_encode($enc);
    }

    public function decrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $data = base64_decode($data);
        $dec = openssl_decrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return $dec;
    }

When I encrypted data from java encryption, This result cannot decrypt on Php decryption. 当我从Java加密中加密数据时,此结果无法通过Php解密进行解密。

Can you guys possibly help me with building a PHP script, that returns the same results with java encryption? 你们能帮我建立一个PHP脚本,用Java加密返回相同的结果吗?

At first glance I see three issues here: 乍一看,我在这里看到三个问题:

First : you are not using the same mode: in java you have AES/ECB/PKCS5Padding whereas your php uses AES-128-CBC . 首先 :您没有使用相同的模式:在Java中,您具有AES/ECB/PKCS5Padding而您的php使用AES-128-CBC

Second : you probably aren't using the same IV's in the Java and PHP code (IV's are irrelevant for ECB, but once you switch your java to CBC you will need it): 第二 :您可能没有在Java和PHP代码中使用相同的IV(IV与ECB无关,但是一旦将Java切换为CBC,您将需要它):

You have $iv = '1010101010101010' (which is then passed to openssl) in your php but nothing like that in your java. 您的php中有$iv = '1010101010101010' (然后传递给openssl),但是在Java中却没有类似的东西。

At the very least, you will probably need something like that in your Java part as well: 至少,您在Java部分中可能还需要类似的东西:

cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv))

with iv being a byte[] containing your IV bytes. iv是包含您的IV字节的byte[]

Third : once the problems above are addressed, padding may be the next breaking thing: your java cipher specification mentions PKCS5Padding . 第三 :一旦解决了上述问题,填充可能是下一个突破性的事情:您的Java密码规范提到了PKCS5Padding You need to make sure that both of your counterparts use the same. 您需要确保两个对方都使用相同的内容。

edit: Fourth : One more issue is the way you derive the key bits to be used. 编辑: 第四 :另一个问题是您得出要使用的密钥位的方式。 In java you take the first 16 bytes of a sha1-hash, and in php you just pass $key to openssl. 在Java中,您采用sha1-hash的前16个字节,而在php中,只需将$key传递给openssl。 openssl might be deriving the encryption key in a different way. openssl可能以另一种方式派生加密密钥。


When building cryptography-related tools using block ciphers, it's always nice to revisit classics like Block cipher mode of operation and Padding on Wikipedia, to get a sense of what is going on under the hood. 使用块密码构建与密码学相关的工具时,最好回顾一下经典的块密码操作模式和Wikipedia上的填充等经典知识,以了解幕后情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM