I'm attempting to port some Python code to Javascript. Here is the Python code:
# Python
import codecs
from Crypto.Cipher import AES
key = b"\xc3\x99\xff\xff\xc3\x99\xff\xff\xc3\x99\xff\xff\xc3\x99\xff\xff"
...
aes = AES.new(key, AES.MODE_ECB)
token = aes.encrypt("HELLO\x00\x00".encode("utf-8"))
token_hex = codecs.encode(token, "hex").decode("utf-8")
I'm not exactly sure how to port my Python key variable. Should it be UInt16Array...or a string?
This is my Javascript so far:
// Javascript
const crypto = require('crypto');
const key = '???' // <-- This is one place I am stuck. String? Byte array?
....
const cipher = crypto.createCipher('aes-128-ecb', key);
let tokenHex = cipher.update('HELLO\x00\x00', 'utf8', 'hex');
tokenHex = tokenHex.toString('utf8')
I appreciate any insight you can provide as to how I can get a matching tokenHex in Javascript.
Thank you!
What you are after is Buffer, which represents a collection of bytes.
You probably want to instantiate the key variable similar to this:
let key = Buffer.from("c399ff...", "hex");
Related
I am trying to encrypt a message. But cipher.update() returns null (The console.log at the end doesn't print anything).The code used:
const crypto = require('crypto')
let iv = crypto.randomBytes(16)
let key = crypto.createHash('sha256').update('MyKey').digest('hex').slice(0,32)
let cipher = crypto.createCipheriv('aes-256-cbc',key,iv)
encryptedPassword = cipher.update('encrypt this message','utf-8','hex')
console.log(encryptedPassword)
I can't understand why this is so. I followed instructions from this docs. I am new to nodejs, If I have missed something, do correct me. Thanks!
I have Ruby 2.5.3 code that create hmac with sha256
require 'openssl'
key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25'
message = 'lucas'
hash = OpenSSL::HMAC.hexdigest('sha256', key, message)
hash => ba2e2505c6f302fb3c40bea4491d95bacd96c3d12e8fbe50197ca431165fcee2
But the result is different from Python & JavaScript code. What should I do in Ruby code to have the same result as from the others?
Python
import hmac
import hashlib
import binascii
message = "lucas"
key = "4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25"
hash = hmac.new(
binascii.unhexlify(bytearray(key, "utf-8")),
msg=message.encode('utf-8'),
digestmod=hashlib.sha256
).hexdigest()
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
JavaScript
const crypto = require('crypto');
const message = 'lucas';
const key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25';
const hash = crypto.createHmac('sha256', Buffer.from(key, 'hex'))
.update(message)
.digest('hex');
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
In Python and JS you are using the "key" as hexstring, means that the hexstring is converted to a binary format. In Ruby the key is used without conversion. – Michael Fehr
This gave me the solution.
key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25'
message = 'lucas'
puts OpenSSL::HMAC.hexdigest('sha256', [key].pack('H*') , message)
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
thank you!
I have an Angular project in which I have to implement datatrans payment. But I am not able to generate sign for payment.
I am following process given on this link (enter link description here) to generate sign.
But i am not able to achive it.
I am using angular library crypto-js to generate HMAC-SHA-256 signed string.
Here is my javascript code.
const merchantId = 'xxxxxxx';
const refNo = '1234567890';
const amount = 0;
const currency = 'CHF';
const theme = 'DT2015';
const paymentmethod = 'VIS';
const stringSs = merchantId+amount+currency+refNo;
const base = 16;
// My Hmac Key
const s = 'fa3d0ea1772cf21e53158283e4f123ebf1eb1ccfb15619e2fc91ee6860a2e5e48409e902b610ce5dc6f7f77fab8affb60d69b2a7aa9acf56723d868d36ab3f32';
// Step 1: Code to generate hex to byte of hmac key
const a = s.replace(/../g, '$&_').slice (0, -1).split ('_').map ((x) => parseInt (x, base));
// Step 3: Sign the string with HMAC-SHA-256 together with your HMAC key
const signedString = HmacSHA256(a, stringSs);
// Step 4: Translate the signature from byte to hex format
const signString = enc.Hex.stringify(signedString);
Can you help me into this to suggest what i am doing wrong or in what way it can be achieved.
You can do it with crypto (no need of extra libraries to install)
// Typescript
import * as crypto from 'crypto';
function signKey (clientKey: string, msg: string) {
const key = new Buffer(clientKey, 'hex');
return crypto.createHmac('sha256', key).update(msg).digest('hex');
}
// Javascript
const crypto = require('crypto')
function signKey (clientKey, msg) {
const key = new Buffer(clientKey, 'hex');
return crypto.createHmac('sha256', key).update(msg).digest('hex');
}
signKey(s, stringSs)
To answer the question for crypto-js (see https://github.com/brix/crypto-js) as requested, the following will do the trick:
// Javascript; example from datatrans documentation using a random key
stringSs ='3000017692850CHF91827364';
key='1ca12d7c0629194a9f9d0dbbc957709dd3aed385925b077e726813f0b452de6a38256abd1116138d21754cfb33964b6b1aaa375b74d3580fcda916898f553c92';
expectedSign='d7dee9ae1e542bc02bcb063a3dd3673871b2e43ccb4c230f26e8b85d14e25901';
signedString = CryptoJS.HmacSHA256(stringSs, CryptoJS.enc.Hex.parse(key));
resultSign = CryptoJS.enc.Hex.stringify(signedString);
// now resultSign == expectedSign is true :-)
Ninja Turtles approach was almost correct except of step 1, hex to byte. Use a builtin function of Crypto-JS instead and everything works as expected.
I have following code in Java.
String secretString = 'AAABBBCCC'
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = SecureRandom.getInstance("SHA1PRNG");
securerandom.setSeed(secretString.getBytes());
kgen.init(256, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
byte[] cryptograph = cipher.doFinal(byteContent);
String enc1 = Base64.getEncoder().encodeToString(cryptograph);
return enc1;
I need to implement it in JavaScript/Node.js, however I can only figure out the last half in js like below
'use strict';
const crypto = require('crypto');
const ALGORITHM = 'AES-256-ECB';
const secretString = 'AAABBBCCC'
// missing part in JS (how to convert secretString to key)
function encrypt(plaintext, key) {
const cipher = crypto.createCipheriv(ALGORITHM, key, Buffer.alloc(0));
return cipher.update(plaintext, 'utf8', 'base64') + cipher.final('base64');
}
For the previous Java part( from secretString to key generated by KeyGenerator), I don't know how to implement it in JavaScript, neither do I know whether there is a thing like KeyGenerator in JavaScript world could help me to do the heavy lifting work.
I think this is what you're after:
const crypto = require("crypto-js");
// Encrypt
const ciphertext = crypto.AES.encrypt('SOMETHING SECRET', 'secret key 123');
// Decrypt
const bytes = crypto.AES.decrypt(ciphertext.toString(), 'secret key 123');
const decryptedData = bytes.toString(crypto.enc.Utf8);
console.log(decryptedData);
https://runkit.com/mswilson4040/5b74f914d4998d0012cccdc0
UPDATE
JavaScript does not have a native equivalent for key generation. The answer is to create your own or use a third party module. I would recommend something like uuid for starters.
You can use crypto.randomBytes().
As per its documentation:
Generates cryptographically strong pseudo-random data. The size argument is a number indicating the number of bytes to generate.
Also, it uses openssl's RAND_bytes API behind scenes
I am using the below code to encrypt strings in my node.js code.
I would like to understand how to generate KEY and HMAC_KEY from a static source. In my program, it's generated randomly as of now. As it's generated randomly, I am not able to encrypt my database password using the below algorithm.
crypto = require('crypto');
ALGORITHM = "AES-256-CBC";
HMAC_ALGORITHM = "SHA256";
KEY = crypto.randomBytes(32);
HMAC_KEY = crypto.randomBytes(32);
function (plain_text) {
var IV = new Buffer(crypto.randomBytes(16)); // ensure that the IV (initialization vector) is random
var cipher_text;
var hmac;
var encryptor;
encryptor = crypto.createCipheriv(ALGORITHM, KEY, IV);
encryptor.setEncoding('hex');
encryptor.write(plain_text);
encryptor.end();
cipher_text = encryptor.read();
hmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY);
hmac.update(cipher_text);
hmac.update(IV.toString('hex')); // ensure that both the IV and the cipher-text is protected by the HMAC
// The IV isn't a secret so it can be stored along side everything else
return cipher_text + "$" + IV.toString('hex') + "$" + hmac.digest('hex')
};
You have to split your code into two executions:
Code that generates your keys and presents them in a storable format
KEY = crypto.randomBytes(32);
HMAC_KEY = crypto.randomBytes(32);
console.log(KEY.toString('hex'));
console.log(HMAC_KEY.toString('hex'));
Code that uses the stored keys
KEY = Buffer.from('some key string', 'hex');
HMAC_KEY = Buffer.from('some other key string', 'hex');
You just have to make sure that your keys aren't actually in your code, but rather in some file, because hardcoding key in code and checking them into your version control system is a bad idea and might give your developers access to production systems which they probably shouldn't have.