Perl 中的 AES 加密,具有自定义密钥和 IV

问题描述 投票:0回答:1

我在 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 个字节。)

javascript perl encryption aes
1个回答
0
投票

[这只是部分答案]

解码后的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=

所以我们现在将两者保存为相同的格式。但在密钥生成或加密方面仍然存在不同。

© www.soinside.com 2019 - 2024. All rights reserved.