I've implemented this module in Drupal, but would also like to duplicate the encrypt/decrypt functionality in Perl with equivalent results (i.e. I'd like to decrypt a Drupal-AES encrypted password using a Perl module). I've tested CRYPT::Rijndael as well as CRYPT::AES, both of which return the same value -- but no where near the encrypted password value stored in Drupal's aes_password file. The drupal encryptions are "readable" (no ascii characters outside normal printable characters), but the Perl encryptions are any ascii value (1..255). If you have any clue, I can provide examples, but right now I'm looking for some direction. I'm using 128 bit Rijndael and MODE_CBC in the Perl script, which according to the phpseclib documentation should be equivalent.

Comments

dwork’s picture

Here's a little more information that I just tested with. Evidently, the plaintext password is padded to 16 bytes (32 hex)

Key: 8A80EB35BF520EDCE1E44EDD292EBEB1
plaintext: abc123## (hex equivalent = 61626331323323232020202020202020 as padded)
Perl CRYPT::AES encryption: 9a4259aeed356fee7b2b35b8931695bc (hex) = šBY®í5oî{+5¸“•¼ (text)
This is duplicated exactly using an independent AES Calculator at http://www.unsw.adfa.edu.au/~lpb/src/AEScalc/AEScalc.html

Actual Perl Program test results (MODE_CBC):
8A80EB35BF520EDCE1E44EDD292EBEB1 (16) => Š€ë5¿RÜáäNÝ).¾±
Encrypted: šBY®í5oî{+5¸“•¼
Decrypted: abc123##

The value stored in Drupal's aes_passwords file is: 0462t7UoEAQuQBXXeX9UkA==
I'm a little confused by this representation, since its neither next nor hex (base64 maybe?)

easyfit’s picture

Hello dwork

Yes the passwords are base64 encoded before they are stored in the database, so you'll have to decode the base64 before decrypting them in Perl.

Also note that the encryption key used in this module is actually a sha1 hash of the key you entered which is then substringed to the key size, like this:

$key = substr(sha1($key), 0, $ks);

Unfortunately this module is not very user friendly for what you're trying to do, I have thought about improving it for exactly this purpose (decrypting in another language/platform), but you seem to be the first one to my knowledge which is trying to do this so it hasn't been a priority.

Anyway, if you take the base64 encoding of the encrypted strings into consideration, as well as the sha1 hashing of the key, then it should work.

easyfit’s picture

And btw, yes the encrypted strings are padded as well, so you'll have to strip the garbage of of then end of the decrypted strings.

dwork’s picture

Still having some trouble matching. I've evidently missed something. Here's my Perl test script:

use Digest::SHA1 qw(sha1);
use MIME::Base64;
use Crypt::OpenSSL::AES;

$keyval = '8A80EB35BF520EDCE1E44EDD292EBEB1';
$storedpwd = '0462t7UoEAQuQBXXeX9UkA==';
$decoded64 = decode_base64($storedpwd); # Just a cross-check, should match encrypted cipher before encoding
$plaintext = 'abc123## '; # Padded

$keysha1 = substr(sha1($keyval),0,16); # same as Drupal AES module

$cipher = new Crypt::OpenSSL::AES($keysha1);
$encrypted = $cipher->encrypt($plaintext);
$encrypted64 = encode_base64($encrypted);
$decrypted = $cipher->decrypt($encrypted);

And here are the results:

ASSIGNMENTS: Key: 8A80EB35BF520EDCE1E44EDD292EBEB1
Stored Password: 0462t7UoEAQuQBXXeX9UkA== ... decoded Base64: ÓŽ¶·µ(.@×yT (should matched "Encrypted/Encrypted64 below)
Plaintext Password: abc123##
Key as SHA1(16): œ¤—˜¹Ö4#~s—¶Ž

RESULTS: AES using SHA1 key
Encrypted: ßg¹yFî(é¤ ¸Ê‰S => Encrypted64: 32e5eUbuKOmkCbjKCIkQUw==
Decrypted: abc123##

easyfit’s picture

I just realized I made a mistake, the key is not run through sha1 if you're using phpseclib instead of mcrypt (which I take it you are), sorry about that. Try using the key in its original form instead, I have no idea if phpseclib does anything to the key internally though.

The code for encrypting something in this module with phpseclib is basically just:

$phpsec = new Crypt_AES();
$phpsec->setKey($key);
$encrypted = $phpsec->encrypt($string);

And then $encrypted gets base64 encoded before being returned.

dwork’s picture

Thanks, that did it. As reference for us dummies, here are the two scripts that work independent of Drupal. Perl requires a couple of CPAN modules and PHP requires the phpseclib library.

PERL:

use MIME::Base64;
use Crypt::OpenSSL::AES;

$keyval = '8A80EB35BF520EDCE1E44EDD292EBEB1';
$stored = '0462t7UoEAQuQBXXeX9UkA==';
$base64 = decode_base64($stored);
$cipher = new Crypt::OpenSSL::AES($keyval);
$plaintext = $cipher->decrypt($base64);

PHP:

include_once './sites/all/modules/aes/phpseclib/Crypt/AES.php';

$keyval = "8A80EB35BF520EDCE1E44EDD292EBEB1";
$stored = "0462t7UoEAQuQBXXeX9UkA==";
$base64 = base64_decode($stored);

$phpsec = new Crypt_AES();
$phpsec->setKey($keyval);
$plaintext = $phpsec->decrypt($base64);

easyfit’s picture

Status: Active » Closed (works as designed)