Reputation: 570
Trying to send data though AES encryption from Javascript to Perl. However, I am not getting any output when decoding on the Perl side.
EDIT:
JAVASCRIPT ENCRYPT
var keySize = 256;
var ivSize = 128;
var iterations = 100;
function testcrypt(){
var pass = 'testpass';
var msg = 'testmsg';
var salt = CryptoJS.lib.WordArray.random(128/8);
var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});
var iv = CryptoJS.lib.WordArray.random(128/8);
var encrypted = CryptoJS.AES.encrypt(JSON.stringify(msg), key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
// salt, iv will be hex 32 in length
// append them to the ciphertext for use in decryption
var packet = salt.toString()+'-'+ iv.toString()+'-' + encrypted.toString();
alert(packet);
}
OUTPUT IS -> 71b851532027b022c50f1a389254fca4-d8a9d7c4fa30f7d9427a5762e2c5794b-8S/JOXgDYuRloLKBiH5fYg==
PERL DECRYPT
use warnings;
use strict;
use Crypt::CBC;
use Crypt::PBKDF2;
use MIME::Base64;
print "\nGot: ".decrypt('ebdfcbd226b7dbc73e77a29d31fab723-3daf178979cb03087f5258907e73e547-CyG6R0EU9s0c8dBCAZk6Jg==', 'testpass');
print "\nGot: ".decrypt('71b851532027b022c50f1a389254fca4-d8a9d7c4fa30f7d9427a5762e2c5794b-8S/JOXgDYuRloLKBiH5fYg==', 'testpass');
sub decrypt{
my $encrypted = shift;
my $key = shift;
my($salt,$iv,$packet)=split '-',$encrypted,3;
$packet = decode_base64($packet);
my %options=(
key_len => length $key,
iv_len => length $iv,
iterations => 100,
# hash_class => 'HMACSHA2',
hash_class => 'HMACSHA1', # To match CryptoJS
);
$options{output_len} = $options{key_len} + $options{iv_len};
my $pbkdf2 = Crypt::PBKDF2->new(%options);
my $AES = Crypt::CBC->new(
#-key => $pbkdf2->PBKDF2($key,$salt),# Was Reversed
-key => $pbkdf2->PBKDF2($salt,$key),
-cipher => 'Cipher::AES',
-pbkdf => 'pbkdf2',
-header => 'none',
);
return $AES->decrypt($packet);
}
Upvotes: 1
Views: 370
Reputation: 49400
Some of the issues have already been addressed in the comments. In the meantime, some changes have been made to the code. The following bug list refers to the originally posted code:
PBKDF2()
.PBKDF2()
, implicitly with -pbkdf => 'pbkdf2'
).These bugs can be fixed as follows:
use warnings;
use strict;
use Crypt::CBC;
use Crypt::PBKDF2;
use MIME::Base64;
print "\nGot: ".decrypt('ebdfcbd226b7dbc73e77a29d31fab723-3daf178979cb03087f5258907e73e547-CyG6R0EU9s0c8dBCAZk6Jg==', 'testpass');
print "\nGot: ".decrypt('71b851532027b022c50f1a389254fca4-d8a9d7c4fa30f7d9427a5762e2c5794b-8S/JOXgDYuRloLKBiH5fYg==', 'testpass');
sub decrypt{
my $encrypted = shift;
my $pwd = shift;
# get IV, salt and ciphertext
my($salt,$iv,$packet)=split '-',$encrypted,3;
$iv = pack("H*", $iv); # Fix regarding 1.
$salt = pack("H*", $salt); # Fix regarding 1.
$packet = decode_base64($packet);
# derive key
my %options=(
output_len => 32,
iterations => 100,
hash_class => 'HMACSHA1', # Fix regarding 2.
);
my $pbkdf2 = Crypt::PBKDF2->new(%options);
my $key = $pbkdf2->PBKDF2($salt, $pwd); # Fix regarding 3.
# decrypt
my $AES = Crypt::CBC->new(
-pbkdf => 'none', # Fix regarding 4.
-key => $key,
-iv => $iv, # Fix regarding 5.
);
return $AES->decrypt($packet);
}
When the script is executed, the ciphertexts are now decrypted correctly (versions used: Crypt::CBC: 3.04, Crypt::PBKDF2: 0.161520).
The internal key derivation cannot be applied because the salt used is 16 bytes long and the internal key derivation supports only 8 byte salts (error message for other salt lengths: argument to -salt must be exactly 8 bytes long...).
In case of an 8 bytes salt the internal key derivation can be used as follows:
use warnings;
use strict;
use Crypt::CBC;
use Crypt::PBKDF2;
use MIME::Base64;
print "\nGot: ".decrypt('0dad5e7e0c105e82-665304727191506bd818cd48ac9917a0-DXF+Bh/K4ESEw1tgtp6p2Q==', 'testpass');
sub decrypt{
my $encrypted = shift;
my $pwd = shift;
# get IV, salt and ciphertext
my($salt,$iv,$packet)=split '-',$encrypted,3;
$iv = pack("H*", $iv);
$salt = pack("H*", $salt);
$packet = decode_base64($packet);
# derive key and decrypt
my $AES = Crypt::CBC->new(
-pbkdf => 'pbkdf2',
-key => $pwd,
-salt => $salt,
-hasher => 'HMACSHA1',
-iter => 100,
-header => 'none',
-iv => $iv,
);
return $AES->decrypt($packet);
}
Upvotes: 3