Jab*_*alr 5 php aes dart flutter
任何人都可以帮助我找出使用 AES-256-CBC 在 PHP 中加密的数据的解密算法。我尝试了很多不同的方法,但我认为在尝试复制在 Dart 中重新创建 Key/IV 的方法时我搞砸了,并且不断收到异常,例如:
RangeError (end): Invalid value: Not in inclusive range 0..16:
Run Code Online (Sandbox Code Playgroud)
进行加密的PHP代码(由于加密字符串由第三方提供,因此无法更改)如下:
function encrypt( $string, $encrypt=true) {
$secret_key = 'SuperSecretKey';
$secret_iv = 'SuperSecretBLOCK';
$output = false;
$encrypt_method = "AES-256-CBC";
$key = hash( 'sha256', $secret_key );
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
if($encrypt) {
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
} else {
$output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
}
return $output;
}
Run Code Online (Sandbox Code Playgroud)
例如,如果调用 PHP 中的加密例程来加密字符串“This is a Test!”,则结果将是:
ZHArWURDY2FkelBtSGY5c1AzdTNBZz09
Run Code Online (Sandbox Code Playgroud)
我试图在 Dart 中解密的正是这个结果,但没有任何运气!
到目前为止,这是我所得到的导致上面提到的异常的原因:
import 'package:encrypt/encrypt.dart';
import 'package:crypto/crypto.dart';
import 'dart:convert' show utf8;
String extractPayload(String payload) {
String strPwd = 'SuperSecretKey';
String strIv = 'SuperSecretBLOCK';
var iv = sha256.convert(utf8.encode(strIv));
var key = sha256.convert(utf8.encode(strPwd));
IV ivObj = IV.fromUtf8(iv.toString());
Key keyObj = Key.fromUtf8(key.toString());
final encrypter = Encrypter(AES(keyObj));
final decrypted = encrypter.decrypt(Encrypted.from64(payload), iv: ivObj);
print(decrypted);
return decrypted;
}
Run Code Online (Sandbox Code Playgroud)
欢迎任何建议,谢谢
PHP 代码有许多不必要的弱点,使移植变得复杂:
hash函数的默认值。将结果作为二进制数据返回更有意义(但为此,必须将第三个参数显式设置为TRUE)。在这种情况下,以十六进制字符串形式返回有两个缺点:openssl_encrypt默认情况下 Base64 对密文进行编码,openssl_decrypt默认情况下需要 Base64 编码的密文。可以使用 flag 禁用此功能OPENSSL_RAW_DATA,但当前代码中并非如此。同时在加密时对密文进行了显式Base64编码,因此是双重Base64编码的。类似地,在解密密文时,它是显式 Base64 解码的,因此它也是双重 Base64 解码的。这种冗余是没有意义的,只会不必要地增加密文并降低性能。此外,Dart 代码假定了错误的默认值:加密包使用 SIC(或 CTR)作为默认模式。由于 CBC 是在 PHP 代码中指定的,因此必须在 Dart 代码中显式指定此模式。
以下 Dart 实现解密密文ZHArWURDY2FkelBtSGY5c1AzdTNBZz09:
import 'package:encrypt/encrypt.dart' as EncryptPack;
import 'package:crypto/crypto.dart' as CryptoPack;
import 'dart:convert' as ConvertPack;
String extractPayload(String payload) {
String strPwd = "SuperSecretKey";
String strIv = 'SuperSecretBLOCK';
var iv = CryptoPack.sha256.convert(ConvertPack.utf8.encode(strIv)).toString().substring(0, 16); // Consider the first 16 bytes of all 64 bytes
var key = CryptoPack.sha256.convert(ConvertPack.utf8.encode(strPwd)).toString().substring(0, 32); // Consider the first 32 bytes of all 64 bytes
EncryptPack.IV ivObj = EncryptPack.IV.fromUtf8(iv);
EncryptPack.Key keyObj = EncryptPack.Key.fromUtf8(key);
final encrypter = EncryptPack.Encrypter(EncryptPack.AES(keyObj, mode: EncryptPack.AESMode.cbc)); // Apply CBC mode
String firstBase64Decoding = new String.fromCharCodes(ConvertPack.base64.decode(payload)); // First Base64 decoding
final decrypted = encrypter.decrypt(EncryptPack.Encrypted.fromBase64(firstBase64Decoding), iv: ivObj); // Second Base64 decoding (during decryption)
return decrypted;
}
Run Code Online (Sandbox Code Playgroud)
以下测试返回明文This is a Test!
String plaintext = extractPayload("ZHArWURDY2FkelBtSGY5c1AzdTNBZz09");
print(plaintext); // This is a Test!
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7726 次 |
| 最近记录: |