使用自定义Key和IV在Perl中进行AES加密

tquggr8v  于 2023-10-24  发布在  Perl
关注(0)|答案(1)|浏览(166)

我在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=

(92 base64编码之前的字节。)
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==

(61 base64编码之前的字节。)

mm9b1k5b

mm9b1k5b1#

  • 使用encode_base64( ..., "" )避免添加换行符和尾随LF。(已在OP中修复。)
  • 您可以反向调用->PBKDF2的参数顺序。
  • 您要求Crypt::CBC使用PBKDF 2,尽管已经应用了它。应该使用-pbkdf => 'none'
  • 你生成了一个长度错误的密钥。128/32应该是128/8。
  • 当使用的密钥长度不是最大的时候,你需要告诉Crypt::CBC。应该使用-keysize => length( $key )
  • 你在JS版本中存储了IV和salt的十六进制,但在Perl版本中存储了原始IV和salt。

[感谢@Topaco识别其中的大部分。
固定版本:

use strict;
use warnings;
use feature qw( say );

use Crypt::CBC    qw( );
use Crypt::PBKDF2 qw( );
use MIME::Base64  qw( encode_base64 );

my $plaintext = 's3cret';
my $password  = 'MyPassword';

#my $iv   = Crypt::CBC->random_bytes( 16 );
#my $salt = Crypt::CBC->random_bytes( 16 );
my $iv   = pack( "H*", "43c9ccba630fe1cd61fc2bdb90121c6f" );  # For testing.
my $salt = pack( "H*", "5c788a415851e909d9c7951717714204" );  # For testing.

my $pbkdf2 = Crypt::PBKDF2->new(
   output_len => 128 / 8,
   iterations => 1000,
);

my $key = $pbkdf2->PBKDF2( $salt, $password );

my $cipher = Crypt::CBC->new(
   -cipher  => 'Cipher::AES',
   -header  => 'none',
   -pbkdf   => 'none',
   -keysize => length( $key ),
   -key     => $key,
   -iv      => $iv,
);

my $ciphertext = $cipher->encrypt( $plaintext );

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::qT1Vtod7ihS2wvtwmlnPow==
92
NDNjOWNjYmE2MzBmZTFjZDYxZmMyYmRiOTAxMjFjNmY6OjVjNzg4YTQxNTg1MWU5MDlkOWM3OTUxNzE3NzE0MjA0OjpxVDFWdG9kN2loUzJ3dnR3bWxuUG93PT0=

相关问题