Cryptojs encryption with Pkcs padding in angularjs - javascript

I am trying to create an encrypted request at the frontend using cryptojs using below code:
function createAesRequestPayload(jsonRequiredToEncrypt) {
var base64Key = $window.CryptoJS.lib.WordArray.random(128/8);
var ivkey = $window.CryptoJS.lib.WordArray.random(128/16);
var aesEncrypted = $window.CryptoJS.AES.encrypt(JSON.stringify(jsonRequiredToEncrypt), base64Key,
{ iv: ivkey, mode: $window.CryptoJS.mode.CBC, padding: $window.CryptoJS.pad.Pkcs7});
var iv = btoa(ivkey);
var key = btoa(base64Key);
var data = btoa(aesEncrypted.toString());
var ivAndKey = iv + "|" + key;
var header = crypt.encrypt(ivAndKey); // Using RSA
return (header + "|" + data);
}
Via this code, I am able to create request but on the server-side, I am getting an exception:
Input length must be multiple of 16 when decrypting with padded cipher
Backend is working fine for android and IOS, and I am not able to understand what I am doing wrong.
The padding used at the backend
Cipher.getInstance("AES/CBC/PKCS7Padding")
I don't have the backend with me only I can see the logs on the server.
Any help would be much appreciated.

Related

TripleDES encryption - c# and javascript differences

I have data encrypted in c#, and need to put together a demo of how to decrypt in javascript. (Note, this is just for a demo - we will not be putting keys into client side code!)
I cannot get the settings right using Crypto-js - I've tried lots of variations, but am getting nowhere.
I cannot change the c# code, so need to get the javascript to work the same way.
Current skeleton code is as follows -
C# (encrypt)
var EncryptionKey = Encoding.ASCII.GetBytes("14ggh11dd3fvv4n4aabb33a3");
var IV = Encoding.ASCII.GetBytes("312a44de");
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = EncryptionKey;
tdes.IV = IV;
byte[] buffer = Encoding.ASCII.GetBytes("test");
var ciphertext = Convert.ToBase64String(tdes.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length));
Console.WriteLine(HttpUtility.UrlEncode(ciphertext));
which generates the cipher VrB1Ih0Ll%2fQ%3d
javascript (decrypt)
function decryptByDESModeCBC(ciphertext) {
var key = '14ggh11dd3fvv4n4aabb33a3';
var iv = '312a44de'
ciphertext = decodeURIComponent(ciphertext);
var keyBytes = CryptoJS.enc.Utf8.parse(key);
var ivBytes = CryptoJS.enc.Utf8.parse(iv);
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
}, keyBytes, {
iv:ivBytes,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
function test()
{
console.log(decryptByDESModeCBC("VrB1Ih0Ll%2fQ%3d"));
}
Expected result is "test", but I am getting blank.
Any pointers would be great.
As answered by #Topaco in the comments
I needed to use CryptoJS.TripleDES instead of CryptoJS.DES

Encrypt in VB.NET Rijndael Managed and Decrypt in Javascript CryptoJS

I'm making an app that has to decrypt QRs and well... It doesn't, because i get the QR string but i cannot decrypt it.
I'm using this encryption method in VB.NET, and it works perfectly when i read an decrypt from VB.NET:
Private Function GetCodedQR(ByVal str As String) As String
Dim sToEncrypt As String = str
Dim encrypted() As Byte
' Create an Rijndael object
' with the specified key and IV.
Using rijAlg = Rijndael.Create()
rijAlg.Padding = PaddingMode.Zeros
rijAlg.Mode = CipherMode.CBC
rijAlg.KeySize = 256
rijAlg.BlockSize = 256
rijAlg.Key = System.Text.Encoding.ASCII.GetBytes("12345678912345678912345678912345")
rijAlg.IV = System.Text.Encoding.ASCII.GetBytes("123452hheeyy66#cs!9hjv887mxx7#8y")
' Create an encryptor to perform the stream transform.
Dim encryptor As ICryptoTransform = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
'Write all data to the stream.
swEncrypt.Write(sToEncrypt)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
End Using
sToEncrypt = Convert.ToBase64String(encrypted)
Return sToEncrypt
End Function
But when im using JS (CryptoJS) to decrypt the message it just dont work!
var iv = CryptoJS.enc.Utf8.parse('123452hheeyy66#cs!9hjv887mxx7#8y');
var decrypted = CryptoJS.AES.decrypt(encrypted, '12345678912345678912345678912345', { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding });
Please help me I'm doing my best but JS is not my thing.

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

python decrypt a text encrypted in jsencrypt

In a web form the answers (packed in a jsonstring) are encrypted in several steps. First a random key is generated. Second the random key is used for AES encryption of the jsonstring. The random key is encrypted as well. Both are send in the body of a mail.
// Generate Random key
var rand_key = ('0000' + Math.random().toString(36).replace('.', '')).substr(-10);
console.log('rand_key', rand_key)
//var pubkey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALDjeFwFNhMCjMwcRVVKG1VvfsntEVPR3lNTujJnNk1+iSqZ4Tl5Lwq9GbwO+qlYVwXHNmeqG7rkEhL9uyDIZVECAwEAAQ=="
// rsa_key_public07012016.bin
//var pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv8FVei4Q2ehmYsSCv/uODSojIOGHwfQe686S1cEH5i/1mGME5ZzNqyy0d+lhMRD0tr7Sje7JoCEC/XRIZaiKJjpl1+3RXotf/Cx3bd9H7WtitshZB1m38ZZFsrX4oigMpUPFbCefMeBS4hvvNnmtl08lQGhfIXdXeflZsgWRHtQIDAQAB";
// my_pub_key.pem
var pubkey ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA38gtENP9/hpirSCIsPh6CAVm0UmME4XBlPyK8yhwk079EUJpNzlEhu9HKcA/B7Fxo2lNoY9Tb9e+PYtJ6+VOB4+Y6zgGMX7cchYmumKRTbbQ6FNfBE5Q8XnOAUlgC7gNrs0e5lW7JH1kWlK+eTT4TANT7F3US09aXmym+fZaRInbXmJujGnDIbRIIbzr5FE82EeMpw2TqRWV466wz5EeFWSSQ8EqV1pSox8B1ywb6cnB/Vofs2qR9Zf2efi9TMcSGm/ij/p9IZcbLeep9qfGsv29lbLNMfwNwQyH0JU27eAM4tPdirceZPxfD6iiILmKzN253BMoAeQCp6us53CnGQIDAQAB"
// Make form_data a JSON string
var jsonstring = JSON.stringify(form_data);
// Create AES encrypted object
var aes_encrypted_json = CryptoJS.AES.encrypt(jsonstring, rand_key);
// Encrypt rand_key
var encrypt = new JSEncrypt();
//console.log('encrypt obj', encrypt);
encrypt.setPublicKey(pubkey);
var encrypted_rand_key = encrypt.encrypt(rand_key);
//var encrypted = encrypt.encrypt(jsonstring);
console.log('encypted', encrypted_rand_key);
var mail_body = encrypted_rand_key + aes_encrypted_json
console.log('body', mail_body)
var mailto_string = "mailto:info#xyz.com?subject=FORM&body=" + encodeURIComponent(mail_body);
$('#mailtosend').attr('href', mailto_string);
At the recipient mail server side I want to decrypt the random generated key and the jsonstring using a private key using the pycryptodome package.
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import *
def decrypt(key, text):
if type(key) == str:
key = key.encode()
if type(text) == str:
text = text.encode()
rsakey = RSA.importKey(key)
rsakey = PKCS1_v1_5.new(rsakey)
d = rsakey.decrypt(text, 'bolloux')
return d
# rand_key am2mhiwwmi
text = "ZvcrluUmZLY3lRRw01W9mQnhMn7zzpIWn1Bo3csM/ZZ0pWY/8H2dCB9fZDi9/cmp0UtIqDXhLd7SIwyxqrFgPcHUuEHlZl0WQcjSty8PjadG2Abulk1XqEQV4u0Gb/bFGDBMcf5tV1G0d4FFcBPE8r8inrxUjSj2CSffVL8gIGq3ZfY5g7t5FOZV8npBCEONgOLKYnzIiHrHUuXWsOaMAqxMFOLd5DTDLKAkyMybDClsLW9ka+CvWd5fnZBCvO2ziehFp7b9PG4QPSnQpdC8jNLGZB2h0FI8YQD6IyUwmVluUbAlPMqwd6A2CBdGCbfbMChaA5R7bJgKkYhPOQTjaQ=="
text = b64decode(text.encode())
with open('my_priv_key.pem', 'rb') as f:
key = f.read()
decrypt(key, text)
I run into a encoding problem. "UnicodeDecodeError: 'ascii' codec can't decode byte 0xf7 in position 1: ordinal not in range(128)" The encoding is complicating the issue beyond my capabilities.
My questions:
1. How can I resolve the encoding problem ?
2. How can I make the decryption work ?
Thanks
The issue is more than likely caused by b64decode(text) returning a str that contains values such as \xf7 and then attempting to .encode() those values within your decrypt function. encode will use the default encoding which in this case is ascii. I would personally remove the calls to encode unless you specifically have a reason you are doing so.

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