CryptoJS : key.clamp is not a function - javascript

TypeError: key.clamp is not a function
at Object.init (path/node_modules/crypto-js/hmac.js:58:18)
The error above occurs when I try to create JWT in Javascript with the relevant code below.
const CryptoJS = require('crypto-js');
var hash = CryptoJS.HmacSHA256(token.join("."), secret);
crypto-js/hmac.js:58:18 has key.clamp(); and I'm not sure what would be the best approach. I tried with HmacSHA512 but it returns the same error.
I'm running with npm 6.1.0 node v6.10.3 crypto-js ^3.1.9-1.

From their samples, secret (or key as they call it), should be a string.
As such, using CryptoJS like this should work just fine:
const token = "a,b"; // fake token
const secret = CryptoJS.enc.Utf8.parse("mySecret"); //encode mySecret into UTF-8 as suggested in the comments
const CryptoJS = require('crypto-js');
var hash = CryptoJS.HmacSHA256(token.split(","), secret);
console.log(hash);

Related

Convert encryption function from Javascript to Python

I'm trying to convert this code from Javascript to Python3:
import crypto from 'crypto';
const secretKey = 'NgTriSCalcUltAbLoGResOnOuSeAKeSTraLryOuR'
function verifySignature(rawBody) {
const calculatedSignature = crypto
.createHmac('sha256', secretKey)
.update(rawBody, 'utf8')
.digest('base64');
return calculatedSignature;
}
console.log(verifySignature('a'));
With that code I get this output: vC8XBte0duRLElGZ4jCsplsbXnVTwBW4BJsUV1qgZbo=
So I'm trying to convert the same function to Python using this code:
UPDATED
import hmac
import hashlib
message = "a"
key= "NgTriSCalcUltAbLoGResOnOuSeAKeSTraLryOuR"
hmac1 = hmac.new(key=key.encode(), msg=message.encode(), digestmod=hashlib.sha256)
message_digest1 = hmac1.hexdigest()
print(message_digest1)
But I get this error: AttributeError: 'hash' object has no attribute 'digest_size'
Can someone tell me what I am missing to achieve the same output in Python?
Thanks you! :)
You're not getting base64 from the digest() on your return statement. In your javascript code it was also encoded in UTF-8 which should be specified below. The key was also not supplied in your python code.
This code snippet I just tested should generate the same result as your javascript code:
def newhashab(msg, key):
digest = hmac.new(key.encode('UTF-8'), msg.encode('UTF-8'), hashlib.sha256)
return base64.b64encode(digest.digest()).decode('UTF-8')
print(newhashab("a", 'NgTriSCalcUltAbLoGResOnOuSeAKeSTraLryOuR'))
It should return:
'vC8XBte0duRLElGZ4jCsplsbXnVTwBW4BJsUV1qgZbo='

How to get Java DigestUtils.md5() output from Javascript?

Java code that uses
Apache Commons library to generate signature:
byte[] md5 = DigestUtils.md5("test");
String signature = Base64.encodeBase64String(md5);
System.out.println(signature);
// CY9rzUYh03PK3k6DJie09g==
Javascript code I am trying to write to get the same output:
const md5 = CryptoJS.MD5("test");
const signature = btoa(md5);
console.log(signature);
// MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=
I know how to get the same output if I change the Java code like this:
String md5 = DigestUtils.md5Hex("test");
String signature = Base64.encodeBase64String(md5.getBytes(StandardCharsets.UTF_8));
System.out.println(signature);
// MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=
But unfortunately I am not allowed to modify Java code, so how can I modify Javascript code instead, to get the same output as Java code?
I think I found the solution by myself:
const md5 = CryptoJS.MD5("test");
const signature = md5.toString(CryptoJS.enc.Base64);
console.log(signature);
// CY9rzUYh03PK3k6DJie09g==

Javascript with SJCL lib, decrypt AES in GCM mode

I try to decrypt an cipher with AES in GCM mode with the SJCL library in Javascript (from within CasperJS).
When I execute the code below the error I receive is:
error: TypeError: 'undefined' is not a function (evaluating 'b.encrypt([0,
0,0,0])')
The code:
var masterkey = '39537496606860671661230109146651832357';
var cipher = 'Sa2Rk3bbdiaI7mO/';
var iv = '59804781381539321505720964105';
var authdata = '199590863504973848417387014842606357793';
var decff = sjcl.mode.gcm.decrypt(masterkey, cipher, iv, authdata);
console.log (decff);
As you can see, I am basically just calling the decrypt function as the SJCL docs told me to.
The encryption was done in python with this code: https://github.com/bozhu/AES-GCM-Python Wich I found is this thread: AES in GCM mode in Python
Is there anything special I have to consider when encrypting in one language and decrypting in another? Im afraid so...
Can I check somehow if the encryption information are valid AES/GCM?
Im not really sure how to proceed here since Im no JS or Python or encryption expert.
For background information:
I try to achieve a more or less secure encryption in pure python (so I can run it on Google App Engine) and the fitting decryption in pure JS.
Thanks for any help.
You cannot directly decrypt try converting your encrypted string, cypher, IV and auth data to bitArray.
const data = sjcl.mode.gcm.decrypt(cipherArray, encryptedBitArray, iv, authArray, 128);
Here 128 is size you can use 256 as well.
Also try to append your IV with the encypted string.
const bitArray = sjcl.codec.base64.toBits(content);
const bitArrayCopy = bitArray.slice(0);
const ivdec = bitArrayCopy.slice(0, 4);
const encryptedBitArray = bitArray.slice(4);
var key = sjcl.codec.base64.toBits("2d73c1dd2f6a3c981afc7c0d49d7b58f");
let cipher = new sjcl.cipher.aes(key);

I have got my private key and api key,How to create HMAC signature using javascript.What actually is HMAC signature?

I want to create HMAC-SHA1 signature in my Sharepoint app of Indian Railways how should I create following code is not working, I mean when I copy paste my HMAC signature to URL it is giving an error, {"error":"UNAUTHORIZED ACCESS. HMAC SIGNATURE MISMATCH."}. And not displaying json, how should I achieve it following is my code.
<script src="lib/jsSHA/src/sha1.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/hmac-sha1.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/enc-base64-min.js"></script>
<script type="text/javascript" >
var message = "json539ff0f815ca697c681fe01d32ba52e31234567890";
var secret = "<my private key>";
var crypto = CryptoJS.HmacSHA1(message, secret).toString(CryptoJS.enc.Base64);
//var crypto = CryptoJS.HmacSHA1(message, secret).toString();
alert(crypto);
var shaObj = new jsSHA(message, "ASCII");
alert("Welcome");
var jssha = shaObj.getHMAC(secret, "ASCII", "SHA-1", "B64");
alert(crypto + "\n" + jssha);
</script>
HMAC is sort of hash algorithms (it counts something like CRC code for provided message but on cryptographic basis). HMAC counts hash value of the message and uses key for it. The purpose of it is to prove that the hash has been counted only by someone who knows the key and nobody else.
HMAC mismatch error can be caused by many reasons:
You use wrong HMAC algorithm. In your code you use HMAC SHA1 but there are many of them
You use good HMAC algorithm but wrong HMAC parameters. HMAC algorithm has typically several parameters like length, chaining mode,...
You use wrong message formatting. There might be some kind of message formatting rules before you count HMAC.
you use wrong key.
It is happening by following code,
<script src="lib/jsSHA/src/sha1.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/hmac-sha1.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/enc-base64-min.js"></script>
var message = "mrjjson539ff0f815ca697c681fe01d32ba52e3";
var secret = "e439c4c1b7d7d2d52d11c0f1cb56552d";
//var crypto = CryptoJS.HmacSHA1(message, secret).toString(CryptoJS.enc.Base64);
var crypto = CryptoJS.HmacSHA1(message, secret).toString();
//var shaObj = new jsSHA(message, "ASCII");
//var jssha = shaObj.getHMAC(secret, "ASCII", "SHA-1", "B64");
alert("crypto answer is " + crypto);

Validating a JWT in node.js

I'm trying to parse and validate a JWT token in node.js based on this sample (authored in .NET): https://github.com/liveservices/LiveSDK/blob/master/Samples/Asp.net/AuthenticationTokenSample/JsonWebToken.cs
Here is my node js javascript that validates the token:
var validateSignature = function(key, claims, envelope, signature) {
var hasher = crypto.createHash('sha256');
hasher.update(key + "JWTSig");
var key = hasher.digest('binary');
var hmac = crypto.createHmac('sha256', key);
hmac.update(envelope + '.' + claims);
var out = hmac.digest('base64');
console.log(out);
console.log(signature);
console.log(out === signature);
}
Now, the very weird thing is - it almost works. Here's the output of the three console.log statements:
pEwNPJ+LUHBdvNx631UzdyVhPFUOvFY8jG3x/cP81FE=
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
false
It seems suspicious to me that the hashes are both the same except for the +-/_=
Anybody spot my mistake? Something to do with my base64 encoding.
UPDATE
I played some more and there seems to be something funky going on with base64 encoding here. The following code in node js:
console.log(signature);
var b = new Buffer(signature, 'base64');
console.log(b.toString('base64'));
yields:
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
pEwNPJLUHBdvNx631UzdyVhPFUOvFY8jG3xcP81F
Which seems very odd, right?
Thanks to Timothy Meade for commenting and pushing me in the right direction.
Node's Buffer type generates standard Base64 with +, / and =
There is a URL safe base64 encoding as mentioned here: http://en.wikipedia.org/wiki/Base64
It replaces + with -, / with _ and = is optional. The token that is passed on the QueryString (d'uh) is a URL safe version. Hence the difference.
Code was fixed by a simple:
out = out.replace('+','-').replace('/','_').replace('=','');
I wrote this library a while ago, I guess you can use some of the code. It is supposed to run in both node.js and in a modern browser.
JWT library for javascript
This is not the exact method that you were trying to use, but I believe it is the preferred way to validate a JWT in NodeJS. Note that I am using the NPM base64url library to convert between base64Url (the default encoding for a JWT) and base64 (what NodeJS expects for the verification function).
Also note, you need a public and private keypair to sign and verify respectively. I have included the private and public keys that were used to sign and verify this JWT at the bottom of this post.
const base64 = require('base64url');
const crypto = require('crypto');
const verifyFunction = crypto.createVerify('RSA-SHA256');
const fs = require('fs');
// The sample JWT from https://jwt.io/
const JWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA';
// This just gets the value of the public key (same as the one at bottom of this post)
const PUB_KEY = fs.readFileSync(__dirname + '/id_rsa_pub.pem', 'utf8');
// Split the JWT by `.` to get each part
const jwtHeader = JWT.split('.')[0];
const jwtPayload = JWT.split('.')[1];
const jwtSignature = JWT.split('.')[2];
// We only need the first two pieces to verify
verifyFunction.write(jwtHeader + '.' + jwtPayload);
verifyFunction.end();
// IMPORTANT: NodeJS expects base64 format, not base64url format!
const jwtSignatureBase64 = base64.toBase64(jwtSignature);
// IMPORTANT: You need to specify that the `jwtSignatureBase64` data is base64 format,
// otherwise, it will default to Buffer format and return false
const signatureIsValid = verifyFunction.verify(PUB_KEY, jwtSignatureBase64, 'base64');
console.log(signatureIsValid); // true
The keys below are from the example JWT mentioned here.
Private Key:
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw
kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr
m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi
NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV
3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2
QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs
kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go
amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM
+bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9
D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC
0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y
lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+
hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp
bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X
+jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B
BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC
2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx
QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz
5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9
Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0
NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j
8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma
3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K
y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB
jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE=
-----END RSA PRIVATE KEY-----
Public Key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc
aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9
MwIDAQAB
-----END PUBLIC KEY-----

Categories