使用 Java 和 PHP 的 AES CBC 128 位加密
AES CBC 128 bit encryption using Java and PHP
我最近在 Java 中使用 AES CBC 128 算法来加密数据。现在我需要在 PHP 中重建该算法,但我不知道如何,因为互联网上的 PHP 算法 return 不同的结果。也许你可以帮助我。
这是要加密的 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);
}
这是我的 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;
}
当我从 java 加密中加密数据时,此结果无法在 Php 解密时解密。
你们可以帮我构建一个 PHP 脚本,return 与 java 加密的结果相同吗?
乍一看,我在这里看到了三个问题:
首先:您使用的模式不同:在java中您有AES/ECB/PKCS5Padding
而您的php使用AES-128-CBC
.
Second:您可能没有在 Java 和 PHP 代码中使用相同的 IV(IV 与 ECB 无关,但是一旦您将您的 java 切换到 CBC,您将需要它):
您的 php 中有 $iv = '1010101010101010'
(然后传递给 openssl),但 java 中没有类似的东西。
至少,您的 Java 部分可能也需要这样的东西:
cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv))
其中 iv
是包含您的 IV 字节的 byte[]
。
第三:一旦上述问题得到解决,填充可能是下一个破坏性的事情:您的 java 密码规范提到 PKCS5Padding
。你需要确保你的两个对手使用相同的。
编辑:第四:还有一个问题是导出要使用的密钥位的方式。在 java 中,您获取 sha1-hash 的前 16 个字节,而在 php 中,您只需将 $key
传递给 openssl。 openssl 可能以不同的方式导出加密密钥。
在使用分组密码构建与密码学相关的工具时,重温维基百科上的 Block cipher mode of operation and Padding 等经典总是很好的,以了解幕后发生的事情。
我最近在 Java 中使用 AES CBC 128 算法来加密数据。现在我需要在 PHP 中重建该算法,但我不知道如何,因为互联网上的 PHP 算法 return 不同的结果。也许你可以帮助我。
这是要加密的 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);
}
这是我的 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;
}
当我从 java 加密中加密数据时,此结果无法在 Php 解密时解密。
你们可以帮我构建一个 PHP 脚本,return 与 java 加密的结果相同吗?
乍一看,我在这里看到了三个问题:
首先:您使用的模式不同:在java中您有AES/ECB/PKCS5Padding
而您的php使用AES-128-CBC
.
Second:您可能没有在 Java 和 PHP 代码中使用相同的 IV(IV 与 ECB 无关,但是一旦您将您的 java 切换到 CBC,您将需要它):
您的 php 中有 $iv = '1010101010101010'
(然后传递给 openssl),但 java 中没有类似的东西。
至少,您的 Java 部分可能也需要这样的东西:
cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv))
其中 iv
是包含您的 IV 字节的 byte[]
。
第三:一旦上述问题得到解决,填充可能是下一个破坏性的事情:您的 java 密码规范提到 PKCS5Padding
。你需要确保你的两个对手使用相同的。
编辑:第四:还有一个问题是导出要使用的密钥位的方式。在 java 中,您获取 sha1-hash 的前 16 个字节,而在 php 中,您只需将 $key
传递给 openssl。 openssl 可能以不同的方式导出加密密钥。
在使用分组密码构建与密码学相关的工具时,重温维基百科上的 Block cipher mode of operation and Padding 等经典总是很好的,以了解幕后发生的事情。