Decrypt AES-generated hex from aes-js(Javascript) to pycryptodome(Python) - javascript

So im trying to decrypt a string I cryptographed with JS in Python. I used the aes-js library. I get this: caba6777379a00d12dcd0447015cd4dbcba649857866072d. This is my JS code:
var key = aesjs.utils.utf8.toBytes("ThisKeyIs16Bytes");
console.log(`Key (bytes): ${key}`);
var text = 'psst... this is a secret';
var textBytes = aesjs.utils.utf8.toBytes(text);
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
var encryptedBytes = aesCtr.encrypt(textBytes);
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
console.log(`Hex: ${key}`);
I've tried a few things in python, but this is what I currently have:
from Crypto.Cipher import AES
ciphered_data = bytearray.fromhex('caba6777379a00d12dcd0447015cd4dbcba649857866072d')
key = b'ThisKeyIs16Bytes'
cipher = AES.new(key, AES.MODE_CTR)
original_data = cipher.decrypt(ciphered_data)
print(original_data.decode("utf-8", errors="ignore"))
But I just recieve a mess.=*լ☻ve↕-:tQɊ#¶.

The CTR mode is used. In the Pyton code the initialization of the counter is missing, i.e. the definition of the correct start value, e.g.
...
cipher = AES.new(key, AES.MODE_CTR, nonce = b'', initial_value = 5)
...
or alternatively using a Counter object:
from Crypto.Util import Counter
...
counter = Counter.new(128, initial_value = 5)
cipher = AES.new(key, AES.MODE_CTR, counter = counter)
...
With one of these two changes the decryption works.

Related

How to match Key & IV generated by C# and JS CryptoJS

I need help to find a way how to match IV and KEY from C# and JS,
with a simple C# code:
Rijndael rijndael = Rijndael.Create();
byte[] saltArray = Encoding.ASCII.GetBytes("20190925");
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes("password", saltArray, 1000);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
Console.WriteLine(BitConverter.ToString(rijndael.Key).Replace("-","").ToLower());
//Output rijndael.Key = c1b34ea814586db4a22dad37e11c7256322ab0eee3a14ed1898f93d7a264242f
Console.WriteLine(BitConverter.ToString(rijndael.IV).Replace("-","").ToLower());
//Output rijndael.IV = 063ead20a9d5f35ab83e1156ebe7c099
with a CryptoJS i can get a same KEY as C# but with the IV i don't get it why the value is not match
CryptoJS code:
let key = CryptoJS.PBKDF2('password', '20190925', {keySize:256/32, iterations:1000})
console.log('key', key.toString(CryptoJS.enc.Hex))
//Output key = 'key', 'c1b34ea814586db4a22dad37e11c7256322ab0eee3a14ed1898f93d7a264242f'
let iv = CryptoJS.PBKDF2('password', '20190925', {keySize:128/32, iterations:1000})
console.log('iv', iv.toString(CryptoJS.enc.Hex))
//Output iv = 'iv', 'c1b34ea814586db4a22dad37e11c7256'
I just think if rijndael.IV = pdb.GetBytes(16); will just get half of rijndael.Key = pdb.GetBytes(32); hex, but the value totally different
is there a way to match IV of C# using CryptoJS?
PBKDF2 must be executed for a length equal to the sum of key length and IV length. The result is divided into two parts. The first part corresponds to the key, the second part to the IV:
let keyLen = 256/32
let ivLen = 128/32
let keyiv = CryptoJS.PBKDF2('password', '20190925', {keySize:keyLen + ivLen, iterations:1000})
let key = CryptoJS.lib.WordArray.create(keyiv.words.slice(0, keyLen));
let iv = CryptoJS.lib.WordArray.create(keyiv.words.slice(keyLen, keyLen + ivLen));
console.log('keyiv:', keyiv.toString())
console.log('key :', key.toString())
console.log('iv :', iv.toString())
This results in:
keyiv: c1b34ea814586db4a22dad37e11c7256322ab0eee3a14ed1898f93d7a264242f063ead20a9d5f35ab83e1156ebe7c099
key : c1b34ea814586db4a22dad37e11c7256322ab0eee3a14ed1898f93d7a264242f
iv : 063ead20a9d5f35ab83e1156ebe7c099
which matches the result of the C# code.

verify js pbkdf2-sha256 hash with python passlib

I encrypt a random string in python file and hashit in javascript using pbkdf2-sha256 but some how the verification fails with python passlib . any idea why?
my python code is :
from passlib.hash import pbkdf2_sha256
import os,random,string
t = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in
range(7))
h = os.popen('node
D:/mojtaba/repos/restaurant_app/frontend/node_modules/a.js '+t).read()[:-2]
a = pbkdf2_sha256.verify(t,h)
print(a)
and js file contains :
var pbkdf2 = require('pbkdf2-sha256');
var salt = 'WitFCKH03htDKAVA6L3Xmg';
var algorithm = "pbkdf2-sha256";
var iterations = 29000;
var hashed = pbkdf2(process.argv[2], new Buffer(salt), iterations,
32).toString('base64');
var finalPass = '$'+algorithm +'$'+ iterations +'$'+ salt +'$'+ hashed;
console.log(finalPass)
and result is always false

Encrypt string with Blowfish in NodeJS

I need to encrypt a string but I almost get the output I desire, I read online that it has something to do with padding and iv_vector at the end to complete for the remaining 8 bytes to be same length as txtToEncrypt.
I'm using this library https://github.com/agorlov/javascript-blowfish
// function in Java that I need
// javax.crypto.Cipher.getInstance("Blowfish/CBC/NoPadding").doFinal("spamshog")
var iv_vector = "2278dc9wf_178703";
var txtToEncrypt = "spamshog";
var bf = new Blowfish("spamshog", "cbc");
var encrypted = bf.encrypt(txtToEncrypt, iv_vector);
console.log(bf.base64Encode(encrypted));
Actual output: /z9/n0FzBJQ=
What I need: /z9/n0FzBJRGS6nPXso5TQ==
If anyone has any clue please let me know. I searched all over Google all day.
Finally, here is how to encrypt a string in NodeJS with Blowfish
// Module crypto already included in NodeJS
var crypto = require('crypto');
var iv = "spamshog";
var key = "spamshog";
var text = "2278dc9wf_178703";
var decipher = crypto.createCipheriv('bf-cbc', key, iv);
decipher.setAutoPadding(false);
var encrypted = decipher.update(text, 'utf-8', "base64");
encrypted += decipher.final('base64');
console.log(encrypted);
Returns: /z9/n0FzBJRGS6nPXso5TQ==

Decrypt code , from ruby to js

does anyone know how to translate below ruby script to javascript?
source = ENCRYPTED_STRING
cipher = OpenSSL::Cipher::Cipher.new('AES-128-ECB')
cipher.decrypt
cipher.key = ['SECRET'].pack('H*')
decoded = Base64.decode64(source)
decrypted = cipher.update(decoded) + cipher.final
I'm assuming you want to encrypt a string using "SECRET" as a passphrase.
Here's an example using crypto-js:
source = ENCRYPTED_STRING
var encrypted = CryptoJS.AES.encrypt(source, "SECRET");
http://yijiebuyi.com/blog/13e2ae33082ac12ba4946b033be04bb5.html
problem solved.
function decryption(data, key) {
var iv = "";
var clearEncoding = 'utf8';
var cipherEncoding = 'base64';
var cipherChunks = [];
var decipher = crypto.createDecipheriv('aes-128-ecb', key, iv);
decipher.setAutoPadding(true);
cipherChunks.push(decipher.update(data, cipherEncoding, clearEncoding));
cipherChunks.push(decipher.final(clearEncoding));
return cipherChunks.join('');
}

AES decryption fails in forge but works in crypto-js

I am decrypting a message string at a regular interval. After studying multiple jsperf's I've noticed forge and stanford are faster than cryptojs - I need that extra speed as I am bound to support older mobile devices, so I'm attempting to migrate.
Here is the working crpto-js code:
var feed = message.data.msg;
var iv = CryptoJS.enc.Hex.parse(_iv);
var key = CryptoJS.enc.Hex.parse(_key);
var decrypted = CryptoJS.AES.decrypt(feed.substr(32), key, { iv: iv });
feed = decrypted.toString(CryptoJS.enc.Utf8);
And now the non-working forge code:
var feed = message.data.msg;
var iv = forge.util.hexToBytes(_iv);
var key = forge.util.hexToBytes(_key);
var buffer = forge.util.createBuffer( feed.substr(32) );
var cipher = forge.aes.createDecryptionCipher(key);
cipher.start( iv );
cipher.update( buffer );
cipher.finish();
feed = cipher.output.toHex();
After decryption with forge I get a random jumble of characters. While stepping through the code, the only thing of note is a failure in forge/aes.js, line 969:
if(count > (Nb << 2)) {
rval = false;
}
Is firing and returning false.
I'm at a loss here as both libraries use CBC as the default for AES so everything should just work.
Have you tried changing:
var buffer = forge.util.createBuffer( feed.substr(32) );
To:
var buffer = forge.util.createBuffer( forge.util.decode64( feed.substr(32) ) );
And changing:
feed = cipher.output.toHex();
To:
feed = cipher.output.getBytes();

Categories

Resources