You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Perl实现与crypto-js@4.2.0一致的AES加密输出?

如何用Perl实现与crypto-js@4.2.0一致的AES加密输出?

需求背景

以下是用于AES加密的JavaScript代码:

'use strict';
const CryptoJS = require('crypto-js');

const plaintext = 's3cret';
const password  = 'MyPassword';
//const iv   = CryptoJS.lib.WordArray.random(16);
//const salt = CryptoJS.lib.WordArray.random(16);
const iv   = CryptoJS.enc.Hex.parse("43c9ccba630fe1cd61fc2bdb90121c6f"); // 测试用固定值
const salt = CryptoJS.enc.Hex.parse("5c788a415851e909d9c7951717714204"); // 测试用固定值
const key = CryptoJS.PBKDF2(password, salt, {keySize: 128/32, iterations: 1000});
const b64ciphertext = CryptoJS.AES.encrypt(plaintext, key, {iv: iv}).ciphertext.toString(CryptoJS.enc.Base64);
console.log(b64ciphertext);

版本差异

1. 使用crypto-js@4.2.0时输出

key: 8E2dqz889iLAam1MV4wweQ==
ciphertext: eiJkaAmCVjHFKbvY/CnkvQ==

2. 使用crypto-js@4.1.1时输出

key: 8NJim/oe3/Q0+wLRq86FGg==
ciphertext: qT1Vtod7ihS2wvtwmlnPow==

已有解决方案(对应crypto-js@4.1.1)

已有Perl代码可实现与crypto-js@4.1.1一致的输出:

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

use Crypt::CBC    qw( );
use Crypt::PBKDF2 qw( );
use Mojo::Util qw(b64_encode);

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" ); # 测试用固定值
my $salt = pack( "H*", "5c788a415851e909d9c7951717714204" ); # 测试用固定值

my $pbkdf2 = Crypt::PBKDF2->new(output_len=>128/8, iterations=>1000);
my $key = $pbkdf2->PBKDF2($salt,$password);
say "key: ", b64_encode($key,'');
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 $b64ciphertext = b64_encode($ciphertext,'');

say "ciphertext: ", $b64ciphertext;

解决方案(对应crypto-js@4.2.0)

crypto-js@4.2.0修复了PBKDF2算法中密码与盐的参数顺序问题,因此Perl代码需要调整PBKDF2的调用方式,同时确保明文编码与CryptoJS一致,具体代码如下:

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

use Crypt::CBC    qw( );
use Crypt::PBKDF2 qw( );
use Mojo::Util qw(b64_encode);

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" ); # 测试用固定值
my $salt = pack( "H*", "5c788a415851e909d9c7951717714204" ); # 测试用固定值

my $pbkdf2 = Crypt::PBKDF2->new(output_len=>128/8, iterations=>1000);
# 关键修改:使用derive方法,参数顺序为密码在前、盐在后,匹配crypto-js@4.2.0的逻辑
my $key = $pbkdf2->derive($password, $salt);
say "key: ", b64_encode($key,'');
my $cipher = Crypt::CBC->new(
                 -cipher  => 'Cipher::AES',
                 -header  => 'none',
                 -pbkdf   => 'none',
                 -keysize => length($key),
                 -key     => $key,
                 -iv      => $iv
                );
# 将明文转为UTF-8编码,与CryptoJS默认行为一致
my $ciphertext = $cipher->encrypt( Encode::encode_utf8($plaintext) );
my $b64ciphertext = b64_encode($ciphertext,'');

say "ciphertext: ", $b64ciphertext;

核心修改说明

  1. PBKDF2参数顺序调整:crypto-js@4.2.0修复了旧版本中PBKDF2算法参数顺序颠倒的问题,Perl中使用Crypt::PBKDF2的derive方法(符合RFC 2898标准的密码在前、盐在后顺序)来匹配这一修正后的逻辑。
  2. 明文编码统一:CryptoJS默认将字符串转为UTF-8字节流处理,Perl代码中通过Encode::encode_utf8确保明文编码方式一致,避免因编码差异导致输出结果不同。

内容的提问来源于stack exchange,提问作者h q

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:44:54