我在 JavaScript 中有以下 AES 加密代码,但我似乎无法在 Perl 中获得可比较的结果。
'use strict';
const CryptoJS = require('crypto-js');
const message = 's3cret';
const aesPassword = 'MyPassword';
const salt = CryptoJS.lib.WordArray.random(16);
const iv = CryptoJS.lib.WordArray.random(16);
const key = CryptoJS.PBKDF2(aesPassword, salt, {keySize: 128/32, iterations: 1000});
const ciphertext = CryptoJS.AES.encrypt(message, key, {iv: iv}).ciphertext.toString(CryptoJS.enc.Base64);
const encryptedMessage = Buffer.from(iv + '::' + salt + '::' + ciphertext).toString('base64');
console.log("encryptedMessage:", encryptedMessage);
encryptedMessage: NDNjOWNjYmE2MzBmZTFjZDYxZmMyYmRiOTAxMjFjNmY6OjVjNzg4YTQxNTg1MWU5MDlkOWM3OTUxNzE3NzE0MjA0OjpxVDFWdG9kN2loUzJ3dnR3bWxuUG93PT0=
(base64 编码前 92 个字节。)
Perl:
use strict;
use warnings;
use Crypt::CBC;
use Crypt::PBKDF2;
use MIME::Base64;
my $message = 's3cret';
my $aesPassword = 'MyPassword';
my $salt = Crypt::CBC->random_bytes(16);
my $iv = Crypt::CBC->random_bytes(16);
my $pbkdf2 = Crypt::PBKDF2->new(output_len=>128/32, iterations => 1000);
my $key = $pbkdf2->PBKDF2($aesPassword, $salt);
my $cipher = Crypt::CBC->new(-cipher=>'Cipher::AES', -pbkdf=>'pbkdf2', -key=>$key, -iv=>$iv, -header=>'none');
my $ciphertext = encode_base64( $cipher->encrypt($message), "" );
my $encryptedMessage = encode_base64( join('::', $iv, $salt, $ciphertext), "" );
print "encryptedMessage: $encryptedMessage";
encryptedMessage: tO/jlJ3NkuJG0ZA58EDR0Do6wUf4xHb/MwWm3iyT+ejYWDo6SllMSHB0S0ZuMDVYWDRzS3ZCWlRiZz09Cg==
(base64 编码前为 61 个字节。)
[这只是部分答案]
解码后的JS字符串:
43c9ccba630fe1cd61fc2bdb90121c6f::5c788a415851e909d9c7951717714204::qT1Vtod7ihS2wvtwmlnPow==
解码的 Perl 字符串:
��㔝͒�Fѐ9�@��::�G��v�3��,����X::JYLHptKFn05XX4sKvBZTbg==
看来您在 JS 版本中使用了 iv 和 salt(小写字母)的十六进制,在 Perl 版本中使用了原始字节。这就是长度差异的原因。
等效的 Perl:
my $iv_hex = unpack( "H*", $iv );
my $salt_hex = unpack( "H*", $salt );
encode_base64( join( "::", $iv_hex, $salt_hex, $ciphertext_base64 ), "" )
字符串会有所不同,因为您使用了不同的盐。因此,让我们使用相同的 IV 和盐进行测试。
use strict;
use warnings;
use feature qw( say );
use Crypt::CBC;
use Crypt::PBKDF2;
use MIME::Base64;
my $message = 's3cret';
my $aesPassword = 'MyPassword';
#my $salt = Crypt::CBC->random_bytes( 16 );
#my $iv = Crypt::CBC->random_bytes( 16 );
my $iv = pack( "H*", "43c9ccba630fe1cd61fc2bdb90121c6f" );
my $salt = pack( "H*", "5c788a415851e909d9c7951717714204" );
my $pbkdf2 = Crypt::PBKDF2->new( output_len => 128/32, iterations => 1000 );
my $key = $pbkdf2->PBKDF2( $aesPassword, $salt );
my $cipher = Crypt::CBC->new(
-cipher => 'Cipher::AES',
-pbkdf => 'pbkdf2',
-key => $key,
-iv => $iv,
-header => 'none',
);
my $ciphertext = $cipher->encrypt($message);
my $ciphertext_base64 = encode_base64( $ciphertext, "" );
my $iv_hex = unpack( "H*", $iv );
my $salt_hex = unpack( "H*", $salt );
my $msg = join( "::", $iv_hex, $salt_hex, $ciphertext_base64 );
my $msg_base64 = encode_base64( $msg, "" );
say $msg;
say length( $msg );
say $msg_base64;
我们得到:
43c9ccba630fe1cd61fc2bdb90121c6f::5c788a415851e909d9c7951717714204::Jsy09eztbQ5QEUnzT3rOHg==
92
NDNjOWNjYmE2MzBmZTFjZDYxZmMyYmRiOTAxMjFjNmY6OjVjNzg4YTQxNTg1MWU5MDlkOWM3OTUxNzE3NzE0MjA0OjpKc3kwOWV6dGJRNVFFVW56VDNyT0hnPT0=
所以我们现在将两者保存为相同的格式。但在密钥生成或加密方面仍然存在不同。