I can encrypt/decrypt with Python OR with JavaScript but passing encrypted data generated by Python to my JavaScript code fails.
The base64 encoding/decoding works across languages so that base encoding on Python and decoding on JavaScript retrieves the original encrypted string.
Outside of test functions I am not using Python decrypt or JavaScript encrypt but they are here for completeness as some readers miss text saying they exist.
In Python 2:
import base64
from pyaes import AESModeOfOperationCTR
SECRET_KEY = "This_key_for_demo_purposes_only!"
def encrypt(raw_data, key=SECRET_KEY):
aes = AESModeOfOperationCTR(key)
encrypted_data = aes.encrypt(raw_data)
base64_encrypted_data = base64.b64encode(encrypted_data)
return base64_encrypted_data
def decrypt(base64_encrypted_data, key=SECRET_KEY):
encrypted_data = base64.b64decode(base64_encrypted_data)
aes = AESModeOfOperationCTR(key)
decrypted = aes.decrypt(encrypted_data)
return decrypted
In Javascript (running Server-side, on Parse.com Cloud Code):
var Buffer = require('buffer').Buffer;
var Crypto = require('crypto');
encrypt: function(raw) {
var cryptoAlgorithm = "aes-256-ctr";
var key = "This_key_for_demo_purposes_only!"
var cipher = Crypto.createCipher(cryptoAlgorithm, key);
var encrypted = cipher.update(raw, 'utf8', 'binary');
encrypted += cipher.final('binary');
var base = toBase64(encrypted);
return base;
},
decrypt: function(base64raw) {
var raw = fromBase64(base64raw);
var cryptoAlgorithm = "aes-256-ctr";
var key = "This_key_for_demo_purposes_only!"
var decipher = Crypto.createDecipher(cryptoAlgorithm, key);
var decrypted = decipher.update(raw, 'binary', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
The output of the JavaScript function decrypt() is nonsense.
Where is the mismatch?
The output of the two encrypt functions does not match when given the same raw string.
My guess: in the JavaScript I shouldn't be using 'binary'. The JavaScript decrypt() function chokes if specify 'hex' for the data generated from the Python side.
Related
I am trying to encrypt and decrypt values using node inbuild module crypto. I have followed this tutorial to encrypt the data. They haven't to gave any sample code to decrypt. When I try to use other tutorial code to decrypt the data. It not working out. Please help me out,
Code
const crypto = require('crypto');
// Difining algorithm
const algorithm = 'aes-256-cbc';
// Defining key
const key = crypto.randomBytes(32);
// Defining iv
const iv = crypto.randomBytes(16);
// An encrypt function
function encrypt(text) {
// Creating Cipheriv with its parameter
let cipher = crypto.createCipheriv(
'aes-256-cbc', Buffer.from(key), iv);
// Updating text
let encrypted = cipher.update(text);
// Using concatenation
encrypted = Buffer.concat([encrypted, cipher.final()]);
// Returning iv and encrypted data
return encrypted.toString('hex');
}
var op = encrypt("Hi Hello"); //c9103b8439f8f1412e7c98cef5fa09a1
Since you havent provided the code for decryption, Cant help you what is actually wrong you doing, apart from that you can do this to get decrypted code:
const crypto = require('crypto')
// Defining key
const key = crypto.randomBytes(32)
// Defining iv
const iv = crypto.randomBytes(16)
// An encrypt function
function encrypt(text) {
// Creating Cipheriv with its parameter
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv)
// Updating text
let encrypted = cipher.update(text)
// Using concatenation
encrypted = Buffer.concat([encrypted, cipher.final()])
// Returning iv and encrypted data
return encrypted.toString('hex')
}
var op = encrypt('Hi Hello')
console.log(op)
function decrypt(data) {
// Creating Decipheriv with its parameter
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv)
// Updating text
const decryptedText = decipher.update(data, 'hex', 'utf8')
const finalText = decryptedText + decipher.final('utf8')
return finalText
}
var decrptedData = decrypt(op)
console.log(decrptedData)
i want to use NaCl library in the client side and libsodium in php to encrypt/decrypt messages between the client and the server using keypair(public,private).
When i encrypt with libsodium and decrypt with NaCl everything works, But when i try to encrypt with NaCl and decrypt with libsodium i get no result.
Encrypting with NaCl in the client side
var message = "Sample Message";
var bytes = nacl.util.decodeUTF8(message);
var client_public = nacl.util.hex2bytearray('35e9f8477b60f61747722698d98791c4e0818ff75da3943a30e13dc0a457d402');
var client_private = nacl.util.hex2bytearray('6382cd5ef713375b6fe3835a763c72dfdc7ddcade7b8bcb9640065582708ef2c');
var server_public = nacl.util.hex2bytearray('1f348bac3b60d3076fc1a32d4e205df67356a9ef16d4b3f391c0e4817f3b987f');
var sharedkey = nacl.box.before(server_public, client_private);
var nonce = nacl.util.hex2bytearray('c031122a5f57e253686d9f6082d1061a1546e5567290c7f0'); // 24 bytes
var cipher = nacl.box.after(bytes, nonce, sharedkey );
var cihper_with_nonce = nacl.util.bytearray2hex(nonce) + bytearray2hex(cipher); // will be sent to the server
//c031122a5f57e253686d9f6082d1061a1546e5567290c7f0b2c05c9fb1483fe9b1bd2d4ae261832a54569748dd7925511b3d236e23e8
nacl.util.hex2bytearray = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
nacl.util.bytearray2hex = bytes => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
nacl.util.decodeUTF8=function(e){;var n,r=unescape(encodeURIComponent(e)),t=new Uint8Array(r.length);for(n=0;n<r.length;n++)t[n]=r.charCodeAt(n);return t}
Decrypting with libsodium in PHP
$cihper_with_nonce = 'c031122a5f57e253686d9f6082d1061a1546e5567290c7f0b2c05c9fb1483fe9b1bd2d4ae261832a54569748dd7925511b3d236e23e8';// received from the client
$server_public = hex2bin('1f348bac3b60d3076fc1a32d4e205df67356a9ef16d4b3f391c0e4817f3b987f');// generated with libsodium
$server_private = hex2bin('cea48d3c14bc9ad26bf3f62932db5d7336b8212866c14dec64670f295ec89d5d');// generated with libsodium
$client_public = hex2bin('35e9f8477b60f61747722698d98791c4e0818ff75da3943a30e13dc0a457d402');// generated with NaCl
$sharedkey = sodium_crypto_box_keypair_from_secretkey_and_publickey($server_private, $client_public );
$nonce = hex2bin(substr($cihper_with_nonce, 0, 48));//24 bytes
$cihper = hex2bin(substr($cihper_with_nonce, 48));
$message = sodium_crypto_box_open($cihper , $nonce, $sharedkey );
var_dump($message);// bool(false)
Am i using the Library the Wrong way or there is something i am doing it wrong?
Because when i encrypt with php and decrypt with NaCl everything works and i did the same way in reverse for the Decryption.
all the bytes(hex) used are generated with the same library.
NaCl Source nacl util
libsodium Source libsodium
I need following encryption decryption, but in java script for client-side.
This code is written in Node-JS and using crypto library, i couldn't find same solution for java script for client side run.
const crypto = require('crypto');
const decrypt = (textBase64, keyBase64, ivBase64) => {
const algorithm = 'aes-256-cbc';
const ivBuffer = Buffer.from(ivBase64, 'base64');
const keyBuffer = Buffer.from(keyBase64, 'base64');
const decipher = crypto.createDecipheriv(algorithm, keyBuffer, ivBuffer);
decipher.setAutoPadding(false);
let decrypted = decipher.update(textBase64, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
const encryptedMessage = '';
const key = 'cGFzc3dvcmQxMjM0NTY3ODk=';
const iv = Buffer.from(encryptedMessage, 'base64').slice(0, 16);
// the message comes from the bytes AFTER the IV - this is what you should decrypt
const message = Buffer.from(encryptedMessage, 'base64').slice(16);
const result = decrypt(message, key, iv);
console.log(result);
//console.log(Buffer.from(encryptedMessage, 'base64').slice(0, 16))
First I would say it is not recommended to decrypt on the client side as the key is visible. but you know what you do.
this library is pure JS and should be working in a browser without any pain : ricmoo/aes-js
I'm trying to develop some very simple code to encrypt and decrypt some simple text. The problem appears to be that when running the code the .final() of my createDecipherIV causes that error in the title to be produced.
I've attempted to toy with the various encoding (Binary vs Hex, base 64, etc.)
node: '10.15.3'
openssl: '1.1.0j'
This is an electron project, though I don't know what impact that might have
const crypto = require('crypto');
let sessionKey = crypto.randomBytes(256/8).toString('hex');
class encryption {
constructor() {
this.encryptionOptions = {
algorithm: 'aes-256-cbc',
iv: crypto.randomBytes(16),
key: String,
}
}
encryptMem(memItem){
this.encryptionOptions['key'] = Buffer.from(sessionKey,'hex');
var cipher = crypto.createCipher(this.encryptionOptions['algorithm'], this.encryptionOptions['key'], this.encryptionOptions['iv']);
var cipherText = cipher.update(memItem,'utf8','hex');
cipherText += cipher.final('hex');
return this.encryptionOptions['iv'].toString('hex') + cipherText;
}
decryptMem(memObject){
this.encryptionOptions['key'] = Buffer.from(sessionKey,'hex');
var _iv = Buffer.from(memObject.slice(0,32),'hex')
var _data = memObject.slice(32)
var _decode = crypto.createDecipheriv(this.encryptionOptions['algorithm'], this.encryptionOptions['key'], _iv);
var _decoded = _decode.update(_data,'hex','utf8');
_decoded += _decode.final('utf8')
return _decoded;
}
}
The sample code
e = new encryption
encryption {encryptionOptions: {…}}
val = e.encryptMem("test")
"adcd1f5876ca02a4420b61df5dfdaa9be3080108020df42dfc630951ffabe0ac"
e.decryptMem(val)
\lib\encrypt.js:25
internal/crypto/cipher.js:172 Uncaught Error: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
at Decipheriv.final (internal/crypto/cipher.js:172)
at encryption.decryptMem (\lib\encrypt.js:26)
at <anonymous>:1:3
final # internal/crypto/cipher.js:172
decryptMem # \lib\encrypt.js:26
(anonymous) # VM433:1
Where as it should simply return "test
EDIT As pointed out in the answer, createCipher needed to be changed to createCipheriv
The following is some shortened code that should also correctly create a new iv with every invocation of encryption, rather then with simply the invocation of the class
const crypto = require('crypto');
let sessionKey = crypto.randomBytes(256/8).toString('hex');
class encryption {
constructor(key = null){
this.algorithm = 'aes-256-cbc';
this.key = key || Buffer.from(sessionKey,'hex');
}
encrypt(plainText){
var iv = crypto.randomBytes(16);
var cipher = crypto.createCipheriv(this.algorithm,this.key,iv);
var cipherText = cipher.update(plainText,'utf8','hex') + cipher.final('hex');
return iv.toString('hex') + cipherText;
}
decrypt(cipherText){
var iv = Buffer.from(cipherText.slice(0,32),'hex');
var data = cipherText.slice(32);
var decode = crypto.createDecipheriv(this.algorithm,this.key,iv);
var decoded = decode.update(data,'hex','utf8') + decode.final('utf8');
return decoded;
}
}
crypto.createCipher
Your block mode (CBC) requires an IV, but you're using createCipher instead of createCipheriv. I assume this is a typo since you're using createDecipheriv.
I'm having an issue where I was given a file to decrypt along with the Key, IV and encryption method (aes-256-ctr). I have been struggling to decrypt this using node.js and keep running into an error saying the IV length is invalid. I was also given the method to decrypt the file using the BouncyCaste library in C#. The C# method seems to work fine with no issues with the IV. What do I need to do differently in node than what is being done here in C# to avoid this error?
Working C# Decryption (Note: IV is in the filename)
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace c_app
{
class Program
{
static void Main(string[] args)
{
var baseFolder = Directory.GetCurrentDirectory();
// Create parameters
var myDi = new DirectoryInfo(baseFolder);
string keyString = "xxxxxxxxxxxxx32BitKeyxxxxxxxxxxx";
byte[] keyBytes = ASCIIEncoding.UTF8.GetBytes(keyString);
var c = CipherUtilities.GetCipher("AES/CTR/NoPadding");
KeyParameter sk = ParameterUtilities.CreateKeyParameter("AES", keyBytes);
// Get the IV
var files = myDi.GetFiles("001398.20180823.000_1966151284357350418");
var fileInfo = files[0];
var pathSplit = fileInfo.FullName.Split('_');
var filePath = pathSplit[0];
var iv = long.Parse(pathSplit[1]);
// Decrypt the file
var base64String = File.ReadAllText(fileInfo.FullName);
c.Init(false, new ParametersWithIV(sk, BitConverter.GetBytes(iv)));
var inputBytesToDecrypt = Convert.FromBase64String(base64String);
var decryptedBytes = c.DoFinal(inputBytesToDecrypt);
var decryptedText = ASCIIEncoding.UTF8.GetString(decryptedBytes);
// Write file back to current directory
File.WriteAllBytes(string.Format(#"{0}/decrypted.csv", myDi.FullName), decryptedBytes);
}
}
}
My attempt in Node.js
var crypto = require('crypto');
var fs = require('fs');
var iv = Buffer.from('1966151284357350418', 'base64'); // Experimenting with encoding types like base64
var key = Buffer.from('xxxxxxxxxxxxx32BitKeyxxxxxxxxxxx');
fs.readFile('./001398.20180823.000_1966151284357350418', (err, encryptedText) => {
if (err) throw err;
var decipher = crypto.createDecipheriv('aes-256-ctr', key, iv); // <--- Error thrown here
decrypted = decipher.update(encryptedText, 'binary', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
});
In case it is helpful I was also given the method for encrypting the file using BouncyCastle, which can be found here: https://pastebin.com/PWNzDum3