NodeJS Decrypt des3 Unicode - node.js

I have the following snippet of code
var crypto = require("crypto");
var iv = new Buffer('d146ec4ce3f955cb', "hex");
var key = new Buffer('dc5c3319dc25c1f6f11f6a792a6dd28864c9dd48be26c2e4', "hex");
var encrypted = new Buffer('6A57201D19B07ABFAE74B453BA46381C', "hex");
var cipher = crypto.createDecipheriv('des3', key, iv);
var result = cipher.update(encrypted);
result += cipher.final();
console.log("result: " + result);
The result is "password"
This snippet works great for ASCII based words.
However, I have some unicode passwords.
So for instance this is Pi:
UU__3185CDAA15C1CDED
I have tried using this value, plus the removal of the "UU__" but no gain.
I also tried something like this for the encrypted data:
var encrypted = new Buffer('UU__3185CDAA15C1CDED', "utf16le");
and
var result = cipher.update(encrypted, 'ucs2');
but no go..
I get the following error
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decr ypt
at Error (native)
at Decipheriv.Cipher.final (crypto.js:202:26)
at Object.<anonymous> (/Users/miker/Local Projects/rec10_decryption/server2.js:14:18)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
Any assistance would be greatly appreciated.

Dropping the UU_ prefix and using this code works for me:
var crypto = require('crypto');
var iv = new Buffer('d146ec4ce3f955cb', 'hex');
var key = new Buffer('dc5c3319dc25c1f6f11f6a792a6dd28864c9dd48be26c2e4', 'hex');
var encrypted = new Buffer('3185CDAA15C1CDED', 'hex');
var cipher = crypto.createDecipheriv('des3', key, iv);
var result = Buffer.concat([
cipher.update(encrypted),
cipher.final()
]).toString('ucs2');
console.log('result: ' + result);
// outputs: result: Π
When you do result += cipher.final(), it's first converting result from a Buffer to a (utf8) string, and then appending cipher.final() converted from a Buffer to a (utf8) string. When you have multi-byte characters, this can cause data corruption if you have a character's bytes span across calls to .update() and .final(). Keeping them as Buffers, concatenating them as binary, and then converting the final concatenated result to a utf16 string will work and is much safer.

Related

How to use crpyto in NodeJs

I am learning NodeJs, and I am trying to implement the crypto library to encrypt and decrpty text,
I am referring the following example -
https://www.w3schools.com/nodejs/ref_crypto.asp
The code to encrypt is as follows -
var crypto = require('crypto');
var mykey = crypto.createCipher('aes-128-cbc', 'mypassword');
var mystr = mykey.update('abc', 'utf8', 'hex')
mystr += mykey.update.final('hex');
console.log(mystr);
The code to decrypt is as follows -
var crypto = require('crypto');
var mykey = crypto.createDecipher('aes-128-cbc', 'mypassword');
var mystr = mykey.update('34feb914c099df25794bf9ccb85bea72', 'hex', 'utf8')
mystr += mykey.update.final('utf8');
console.log(mystr);
The code samples seem to work on their environment,
But I am getting the following error when I try to run the same code on my machine -
mystr += mykey.update.final('hex');
^
TypeError: mykey.update.final is not a function
at Object.<anonymous> (/home/user/office/pocs/node-apps/sample-apps/Apps/crypto.js:5:23)
at Module._compile (internal/modules/cjs/loader.js:734:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:797:12)
at executeUserCode (internal/bootstrap/node.js:526:15)
at startMainThreadExecution (internal/bootstrap/node.js:439:3)
Can someone help implement it correctly to encrypt and decrytp text?What am I doing wrong?
update line
mystr += mykey.update.final('hex');
to
mystr += mykey.final("hex");
Tried the code according to
official documentation

how to use Crypto to encrypt and decrypt binary data in Nodejs

I have new to use Crypto to encrypt an audio data in NodeJs. I got some error output when I trying to decrypt the data. here is my test code.
function encrypt (buf, key) {
const cipher = crypto.createCipheriv('des-ecb', key, new Buffer(0))
let c = cipher.update(Buffer.from(buf))
c += cipher.final('binary')
return c
}
function decrypt (buf, key) {
const cipher = crypto.createDecipheriv('des-ecb', key, new Buffer(0))
let c = cipher.update(buf)
c += cipher.final('binary')
return c
}
let pcmbuf = fs.readFileSync("test.pcm")
let enc = encrypt(pcmbuf,gen_key())
let dec = decrypt(enc,gen_key())
fs.writeFileSync('dec.pcm',dec)
It has produced an Error when I running this code. The detail is like bellow.
internal/crypto/cipher.js:104
var ret = this._handle.final();
^
Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Decipheriv.final (internal/crypto/cipher.js:104:26)
at decrypt (/home/zsc/asr-js/test.js:60:17)
at Object.<anonymous> (/home/zsc/asr-js/test.js:67:11)
at Module._compile (module.js:660:30)
at Object.Module._extensions..js (module.js:671:10)
at Module.load (module.js:573:32)
at tryModuleLoad (module.js:513:12)
at Function.Module._load (module.js:505:3)
at Function.Module.runMain (module.js:701:10)
at startup (bootstrap_node.js:190:16)
How could I fix that problem. thanks for answer my problem!
Apparently the problem is with the padding...because of different languages of encrypting/decrypting...the answer is here on node.js github issues page
Quoting the answer
So calling decrypt.setAutoPadding(false); after you create the decipher instance will make it work as expected:
var crypto = require('crypto');
//the encrypted result
var theCipher = "ccZmMULq3tlzAY+iafZz+96xz+qFsAuGpEjhN7CckJTcdBT03fgobfSVGCGYzILyPNSA3e3msUqHUTCpv8kRnWvFdLv9c+GTEhg+Lj5dOThGDHtkQX2j5bd6Eubw9/l+Lcwj0PeyW0ZoVkB5Nnp1yCnmKAn2Euliq+IurgthT+wln6cQmTjXfL4IB5VxwUEb72FcbeiCfbKxa+MxxbcQTCpli3ErSptwdp9on2k87JTPFqyyMmMRFA9VgOXpHNe43IwFzME01DyHZ+Rp/eQguTmY9FtkFIZeD2e2nrbbDbW6tlk/KOtdhGVIlIGMPNS5m8LYqlrGZlJU3JythEy+J0z1wW1owjVe9Yto2OtUe8WeKI744enBKAX4FnD4My7+/XRjbF5kf6loT9lqeMCdXFb3LDej3GVcKWbJuZjXmD4="
var key = "abcdefghijklmnopqrstuvwx"
var decrypt = crypto.createDecipheriv('des-ede3', key, "");
//Add the auto padding here....IT HAVE TO BE after creating the decipher immeditely
decrypt.setAutoPadding(false);
var s = decrypt.update(theCipher, 'base64', 'utf8');
console.log(s + decrypt.final('utf8'));
Finally. I found a way to solve that case. Pass binary encoded string as the parameter instead pass buffer. Code as below.
function encrypt (buf, key) {
const cipher = crypto.createCipheriv('des-ecb', key, new Buffer(0))
let c = cipher.update(buf,'binary','base64')
c += cipher.final('base64')
return c
}
function decrypt (buf, key) {
const cipher = crypto.createDecipheriv('des-ecb', key, new Buffer(0))
let c = cipher.update(buf,'base64','base64')
c += cipher.final('base64')
return c
}
let pcmbuf = fs.readFileSync("test.pcm")
let enc = encrypt(pcmbuf.toString('binary'),gen_key())
let dec = decrypt(enc,gen_key())
fs.writeFileSync('dec.pcm',Buffer.from(dec,'base64'))

Creating a PEM file from javascript looks different from Java causing a failed signature verification

I'm trying to verify a SHA1 with RSA signature with its public key, I have written the java code below which works perfectly but but javascript cannot verify when it uses same modulus and exponent which is created by crypto or ursa. though If i use it against the pem file created by java it works.
any idea or suggestion of the best way of converting the java code to javascript?
JAVA:
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
public class Verify {
static public Boolean verifySignature(String modulus, String exponent , String encodedMsg, String encodedSignature, String signatureAlgorithm)
throws Exception {
try {
RSAPublicKeySpec senderPublicKeySpec =
new RSAPublicKeySpec(
new BigInteger(modulus, 16),
new BigInteger(exponent, 16)
);
RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance(Constants.RSA_KEY).generatePublic(senderPublicKeySpec);
System.out.println("------------ pem file ----------------");
System.out.println("format:" + rsaPublicKey.getFormat());//x.509
byte[] data = rsaPublicKey.getEncoded();
rsaPublicKey.getFormat();
String base64encoded = new String(Base64.getEncoder().encode(data));
System.out.println(base64encoded);
System.out.println("----------------------------");
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(rsaPublicKey);
signature.update(encodedMsg.getBytes());
//this returns true;
return signature.verify(Base64.getDecoder().decode(encodedSignature.getBytes()));
} catch (Exception invaKeySpeExp) {
throw new Exception(invaKeySpeExp.getMessage());
}
}
Javascript:
'use strict';
var ursa = require('ursa');
function verifySignature( modulus, exponent, encodedMsg) {
var pem = fs.readFileSync('./java.pem');
var publicKeyNode = ursa.createPublicKeyFromComponents(new Buffer(modulus,'binary'), new Buffer(exponent,'binary'));
var publicKeyJava = ursa.createPublicKey(pem);
var sig = ursa.createVerifier(signatureAlgorithm);
sig.update(encodedMsg);
var successJ = sig.verify(publicKeyJava , new Buffer(encodedSignature, 'base64'), 'base64');
console.log(successJ);
var successN = sig.verify(publicKeyNode , new Buffer(encodedSignature, 'base64'), 'base64');
console.log(successN);
}
OUTPUT:
true //from verifying against PEM file created by Java
crypto.js:126 //from Verifying against modulus and exponent
return this._handle.digest(outputEncoding);
^
Error: Not initialized
at Error (native)
at Hash.digest (crypto.js:126:23)
at Object.verify (/Users/aemami/WebstormProjects/temp/node_modules/ursa/lib/ursa.js:705:39)
at verifySignature (/Users/aemami/WebstormProjects/temp/index.js:28:22)
at Object.<anonymous> (/Users/aemami/WebstormProjects/temp/index.js:64:1)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)

How to create an RSA key from hex-encoded modulus and encrypt in node.js

I'm finding the way to RSA encryption in node.js, I want to handle big numbers, so I use this: https://github.com/eschnou/node-bignumber
What I'm going to do is just encryption, with modulus and exponent. I don't have to do decryption. anyway, I got an error on and on, but I don't know what's wrong. Can anyone know what it is wrong? Thanks.
Code
require("node-bignumber");
var nvalue="ad6eb61316ff805e9c94667ab04aa45aa3203eef71ba8c12afb353a5c7f11657e43f5ce4483d4e6eca46af6b3bde4981499014730d3b233420bf3ecd3287a2768da8bd401f0abd7a5a137d700f0c9d0574ef7ba91328e9a6b055820d03c98d56943139075d";
var evalue="010001";
var encpw="";
var rsa = new RSAKey;
function encryptMessage() {
var message = "All your bases are belong to us.";
rsa.setPublic(evalue, nvalue);
encpw.value = rsa.encrypt(message);
console.log(encpw);
}
encryptMessage();
Error
ReferenceError: RSAKey is not defined
at Object.<anonymous> (c:\Users\win\Desktop\untitled\juntae.js:5:15)
at Module._compile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Function.Module.runMain (module.js:467:10)
at startup (node.js:136:18)
at node.js:963:3
You should be able to load an RSA public key from modulus and public exponent in this way:
var rsa = require("node-bignumber");
var n = "ad6eb61316ff805e9c94667ab04aa45aa3203eef71ba8c12afb353a5c7f11657e43f5ce4483d4e6eca46af6b3bde4981499014730d3b233420bf3ecd3287a2768da8bd401f0abd7a5a137d700f0c9d0574ef7ba91328e9a6b055820d03c98d56943139075d";
var e = "010001";
var pub = new rsa.Key();
pub.setPublic(n, e);
var message = "Message";
var encrypted = pub.encrypt(message);
console.log(encrypted);
The public key in RSA consists of the modulus and the public exponent, because both values are needed during encryption.

Error handling in using Crypto in Node.js

I am using Crypto library of Node.js for encryption/decryption as follows :
encrypt = function(text, passPhrase){
var cipher = crypto.createCipher('AES-128-CBC-HMAC-SHA1', passPhrase);
var crypted = cipher.update(text,'utf8','hex');
crypted += cipher.final('hex');
return crypted;
} ,
decrypt = function(text, passPhrase){
var decipher = crypto.createDecipher('AES-128-CBC-HMAC-SHA1', passPhrase)
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}
There is no problem with encryption part. and if I send the correct passPhrase for decryption there is also no problem. My problem is,if I send 'wrong' passPhrase for decryption, code breaks and throw an error :
TypeError: Bad input string
at Decipher.Cipher.update (crypto.js:279:27)
at module.exports.decrypt (/xxxx/yyyyy/jjj/ssss/encryptionService.js:19:28)
at Object.module.exports.passwordDecryptor (/xxxx/yyyyy/jjj/ssss/encryptionService.js:59:56)
at Object.<anonymous> (/xxxx/yyyyy/jjj/ssss/test.js:32:33)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
I dont want it happen. I want for example decrypt function returns 'Passpharse is wrong' sentence. According to the documentation enter link description here createDecipher
function doesn't accept a callback function.
I solved the problem with try and catch. (The callback function doesn't work.)
decrypt = function(text, passPhrase){
var decipher = crypto.createDecipher('AES-128-CBC-HMAC-SHA1', passPhrase);
try {
var dec = decipher.update(text,'hex','utf8');
dec += decipher.final('utf8');
return dec;
} catch (ex) {
console.log('failed');
return;
}
}

Resources