I have encoded a string using this method in Python. I want to decode the encoded string using Javascript.
from Crypto.Cipher import XOR
def encrypt(key, plaintext):
cipher = XOR.new(key)
return base64.b64encode(cipher.encrypt(plaintext))
I got a better solution to encrypt in Python and decrypt in Javascript.
Python Encoding Part:
import base64
from Crypto import Random
from Crypto.Cipher import AES
import json
def encrypt_val(clear_text):
master_key = '0123456789101112'
encoder = PKCS7Encoder()
raw = encoder.encode(clear_text)
iv = Random.new().read( 16 )
cipher = AES.new( master_key, AES.MODE_CBC, iv, segment_size=128 )
return base64.b64encode( iv + cipher.encrypt( raw ) )
print(encrypt_val(json.dumps({"name":"Tahir"})))
Javascript Decoding Part:
const CryptoJS = require('crypto-js')
const atob = require('atob')
function decryptMsg (data) {
master_key = '0123456789101112';
// Decode the base64 data so we can separate iv and crypt text.
var rawData = atob(data);
// Split by 16 because my IV size
var iv = rawData.substring(0, 16);
var crypttext = rawData.substring(16);
//Parsers
crypttext = CryptoJS.enc.Latin1.parse(crypttext);
iv = CryptoJS.enc.Latin1.parse(iv);
key = CryptoJS.enc.Utf8.parse(master_key);
// Decrypt
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: crypttext},
key,
{iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}
);
// Can be Utf8 too
output_plaintext = CryptoJS.enc.Latin1.stringify(plaintextArray);
console.log("plain text : " + output_plaintext);
}
encoded_message = "XF8T/miPPVk9B7GfNUshRqJf6//sJnWey+TqoXj70Tp0vJhjw22uDLOLh7es4BOp"
decryptMsg(encoded_message)
Related
I've got a set of functions for encrypting/decrypting on the server (C#), however I'd like to port the decryption piece to Javascript. Here's the C# decryption functions I've used previously in C# with a sample encrypted string, password and IV
I'm having trouble with the JavaScript decryption piece using Cryptojs. The result that comes back is unexpectedly an empty string.
var ciphertext = "0MuDwNoWBFjN/1anszbl0Cxkrwh9ahRwE3c61t7io2c=";
var key = "8beee7ac-42d1-4294-91b8-68cd032cf1e1";
var iv = "9bC_#$/-+%#Kli%1Az=-#qT";
var ciphertextWA = CryptoJS.enc.Hex.parse(ciphertext);
var keyWA = CryptoJS.enc.Utf8.parse(key);
var ivWA = CryptoJS.enc.Utf8.parse(iv);
var ciphertextCP = { ciphertext: ciphertextWA };
var decrypted = CryptoJS.AES.decrypt(
ciphertextCP,
keyWA,
{ iv: ivWA }
);
console.log(decrypted.toString(CryptoJS.enc.Utf8));
The bugs are in the determination of IV and key. Both are derived from passwords using SHA512. In the case of the key the first 32 bytes (bytes 0-31) are used, in the case of the IV the 16 bytes following the first 32 bytes (bytes 32-47).
The fixed code is:
var ciphertext = "0MuDwNoWBFjN/1anszbl0Cxkrwh9ahRwE3c61t7io2c=";
var key = "8beee7ac-42d1-4294-91b8-68cd032cf1e1";
var iv = "9bC_#$/-+%#Kli%1Az=-#qT";
var ciphertextWA = CryptoJS.enc.Base64.parse(ciphertext);
var ciphertextCP = { ciphertext: ciphertextWA };
var keyHashWA = CryptoJS.SHA512(key);
var keyWA = CryptoJS.lib.WordArray.create(keyHashWA.words.slice(0, 32/4));
var ivHashWA = CryptoJS.SHA512(iv);
var ivWA = CryptoJS.lib.WordArray.create(ivHashWA.words.slice(32/4, 48/4));
var decryptedWA = CryptoJS.AES.decrypt(
ciphertextCP,
keyWA,
{ iv: ivWA }
);
console.log(decryptedWA.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
Edit:
As you correctly guessed, the problem is caused by the different encodings (Windows-1252 in the C# code and UTF-8 in the JavaScript code). The fix is to decode in the JavaScript code with Windows-1252.
CryptoJS supports Latin1 (aka ISO-8859-1) but not Windows-1252 (aka Cp1252), s. encoders. The differences between the two encodings are minor, ranging from 0x80 to 0x9F. Just like UTF-8, both correspond to ASCII encoding in the range between 0x00 and 0x7F. Since the original plaintext contained only ASCII characters, there were no problems.
However, the new plaintext now contains byte sequences that are not compatible with UTF-8 (hence the error) or whose characters differ from Latin1 (hence the mismatches).
Since CryptoJS does not support Windows-1252, the decoding must be done with JavaScript on-board means or another library. One possibility is to convert the CryptoJS type WordArray to the more general JavaScript type Uint8Array. Then, using TextDecoder(), which supports a large repertoire of encodings, decoding can be performed using Windows-1252:
var ciphertext = `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`;
var key = "55790c03-4a4b-49f7-b7fe-d178454d88f0";
var iv = "9bC_#$/-+%#Kli%1Az=-#qT";
var ciphertextWA = CryptoJS.enc.Base64.parse(ciphertext);
var ciphertextCP = { ciphertext: ciphertextWA };
var keyHashWA = CryptoJS.SHA512(key);
var keyWA = CryptoJS.lib.WordArray.create(keyHashWA.words.slice(0, 32/4));
var ivHashWA = CryptoJS.SHA512(iv);
var ivWA = CryptoJS.lib.WordArray.create(ivHashWA.words.slice(32/4, 48/4));
var decryptedWA = CryptoJS.AES.decrypt(
ciphertextCP,
keyWA,
{ iv: ivWA }
);
function convertWordArrayToUint8Array(wordArray) {
var arrayOfWords = wordArray.hasOwnProperty("words") ? wordArray.words : [];
var length = wordArray.hasOwnProperty("sigBytes") ? wordArray.sigBytes : arrayOfWords.length * 4;
var uInt8Array = new Uint8Array(length), index=0, word, i;
for (i=0; i<length; i++) {
word = arrayOfWords[i];
uInt8Array[index++] = word >> 24;
uInt8Array[index++] = (word >> 16) & 0xff;
uInt8Array[index++] = (word >> 8) & 0xff;
uInt8Array[index++] = word & 0xff;
}
return uInt8Array;
}
var decryptedUint8Array = convertWordArrayToUint8Array(decryptedWA);
var decrypted = new TextDecoder('windows-1252').decode(decryptedUint8Array);
console.log(decrypted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
I've been trying to encrypt and decrypt strings in by AES and C# in an interoperable way. My client application is a Node server that communicates with vendor's API is in dot NET.
The vendor uses these methods for encrypting and decrypting the strings:
public static string Encrypt(string data, string key)
{
string IV = key.Substring(0, 16);
byte[] iv = Encoding.UTF8.GetBytes(IV);
byte[] array;
using(Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using(MemoryStream memoryStream = new MemoryStream())
{
using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
{
using(StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
{
streamWriter.Write(data);
}
array = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(array);
}
public static string Decrypt(string data, string key)
{
string IV = key.Substring(0, 16);
byte[] iv = Encoding.UTF8.GetBytes(IV);
byte[] buffer = Convert.FromBase64String(data);
using(Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using(MemoryStream memoryStream = new MemoryStream(buffer))
{
using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using(StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
I tried for example crypto-js for decrypting the strings, but I cannot make it work:
const encryptedText = CryptoJS.enc.Base64.parse(base64Value)
const encrypted2 = encryptedText.toString(CryptoJS.enc.Base64);
const decrypt2 = CryptoJS.AES.decrypt(encrypted2, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypt2.toString(CryptoJS.enc.Utf8)) // (also tried various other encodings, Utf16, Utf16LE and others)
The following Node.js code should work correctly with your .NET code.
We're using the algorithm aes-256-cbc to match the mode used in the C# example.
const crypto = require("crypto");
const Algorithm = "aes-256-cbc";
function encrypt(plainText, key, iv, outputEncoding = "base64") {
const cipher = crypto.createCipheriv(Algorithm, key, iv);
const output = Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding);
return output.replace('+', '-').replace('/', '_').replace('=', '');
}
function decrypt(cipherText, key, iv, outputEncoding = "utf8") {
cipherText = Buffer.from(cipherText, "base64");
const cipher = crypto.createDecipheriv(Algorithm, key, iv);
return Buffer.concat([cipher.update(cipherText), cipher.final()]).toString(outputEncoding);
}
const KEY = 'KFmnMAPzP!g#6Dy5HD?JSgYC9obE&m#m';
const IV = KEY.slice(0,16);
// Taking the output from our C# sample...
const encrypted = 'SORoNS48u0KniiANU3Y9Mw==';
console.log("Encrypted (base64):", encrypted);
const decrypted = decrypt(encrypted, KEY, IV)
console.log("Decrypted:", decrypted);
The equivalent C# code is below:
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class Program
{
public static void Main()
{
var str = Encrypt("test", "KFmnMAPzP!g#6Dy5HD?JSgYC9obE&m#m");
Console.WriteLine("Encrypted: " + str);
Console.WriteLine("Decrypted: " + Decrypt(str, "KFmnMAPzP!g#6Dy5HD?JSgYC9obE&m#m"));
}
public static string Encrypt(string data, string key)
{
string IV = key.Substring(0, 16);
byte[] iv = Encoding.UTF8.GetBytes(IV);
byte[] array;
using(Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using(MemoryStream memoryStream = new MemoryStream())
{
using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
{
using(StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
{
streamWriter.Write(data);
}
array = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(array);
}
public static string Decrypt(string data, string key)
{
string IV = key.Substring(0, 16);
byte[] iv = Encoding.UTF8.GetBytes(IV);
byte[] buffer = Convert.FromBase64String(data);
using(Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using(MemoryStream memoryStream = new MemoryStream(buffer))
{
using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using(StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
}
The output for the C# code is:
Encrypted: SORoNS48u0KniiANU3Y9Mw==
Decrypted: test
The Node.js code then decrypts this (using the same key and IV):
Encrypted (base64): SORoNS48u0KniiANU3Y9Mw=
Decrypted: test
Since you are using NodeJS, it makes sense to use the crypto module of NodeJS instead of CryptoJS (see the other answer). CryptoJS is of course also possible. Then the following must be considered:
In the JavaScript code, CBC mode has to be used, and key and IV must be passed as WordArray to CryptoJS.AES.decrypt(). The ciphertext can be passed Base64 encoded, CryptoJS implicitly converts this to a CipherParams object.
CryptoJS applies CBC and PKCS#7 padding by default, so these do not need to be explicitly specified (but may of course).
The ciphertext in the following example was generated with the C# code and can be decrypted with the following CryptoJS code:
const ciphertext = 'yKiV9TBw3eNt2QvK1kdXaw==';
const keyStr = "01234567890123456789012345678901"; // 32 bytes -> AES-256
const key = CryptoJS.enc.Utf8.parse(keyStr);
const IV = CryptoJS.enc.Utf8.parse(keyStr.substr(0, 16));
const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {iv: IV}); // apply default: CBC and PKCS#7 padding
console.log(decrypted.toString(CryptoJS.enc.Utf8)); // Hello world!
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
Regarding security:
It's insecure to use the key (or a part of it) as IV. Instead, a random IV should be generated for each encryption. This is not secret and is passed together with the ciphertext, in general concatenated.
Also the generation of the key from a text reduces security (even with correct size the value range is reduced). More secure would be to use a reliable key derivation function like PBKDF2 if a text/passphrase is involved.
Implemented in javascript using cryptojs but unable to do the same in swift using cryptoswift. I am unable to understand how key, iv & ciphertext are generated in javascript looking at the below code. Out of ideas to do the same in Swift using cryptoswift.
decryptPayloadQR(ciphertextStr, SecretKey) {
try {
let key = CryptoJS.enc.Utf8.parse(SecretKey);
var ciphertext = CryptoJS.enc.Base64.parse(ciphertextStr);
var iv = ciphertext.clone();
iv.sigBytes = 16;
iv.clamp();
ciphertext.words.splice(0, 4);
ciphertext.sigBytes -= 16;
var decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, key, {
iv: iv
});
console.log("===decrypted.toString(CryptoJS.enc.Utf8)=",decrypted.toString(CryptoJS.enc.Utf8));
return decrypted.toString(CryptoJS.enc.Utf8);
} catch (error) {
console.log("===error in decrpt fun === : ",error);
return false
}
}
Result is string which can be converted to json.
Swift code below.
let encryptedString = "OdqBIN4twOxKwe1aIZhTatkzVdfvN/mfB2Arra38tF25+3efc+Kl+HABZtqiGrTIihSpfW/XHW8+31Rl+uHZB2immfB6/w8E2j5ylCV8RKrqHVMMB7BPBLyr8oTuxmYEla1J1NxywLFPyNZCI4zmkYczwVSyssd5VKWH8WaBHR5Yai6MaxugdohW40byPx6xqbhwjHN5w+dh3dJBSFbM5EhQTqPwfBA1v1UBrCXooay47keSFor/7ywjV3e2bU5JrL0o+S26UF6zoVkRP1tdGAY3TqYyrPLUHVq0nIzkmnZdQk5gFGjN0sF58WdhuqjgRAtSrbmL5biuOtmQHFmNx4sUjkF4pYvfYxrj3ze2H/6G03cxCzW/DUytV678IBrd"
//======== iv & cipher text should be same as generated in above javascript code ==========//
//======== Should these keys be in hex =======//
let iv = "" /* No idea how to get iv from encrypted string */
let cipherText = "" /* No idea how to get cipherText from encrypted string */
let key = "abababababababab"
do {
let decryptor = try AES(key: key, iv: iv)
let decryptedBytes = try decryptor.decrypt(cipherText.bytes)
print(String(bytes: decryptedBytes, encoding: .utf8)!)
} catch {
print(error)
}
How do I get iv, key & cipher text for swift similar to that in javascript?
Thanks in advance.
I was able to do the same in Swift with cryptoswift using below code.
let encryptedString = "OdqBIN4twOxKwe1aIZhTatkzVdfvN/mfB2Arra38tF25+3efc+Kl+HABZtqiGrTIihSpfW/XHW8+31Rl+uHZB2immfB6/w8E2j5ylCV8RKrqHVMMB7BPBLyr8oTuxmYEla1J1NxywLFPyNZCI4zmkYczwVSyssd5VKWH8WaBHR5Yai6MaxugdohW40byPx6xqbhwjHN5w+dh3dJBSFbM5EhQTqPwfBA1v1UBrCXooay47keSFor/7ywjV3e2bU5JrL0o+S26UF6zoVkRP1tdGAY3TqYyrPLUHVq0nIzkmnZdQk5gFGjN0sF58WdhuqjgRAtSrbmL5biuOtmQHFmNx4sUjkF4pYvfYxrj3ze2H/6G03cxCzW/DUytV678IBrd"
let aesIVBlockSize = 16
let cipherData = Data(base64Encoded: encryptedString, options: .ignoreUnknownCharacters)
let ivBytes = Array(Array(cipherData!).dropLast(cipherData!.count - aesIVBlockSize))
let actualCipherBytes = Array(Array(cipherData!).dropFirst(aesIVBlockSize))
do {
let aes = try AES(key: Array("abababababababab".data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
let decrypted = try aes.decrypt(actualCipherBytes)
let outData = Data(bytes: decrypted)
print(outData)
print(String(bytes: outData, encoding: .utf8) as Any)
} catch {
print("Decryption error: \(error)")
}
I am getting an encrypted key which is generated using Java. I need to decrypt it in AngularJS app using CryptoJS. I had done similar thing using node but now in Angular I am stuck. This fiddle http://jsfiddle.net/s5g82rqh/ is what I have tried so far but it returns empty.
Below is what I have tried till now
function decrypt_core_AES_CBC(password, ciphertext) {
var iv = CryptoJS.lib.WordArray.random(128/8);
var message = CryptoJS.AES.decrypt(ciphertext, password, { mode: CryptoJS.mode.CBC, iv: password });
console.log("The current iv is: " + iv.toString() );
return CryptoJS.enc.Utf8.stringify(message);
}
var data = '6615702f2dd672f643fd57623d6362a510a98faf4b1c068fd468b525a5fa5471809852a0f9cb7936ce3d3892c233b8c48ce2608f16ce6fa66005b2d97689fbb4';
var key = '3426D38AB846B62B9C236D288778D997';
var dec = decrypt_core_AES_CBC(key, data);
console.log(dec);
Below is the node.js code which works for me. I have no success in achieving similar in CryptoJS. As per my understanding crypto comes as built-in library which node has its own wrapper on top of it.
var crypto = require('crypto');
var defaultAlgorithm= 'aes-128-cbc';
var defaultFormat= 'hex';
var ivLength= 16;
function decode (data, key, algorithm, format) {
// Make sure the data is a buffer object
if (data instanceof Buffer) {
data = data.toString();
}
// Get defaults if needed
algorithm = algorithm || defaultAlgorithm;
format = format || defaultFormat;
ivLength = ivLength * 2;
// Get the initialization vector
var iv = new Buffer(data.substring(0, ivLength), 'hex');
// Remove the iv from the data
data = data.substring(ivLength);
var decipher = crypto.createDecipheriv(algorithm, new Buffer(key, 'hex'), iv);
var decrypted = decipher.update(data, format, 'utf8') + decipher.final('utf8');
return decrypted;
}
var data ='6615702f2dd672f643fd57623d6362a510a98faf4b1c068fd468b525a5fa5471809852a0f9cb7936ce3d3892c233b8c48ce2608f16ce6fa66005b2d97689fbb4';
var key = '3426D38AB846B62B9C236D288778D997';
var dec = decode(data, key, defaultAlgorithm, defaultFormat);
console.log(dec);
You have three issues:
CryptoJS supports two types of encryption/decryption: key derived from a password and directly passed key. You want to do this from a key, so you need to parse the hex-encoded key string into CryptoJS' native format before passing it to the decrypt() function:
key = CryptoJS.enc.Hex.parse(key);
Also, don't confuse a key with a password.
You forgot to slice off the IV from the ciphertext before decrypting.
var iv = CryptoJS.enc.Hex.parse(ciphertext.slice(0, 32));
ciphertext = CryptoJS.enc.Hex.parse(ciphertext.slice(32));
CryptoJS' expects either a CipherParams object or an OpenSSL-formatted string to decrypt from. Since you only have a hex string, you have to parse it before use and use it like this:
var message = CryptoJS.AES.decrypt({
ciphertext: ciphertext
}, key, {
iv: iv
});
It took one week for me to find out working code for aes-128-cbc in Java, PHP and Java Script. I had to search alot at various website. Finally with multiple hit and trial below code worked out for me. Both encryption and decryption. Encrypt in Java; Decrypt in PHP or JavaScript, Encrypt in PHP; Decrypt in Java or JavaScript, Encrypt in JavaScript Decrypt in PHP or Java. All option will work
The length of Key will be 16 digit having Alpha-numeric values. Use Same key to encrypt and decrypt data. IV is 16 digit Random value of Alpha-numeric to be passed while encryption.
PHP code for Encryption and Decryption:
function encrypt($key, $iv, $data) {
static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher
static $CIPHER_KEY_LEN = 16; //128 bits
if (strlen($key) < $CIPHER_KEY_LEN) {
$key = str_pad("$key", $CIPHER_KEY_LEN, "0"); //0 pad to len 16
} else if (strlen($key) > $CIPHER_KEY_LEN) {
$key = substr($str, 0, $CIPHER_KEY_LEN); //truncate to 16 bytes
}
$encodedEncryptedData = base64_encode(openssl_encrypt($data, $OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv));
$encodedIV = base64_encode($iv);
$encryptedPayload = $encodedEncryptedData.":".$encodedIV;
return $encryptedPayload;
}
function decrypt($key, $data) {
// $key = $request['key'];
// $data = $request['data'];
static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher
static $CIPHER_KEY_LEN = 16; //128 bits
if (strlen($key) < $CIPHER_KEY_LEN) {
$key = str_pad("$key", $CIPHER_KEY_LEN, "0"); //0 pad to len 16
} else if (strlen($key) > $CIPHER_KEY_LEN) {
$key = substr($str, 0, $CIPHER_KEY_LEN); //truncate to 16 bytes
}
$parts = explode(':', $data); //Separate Encrypted data from iv.
$decryptedData = openssl_decrypt(base64_decode($parts[0]), $OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
return $decryptedData;
}
Java Code for Encryption and Decryption
import android.util.Base64;
import android.util.Log;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Java_AES_Cipher {
private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
private static int CIPHER_KEY_LEN = 16; //128 bits
/**
* Encrypt data using AES Cipher (CBC) with 128 bit key
*
*
* #param key - key to use should be 16 bytes long (128 bits)
* #param iv - initialization vector
* #param data - data to encrypt
* #return encryptedData data in base64 encoding with iv attached at end after a :
*/
public static String encrypt(String key, String iv, String data) {
try {
if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();
for(int i = 0; i < numPad; i++){
key += "0"; //0 pad to len 16 bytes
}
} else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
}
IvParameterSpec initVector = new IvParameterSpec(iv.getBytes("ISO-8859-1"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);
byte[] encryptedData = cipher.doFinal((data.getBytes()));
String base64_EncryptedData = Base64.encodeToString(encryptedData, Base64.DEFAULT);
String base64_IV = Base64.encodeToString(iv.getBytes("ISO-8859-1"), Base64.DEFAULT);
base64_EncryptedData = base64_EncryptedData.replaceAll(System.getProperty("line.separator"), "");
base64_IV = base64_IV.replaceAll(System.getProperty("line.separator"), "");
Log.i("Java_AES_Cipher","Encrypted data is "+ base64_EncryptedData + ":" + base64_IV);
return base64_EncryptedData + ":" + base64_IV;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* Decrypt data using AES Cipher (CBC) with 128 bit key
*
* #param key - key to use should be 16 bytes long (128 bits)
* #param data - encrypted data with iv at the end separate by :
* #return decrypted data string
*/
public static String decrypt(String key, String data) {
try {
if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();
for(int i = 0; i < numPad; i++){
key += "0"; //0 pad to len 16 bytes
}
} else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
}
String[] parts = data.split(":");
if (parts.length<2)
{
Log.i("Java_AES_Cipher","Length "+ parts.length);
return data;
}
IvParameterSpec iv = new IvParameterSpec(Base64.decode(parts[1], Base64.DEFAULT));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decodedEncryptedData = Base64.decode(parts[0], Base64.DEFAULT);
byte[] original = cipher.doFinal(decodedEncryptedData);
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
Java Script Code for Encryption and Decryption
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
function encrypt (messageText,key, iv){
var message = messageText;
var key = CryptoJS.enc.Utf8.parse(key);
var iv = CryptoJS.enc.Utf8.parse(iv);
var encrypted = CryptoJS.AES.encrypt(
message,key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
);
this.encrypted = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
console.log('encrypted:'+encrypted);
return encrypted;
}
function decrypt(keyBase64, messagebase64) {
const digest = messagebase64.split(':');
const crypttext = CryptoJS.enc.Base64.parse(digest[0])
const ivBase64 = CryptoJS.enc.Base64.parse(digest[1])
const decrypted = CryptoJS.AES.decrypt(
{
ciphertext: crypttext
},
CryptoJS.enc.Utf8.parse(keyBase64),
{
iv: ivBase64,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
);
console.log('decrypted: '+decrypted.toString(CryptoJS.enc.Utf8));
return decrypted.toString(CryptoJS.enc.Utf8);
}
I'm able to decrypt AES encrypted message with Ruby like this:
require 'openssl'
require 'base64'
data = "IYkyGxYaNgHpnZWgwILMalVFmLWFgTCHCZL9263NOcfSo5lBjAzOZAtF5bF++R0Bi+9c9E+p3VEr/xvj4oABtRWVJ2wlWzLbYC2rKFk5iapFhb7uZCUpO4w4Su3a5QFa2vInjYueziRoqySZd/DpstMJ8rsJ94VGizFFFZ1l0sw1ax+wfBAv5+wHs/hlnHi/ea66KBO3rgXKahvV28h+4bh5etc8RCrmiiNbfg6Oj0jQJDjdYIdW8T9YPOI9E1hih8lbfRnMWcOFJgYekfLpoy5LI525UGnlM46J1k6ekLqsn9FqvbiOOoLgqa4YqBm1i9P0ePyjkME+t+RiL8xXX+ItgOYr9G7kM64wlTJPCW8B/crmUdmGzQNC/hD/u/8wfHBS2f8u6OtQMG/+Kpk1oju8lcUZGI/4S8A6/OuktvQr2zgnbs2aADMrM37Oait/pJ3G73S7NwVT8EaK+X43c0C/fUvW2/bD/rqCNpAh9WQlz4Cj6JHwjbmwuind6aCimF1tHjXuR9FXu+g17sPT4ZkKZ6aeBG+m170XdCGn2hVM0wH1rh3VeCG2u/JFqfuGKGSoqeHeNY/icu9pEhtZDzHd7aPoaMXcWvXC9PjooBf7GM1EPacSdnon1kBobjtKSt1l15DjO5TMrJoX7VO7GotQwo+uI/u5Kop01hBXxyxyggl1/8N0ESohPJoqLDrIwvbGK5kW4B49FVPnx9CMvjZDdSsoxPAh+hx6SPe8Hj0Nx4bRs06cbtOkte/V8QSYIqjiJDleEqPrdiKlvgToZz9L29ZR/3Ln65qU1sq7q9c0SEYxIopV7TdTjFS7y76zDPFZkhzc3DjfLtJo/M1hdtt648APcZdmAIgWH6fh3eJZ0qbiPh8RStYH7I2COmnlMw4+t/B5mlhYVSgwPK2Ir736Mh+P9Bw0fF8r9Ghhs4AJzpU0RiK9d1tCsrLfK/hSRwTXhtsSB6eDWEGkO7oeEIz43mgn0sv3SrA9JNHzYkg="
key = "2e35f242a46d67eeb74aabc37d5e5d05"
aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
aes.decrypt
aes.key = key.scan(/../).collect{ |x| x.hex }.pack('c*')
aes.iv = Base64.decode64(data)[0...16]
puts aes.update(Base64.decode64(data)[16..-1]) + aes.final
# => JSON data...
Being new to CryptoJS I fail to put together working alternative. Here's what i've done so far:
data = "IYkyGxYaNgHpnZWgwILMalVFmLWFgTCHCZL9263NOcfSo5lBjAzOZAtF5bF++R0Bi+9c9E+p3VEr/xvj4oABtRWVJ2wlWzLbYC2rKFk5iapFhb7uZCUpO4w4Su3a5QFa2vInjYueziRoqySZd/DpstMJ8rsJ94VGizFFFZ1l0sw1ax+wfBAv5+wHs/hlnHi/ea66KBO3rgXKahvV28h+4bh5etc8RCrmiiNbfg6Oj0jQJDjdYIdW8T9YPOI9E1hih8lbfRnMWcOFJgYekfLpoy5LI525UGnlM46J1k6ekLqsn9FqvbiOOoLgqa4YqBm1i9P0ePyjkME+t+RiL8xXX+ItgOYr9G7kM64wlTJPCW8B/crmUdmGzQNC/hD/u/8wfHBS2f8u6OtQMG/+Kpk1oju8lcUZGI/4S8A6/OuktvQr2zgnbs2aADMrM37Oait/pJ3G73S7NwVT8EaK+X43c0C/fUvW2/bD/rqCNpAh9WQlz4Cj6JHwjbmwuind6aCimF1tHjXuR9FXu+g17sPT4ZkKZ6aeBG+m170XdCGn2hVM0wH1rh3VeCG2u/JFqfuGKGSoqeHeNY/icu9pEhtZDzHd7aPoaMXcWvXC9PjooBf7GM1EPacSdnon1kBobjtKSt1l15DjO5TMrJoX7VO7GotQwo+uI/u5Kop01hBXxyxyggl1/8N0ESohPJoqLDrIwvbGK5kW4B49FVPnx9CMvjZDdSsoxPAh+hx6SPe8Hj0Nx4bRs06cbtOkte/V8QSYIqjiJDleEqPrdiKlvgToZz9L29ZR/3Ln65qU1sq7q9c0SEYxIopV7TdTjFS7y76zDPFZkhzc3DjfLtJo/M1hdtt648APcZdmAIgWH6fh3eJZ0qbiPh8RStYH7I2COmnlMw4+t/B5mlhYVSgwPK2Ir736Mh+P9Bw0fF8r9Ghhs4AJzpU0RiK9d1tCsrLfK/hSRwTXhtsSB6eDWEGkO7oeEIz43mgn0sv3SrA9JNHzYkg=";
key = "2e35f242a46d67eeb74aabc37d5e5d05";
CryptoJS.AES.decrypt(atob(data).substring(16), key, {
iv: atob(cipher).substring(0, 16),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
Does CryptoJS expect data, key and initialization vector in some different way? As far as i understand, the IV are the first 16 bytes in data.
This works for decryption using javascript.
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/aes.js"></script>
var key = "2e35f242a46d67eeb74aabc37d5e5d05";
var data = CryptoJS.AES.encrypt("Message", key); // Encryption Part
var decrypted = CryptoJS.AES.decrypt(data, key).toString(CryptoJS.enc.Utf8); // Message
Guess I am a little late to the party.
This seems to work for me (writes decoded string to the console):
data = "IYkyGxYaNgHpnZWgwILMalVFmLWFgTCHCZL9263NOcfSo5lBjAzOZAtF5bF++R0Bi+9c9E+p3VEr/xvj4oABtRWVJ2wlWzLbYC2rKFk5iapFhb7uZCUpO4w4Su3a5QFa2vInjYueziRoqySZd/DpstMJ8rsJ94VGizFFFZ1l0sw1ax+wfBAv5+wHs/hlnHi/ea66KBO3rgXKahvV28h+4bh5etc8RCrmiiNbfg6Oj0jQJDjdYIdW8T9YPOI9E1hih8lbfRnMWcOFJgYekfLpoy5LI525UGnlM46J1k6ekLqsn9FqvbiOOoLgqa4YqBm1i9P0ePyjkME+t+RiL8xXX+ItgOYr9G7kM64wlTJPCW8B/crmUdmGzQNC/hD/u/8wfHBS2f8u6OtQMG/+Kpk1oju8lcUZGI/4S8A6/OuktvQr2zgnbs2aADMrM37Oait/pJ3G73S7NwVT8EaK+X43c0C/fUvW2/bD/rqCNpAh9WQlz4Cj6JHwjbmwuind6aCimF1tHjXuR9FXu+g17sPT4ZkKZ6aeBG+m170XdCGn2hVM0wH1rh3VeCG2u/JFqfuGKGSoqeHeNY/icu9pEhtZDzHd7aPoaMXcWvXC9PjooBf7GM1EPacSdnon1kBobjtKSt1l15DjO5TMrJoX7VO7GotQwo+uI/u5Kop01hBXxyxyggl1/8N0ESohPJoqLDrIwvbGK5kW4B49FVPnx9CMvjZDdSsoxPAh+hx6SPe8Hj0Nx4bRs06cbtOkte/V8QSYIqjiJDleEqPrdiKlvgToZz9L29ZR/3Ln65qU1sq7q9c0SEYxIopV7TdTjFS7y76zDPFZkhzc3DjfLtJo/M1hdtt648APcZdmAIgWH6fh3eJZ0qbiPh8RStYH7I2COmnlMw4+t/B5mlhYVSgwPK2Ir736Mh+P9Bw0fF8r9Ghhs4AJzpU0RiK9d1tCsrLfK/hSRwTXhtsSB6eDWEGkO7oeEIz43mgn0sv3SrA9JNHzYkg=";
key = "2e35f242a46d67eeb74aabc37d5e5d05";
// Decode the base64 data so we can separate iv and crypt text.
var rawData = atob(data);
var iv = btoa(rawData.substring(0,16));
var crypttext = btoa(rawData.substring(16));
// Decrypt...
var plaintextArray = CryptoJS.AES.decrypt(
{
ciphertext: CryptoJS.enc.Base64.parse(crypttext),
salt: ""
},
CryptoJS.enc.Hex.parse(key),
{ iv: CryptoJS.enc.Base64.parse(iv) }
);
// Convert hex string to ASCII.
// See https://stackoverflow.com/questions/11889329/word-array-to-string
function hex2a(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
console.log(hex2a(plaintextArray.toString()));
The important bits are to specify no salt in your input and pass the key as a WordArray as jlvaquero says. There are probably some efficiency improvements to be made, e.g. I'm guessing there's an easier way to convert a string to a WordArray than going to base64 and back, but at least it successfully decodes. I lifted the hex2a function from StackOverflow question Word Array to String.
Edit: I figured out how to convert strings to WordArrays and vice-versa with CryptoJS so the extra base64 encode/decode and hex-to-ASCII function are not needed. Also it turns out the salt property need not be specified. This is more compact and efficient:
data = "IYkyGxYaNgHpnZWgwILMalVFmLWFgTCHCZL9263NOcfSo5lBjAzOZAtF5bF++R0Bi+9c9E+p3VEr/xvj4oABtRWVJ2wlWzLbYC2rKFk5iapFhb7uZCUpO4w4Su3a5QFa2vInjYueziRoqySZd/DpstMJ8rsJ94VGizFFFZ1l0sw1ax+wfBAv5+wHs/hlnHi/ea66KBO3rgXKahvV28h+4bh5etc8RCrmiiNbfg6Oj0jQJDjdYIdW8T9YPOI9E1hih8lbfRnMWcOFJgYekfLpoy5LI525UGnlM46J1k6ekLqsn9FqvbiOOoLgqa4YqBm1i9P0ePyjkME+t+RiL8xXX+ItgOYr9G7kM64wlTJPCW8B/crmUdmGzQNC/hD/u/8wfHBS2f8u6OtQMG/+Kpk1oju8lcUZGI/4S8A6/OuktvQr2zgnbs2aADMrM37Oait/pJ3G73S7NwVT8EaK+X43c0C/fUvW2/bD/rqCNpAh9WQlz4Cj6JHwjbmwuind6aCimF1tHjXuR9FXu+g17sPT4ZkKZ6aeBG+m170XdCGn2hVM0wH1rh3VeCG2u/JFqfuGKGSoqeHeNY/icu9pEhtZDzHd7aPoaMXcWvXC9PjooBf7GM1EPacSdnon1kBobjtKSt1l15DjO5TMrJoX7VO7GotQwo+uI/u5Kop01hBXxyxyggl1/8N0ESohPJoqLDrIwvbGK5kW4B49FVPnx9CMvjZDdSsoxPAh+hx6SPe8Hj0Nx4bRs06cbtOkte/V8QSYIqjiJDleEqPrdiKlvgToZz9L29ZR/3Ln65qU1sq7q9c0SEYxIopV7TdTjFS7y76zDPFZkhzc3DjfLtJo/M1hdtt648APcZdmAIgWH6fh3eJZ0qbiPh8RStYH7I2COmnlMw4+t/B5mlhYVSgwPK2Ir736Mh+P9Bw0fF8r9Ghhs4AJzpU0RiK9d1tCsrLfK/hSRwTXhtsSB6eDWEGkO7oeEIz43mgn0sv3SrA9JNHzYkg=";
key = "2e35f242a46d67eeb74aabc37d5e5d05";
// Decode the base64 data so we can separate iv and crypt text.
var rawData = atob(data);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);
// Decrypt...
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
CryptoJS.enc.Hex.parse(key),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
console.log(CryptoJS.enc.Latin1.stringify(plaintextArray));
encryptWithCryptoJS(plainText: string): string {
const key = CryptoJS.enc.Utf8.parse("hf8685nfhfhjs9h8");
const iv1 = CryptoJS.enc.Utf8.parse("hf8685nfhfhjs9h8");
const encrypted = CryptoJS.AES.encrypt(plainText, key, {
keySize: 16,
iv: iv1,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted + "";
}
decryptionWithCryptoJS(cipher: string): string {
const key = CryptoJS.enc.Utf8.parse("hf8685nfhfhjs9h8");
const iv1 = CryptoJS.enc.Utf8.parse("hf8685nfhfhjs9h8");
const plainText = CryptoJS.AES.decrypt(cipher, key, {
keySize: 16,
iv: iv1,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return plainText.toString(CryptoJS.enc.Utf8);
}
for the hex2a provided by another user, it may not working if ascii code is over 128 (i.e text contains chinese , etc)
you can use the follow to return proper unicode
function hex2a(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2){
var dec = parseInt(hex.substr(i, 2), 16);
character = String.fromCharCode(dec);
if (dec > 127)
character = "%"+hex.substr(i,2);
str += character;
}
return decodeURI(str);
}
var key = CryptoJS.enc.Utf8.parse('8080808080808080');
var iv = CryptoJS.enc.Utf8.parse('8080808080808080');
var _enid = CryptoJS.AES.decrypt(data, key,
{
keySize: 128 / 8,
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
return _enid;