java - Java 中的加密和 Flutter 中的解密 (AES-256)
问题描述
我正在尝试在我的代码中实现加密,我使用 java 作为移动应用程序的后端和 dart,但我无法在颤动中解密代码。
这是用于加密的 java 代码 此 java 代码取自此博客。
public void encrypt(String item) throws Exception {
byte[] ivBytes;
String password="Hello";
/*you can give whatever you want for password. This is for testing purpose*/
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
byte[] saltBytes = bytes;
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(),saltBytes,65556,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
System.out.println("saltBytes : " + saltBytes);
//encrypting the word
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
System.out.println("ivBytes : " + ivBytes);
byte[] encryptedTextBytes = cipher.doFinal(item.getBytes("UTF-8"));
//prepend salt and vi
byte[] buffer = new byte[saltBytes.length + ivBytes.length + encryptedTextBytes.length];
System.arraycopy(saltBytes, 0, buffer, 0, saltBytes.length);
System.arraycopy(ivBytes, 0, buffer, saltBytes.length, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, buffer, saltBytes.length + ivBytes.length, encryptedTextBytes.length);
String val = new Base64().encodeToString(buffer);
System.out.println(val);
}
现在在 dart 中,我使用了多个插件,但无法解密 dart 中的代码。对于 dart 解密,我从这个stackoverflow 讨论中获取了代码。
Dart 的实现是这样的
static Uint8List decrypt(String ciphertext,) {
Uint8List ciphertextlist = base64.decode(ciphertext);
print('ciphertextlist => $ciphertextlist');
Uint8List key = generateKey("Hello");
print('key => $key');
CBCBlockCipher cipher = new CBCBlockCipher(new AESFastEngine());
int iv = cipher.blockSize;
Uint8List ivIntList = Uint8List.fromList(iv.toString().codeUnits);
ParametersWithIV<KeyParameter> params =
new ParametersWithIV<KeyParameter>(new KeyParameter(key), ivIntList);
PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>
paddingParams =
new PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>(
params, null);
PaddedBlockCipherImpl paddingCipher =
new PaddedBlockCipherImpl(new PKCS7Padding(), cipher);
paddingCipher.init(false, paddingParams);
var val = paddingCipher.process(ciphertextlist);
print('val => $val');}
static Uint8List generateKey(String passphrase) {
Uint8List passphraseInt8List = Uint8List.fromList(passphrase.codeUnits);
Uint8List salt = Uint8List.fromList('20'.codeUnits);
KeyDerivator derivator = PBKDF2KeyDerivator(HMac(SHA1Digest(), 16));
Pbkdf2Parameters params = Pbkdf2Parameters(salt, 65556, 256);
derivator.init(params);
return derivator.process(passphraseInt8List);
运行代码后,我收到此错误。
Invalid argument(s): Initialization vector must be the same length as block size
解决方案
Dart 代码缺少盐、IV 和密文的分离。添加decrypt()
:
var salt = ciphertextlist.sublist(0, 20);
var iv = ciphertextlist.sublist(20, 20 + 16);
var encrypted = ciphertextlist.sublist(20 + 16);
必须将盐传递给generateKey()
并在那里使用以派生密钥,iv 和密文应用如下:
Uint8List key = generateKey("Hello", salt);
...
//int iv = cipher.blockSize;
//Uint8List ivIntList = Uint8List.fromList(iv.toString().codeUnits);
ParametersWithIV<KeyParameter> params = new ParametersWithIV<KeyParameter>(new KeyParameter(key), iv);
...
var val = paddingCipher.process(encrypted);
...
String decrypted = new String.fromCharCodes(val);
print(decrypted);
generateKey()
必须考虑传递的盐,而且摘要块大小和密钥大小不正确,因此需要进行以下更改:
static Uint8List generateKey(String passphrase, Uint8List salt) { // pass salt
Uint8List passphraseInt8List = Uint8List.fromList(passphrase.codeUnits);
//Uint8List salt = Uint8List.fromList('20'.codeUnits);
KeyDerivator derivator = PBKDF2KeyDerivator(HMac(SHA1Digest(), 64)); // 64 byte block size
Pbkdf2Parameters params = Pbkdf2Parameters(salt, 65556, 32); // 32 byte key size
derivator.init(params);
return derivator.process(passphraseInt8List);
}
通过这些更改,解密可以在我的机器上运行。
推荐阅读
- jenkins - 基于自定义字段的 JQL 过滤器不起作用
- php - 如何避免 WooCommerce 电子邮件模板中的样式注入
- python - 使用 Pandas 将所有列值与另一列值进行比较
- javascript - 在 UseEffect 间隔后反应 useState 不存储新值
- javascript - 我使用 js 函数收到此错误,指出它未定义
- python - 为拥抱脸模型加载标记器时出现 OSError
- javascript - TheGraph Subgraph - 如何在 ETH 区块链中部署像寿司一样的子图
- python - 如何将连接的列插入到熊猫中的数据透视表中
- vba - 在 MS word 中使用宏,我尝试使用宏来截取屏幕截图,但我能够全屏而不是特定区域
- javascript - 如何通过 React js 中的普通代码使用/创建通知/toastr?