java - Android 相当于 PHP 中的 AES-256-CBC-HMAC-SHA256
问题描述
我在 PHP 中完成了以下加密:
openssl_encrypt($data, "AES-256-CBC-HMAC-SHA256", $key, OPENSSL_RAW_DATA, $iv));
我可以在我的 Android 应用程序中以 JSON 格式接收该 $data。
我必须在应用程序中解密该 $data。
我正在使用如下结构:
private static final String engine = "AES";
private static final String crypto = "AES/CBC/PKCS5Padding";
[...]
public byte[] cipher(byte[] data, int mode, String key, String iv2) throws NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException {
SecretKeySpec sks = new SecretKeySpec(key.getBytes(), engine);
IvParameterSpec iv = new IvParameterSpec(iv2.getBytes());
Cipher c = Cipher.getInstance(crypto);
c.init(mode, sks, iv);
return c.doFinal(data);
}
public byte[] decrypt(byte[] data, String key, String iv) throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
return cipher(data, Cipher.DECRYPT_MODE,key,iv);
}
所以我用所需的密钥和所需的 iv 调用解密。
但是将引擎定义为“AES”并将加密定义为“AES/CBC/PKCS5Padding”会引发错误,因为它不等同于来自服务器的那个。
另一方面,将加密函数与该密码函数一起使用并随后对其进行解密确实有效,因为加密和解密是使用相同的密钥 iv、引擎和加密完成的。
哪个是 PHP 中 AES-256-CBC-HMAC-SHA256 的引擎和加密等效项?
解决方案
我正在回答你的问题,但我很困惑......你会看到:-)。
首先,我设置了一个带有 2 个加密/解密函数的简单 PHP 程序,它们使用以下算法:
$algorithm = "aes-256-cbc-hmac-sha256";
$algorithm2 = "aes-256-cbc";
代码:
<?php
// https://stackoverflow.com/questions/63135041/android-equivalent-to-aes-256-cbc-hmac-sha256-in-php
$key = "!mysecretkey#9^5usdk39d&dlf)03sL";
$iv = "Cfq84/46Qjet3EEQ1HUwSg==";
$plaintext = "The quick brown fox jumps over the lazy dog";
$algorithm = "aes-256-cbc-hmac-sha256";
echo 'encryption with algorithm: ' . $algorithm . PHP_EOL;
// encryption
$ciphertext = openssl_encrypt($plaintext, $algorithm, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'ciphertext : ' . base64_encode($ciphertext) . PHP_EOL;
// decryption
$decryptedtext = openssl_decrypt($ciphertext, $algorithm, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'cbc-256-hmac decrypt : ' . $decryptedtext . PHP_EOL . PHP_EOL;
$algorithm2 = "aes-256-cbc";
echo 'encryption with algorithm: ' . $algorithm2 . PHP_EOL;
$ciphertext2 = openssl_encrypt($plaintext, $algorithm2, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'ciphertext2: ' . base64_encode($ciphertext2) . PHP_EOL;
// decryption
$decryptedtext2 = openssl_decrypt($ciphertext2, $algorithm2, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'cbc-256 decrypt : ' . $decryptedtext2 . PHP_EOL;
?>
两者都做得很好但是 - 这让我感到困惑 - 给出相同的输出(这里用 Base64 编码):
encryption with algorithm: aes-256-cbc-hmac-sha256
ciphertext : sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV
cbc-256-hmac decrypt : The quick brown fox jumps over the lazy dog
encryption with algorithm: aes-256-cbc
ciphertext2: sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV
cbc-256 decrypt : The quick brown fox jumps over the lazy dog
在使用算法的简单Java解密方法中使用密文字符串作为输入
AES/CBC/PKCS5Padding
加密消息成功解密。因此,也许我们的一位“加密专家”能够“指出”为什么两种不同的算法会给出相同的输出。
这是Java结果:
decryptedtext: The quick brown fox jumps over the lazy dog
和Java代码:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
System.out.println("https://stackoverflow.com/questions/63135041/android-equivalent-to-aes-256-cbc-hmac-sha256-in-php");
String key = "!mysecretkey#9^5usdk39d&dlf)03sL";
String iv = "Cfq84/46Qjet3EEQ1HUwSg==";
String ciphertext = "sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV";
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(Base64.getDecoder().decode(iv));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decryptedtextByte = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
String decryptedtext = new String(decryptedtextByte);
System.out.println("decryptedtext: " + decryptedtext);
}
}
推荐阅读
- javascript - 在不循环数组的情况下优化函数
- alexa - Alexa Skill Flow Builder Linux 可用性
- javascript - 使用 REST 从 Sharepoint 列表访问名称列元素
- tensorflow - 调用 Session() 后无法打印变量
- python - 为 Python 创建独立环境
- android-studio - 在烧瓶服务器上发布 json 数据的问题
- java - 在 Chrome 中运行 IntelliJ JSP 代码而不是显示源代码
- node.js - 我需要 Meteor 的架构吗?
- c# - 将 MergeField 更改为仅文本
- angular - 如何从 Typescript / Angular 7 中的对象变量中获取类型?