AES-256 CBC在PHP中加密并以Java解密,反之亦然 [英] AES-256 CBC encrypt in php and decrypt in Java or vice-versa

查看:165
本文介绍了AES-256 CBC在PHP中加密并以Java解密,反之亦然的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JAVA



  import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

class AES256JavaPhp {
public static void main(String [] args)throws Exception {
Base64 base64 = new Base64();
密码ciper = Cipher.getInstance(AES / CBC / PKCS5Padding);
SecretKeySpec key = new
SecretKeySpec(PasswordPassword.getBytes(UTF-8),AES);
IvParameterSpec iv = new IvParameterSpec
(dynamic @ dynamic @。getBytes(UTF-8),0,ciper.getBlockSize());
//加密
ciper.init(Cipher.ENCRYPT_MODE,key,iv);
byte [] encryptedCiperBytes = base64.encode
((ciper.doFinal(Hello.getBytes())));
System.out.println(Ciper:+ new String(encryptedCiperBytes));
// Decrypt
ciper.init(Cipher.DECRYPT_MODE,key,iv);
byte [] text = ciper.doFinal(base64.decode(encryptedCiperBytes));
System.out.println(解密文本:+新的String(文本));
}
}

Java输出:

  Ciper:KpgzpzCRU7mTKZePpPlEvA == 
解密文本:Hello



PHP



 <?php> 
$ cipherText = encrypt(Hello,'aes-256-cbc');
exit();

函数加密($ data,$ algo)
{
$ key ='PasswordPassword';
// $ iv = random_bytes(openssl_cipher_iv_length($ algo));
$ iv ='dynamic @ dynamic @';
$ cipherText = openssl_encrypt(
$ data,
$ algo,
$ key,
OPENSSL_RAW_DATA,
$ iv
);
$ cipherText = base64_encode($ cipherText);
printData(Ciper Text:$ cipherText);

$ cipherText = base64_decode($ cipherText);
$ plaintext = openssl_decrypt(
$ cipherText,
$ algo,
$ key,
OPENSSL_RAW_DATA,
$ iv
);
printData(解密后的纯文本:$ plaintext);
}

函数printData($ obj)
{
print_r($ obj);
}
?>

PHP输出:

  Ciper文本:ef / ENVlBn9QBFlkvoN7P2Q == 
解密后的纯文本:$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

所得到的密码是不同的,即使它们使用相同的密钥和IV。

解决方案

显然,您必须使用相同的AES密钥和IV 来确保安全会话。他们必须在客户端之间妥善安全地沟通。 无关紧要客户所写的是什么语言。您的问题不是理解密钥协商和会话建立的协议。



初始化向量不是受保护的值;即您在客户端之间进行通信时不加密。它必须使用加密的AES密钥(从某些密钥协商协议导出)以明文打包



CMS 使用 KeyTransRecipientInfo 提供此信息。 TLS 还定义了 IV建立遵循其握手。我强烈建议遵循CMS实施而不是设计的东西,几乎可以保证包含安全漏洞。






更新



现在很清楚,你很困惑为什么生成的密文不是确定性的。这是因为Java实现默认为128位加密,并提供了一个128位密钥,但是 PHP代码正在请求256位强度加密,并且只提供相同的 128位密钥。因此,PHP必须填充密钥。






更新2



根据下面的注释,下面是使用Java生成256位密钥的例子:

  KeyGenerator generator = KeyGenerator.getInstance( AES); 
generator.init(256); // AES密钥大小位数
SecretKey secKey = generator.generateKey();


JAVA

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

class AES256JavaPhp{
        public static void main(String[] args) throws Exception {
                Base64 base64 = new Base64();
                Cipher ciper = Cipher.getInstance("AES/CBC/PKCS5Padding");
                SecretKeySpec key = new
                          SecretKeySpec("PasswordPassword".getBytes("UTF-8"),"AES");
                IvParameterSpec iv = new IvParameterSpec
                      ("dynamic@dynamic@".getBytes("UTF-8"),0,ciper.getBlockSize());
            //Encrypt
                ciper.init(Cipher.ENCRYPT_MODE, key,iv);
                byte[] encryptedCiperBytes = base64.encode
                                              ((ciper.doFinal("Hello".getBytes())));
                System.out.println("Ciper : "+new String(encryptedCiperBytes));
            //Decrypt
                ciper.init(Cipher.DECRYPT_MODE, key,iv);    
                byte[] text = ciper.doFinal(base64.decode(encryptedCiperBytes));
                System.out.println("Decrypt text : "+new String(text));
          }
    }

Java output:

Ciper : KpgzpzCRU7mTKZePpPlEvA==
Decrypt text : Hello

PHP

<?php>    
        $cipherText = encrypt("Hello", 'aes-256-cbc');
        exit();

        function encrypt($data, $algo)
        {
            $key = 'PasswordPassword';
            //$iv = random_bytes(openssl_cipher_iv_length($algo));
            $iv = 'dynamic@dynamic@';
            $cipherText = openssl_encrypt(
                    $data,
                    $algo,
                    $key,
                    OPENSSL_RAW_DATA,
                    $iv
                );
        $cipherText = base64_encode($cipherText);
        printData("Ciper Text : $cipherText");

        $cipherText = base64_decode($cipherText);
        $plaintext = openssl_decrypt(
                    $cipherText,
                    $algo,
                    $key,
                    OPENSSL_RAW_DATA,
                    $iv
                );
        printData("Plain Text after decryption : $plaintext");
        }

        function printData($obj)
        {
            print_r($obj);
        }
?>

PHP output:

Ciper Text : ef/ENVlBn9QBFlkvoN7P2Q==
Plain Text after decryption : Hello

The resulting ciphers are different, even though they are using the same key and IV. How is this possible?

解决方案

Clearly you must use the same AES key and IV for a secure session. And they must be properly and securely communicated across clients. It does not matter at all what language the clients are written in. Your problem is not understanding the protocol for key agreement and session establishment.

The initialization vector is not a protected value; i.e., you are not encrypting it when communicating between clients. It must be packaged in cleartext with encrypted AES key (which you derive from some key agreement protocol).

CMS uses a KeyTransRecipientInfo to deliver this information. TLS also defines IV establishment followings its handshake. I would highly suggest following the CMS implementation instead of something contrived and almost guaranteed to contain security bugs.


Update

It is now clear that you are confused why the resulting ciphertexts are not deterministic. That is because the Java implementation is defaulting to a 128-bit encryption and has been supplied a 128-bit key, but the PHP code is requesting 256-bit strength encryption and only being supplied the same 128-bit key. Therefore, PHP must be padding the key.


Update 2

Based on your below comments, here is an example of using Java to generate a 256-bit key:

KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256); // The AES key size in number of bits
SecretKey secKey = generator.generateKey();

这篇关于AES-256 CBC在PHP中加密并以Java解密,反之亦然的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆