How to sign a JWT with a private key (pem) in CryptoJS?












5















I am trying to create a signed JWT in postman with the following code



function base64url(source) {
// Encode in classical base64
encodedSource = CryptoJS.enc.Base64.stringify(source);

// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');

// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/+/g, '-');
encodedSource = encodedSource.replace(///g, '_');

return encodedSource;
}

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "HS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var secret = 'myjwtsecret';

// encode header
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signature = CryptoJS.HmacSHA256(token, secret);
signature = base64url(signature);
var signedToken = token + "." + signature;

postman.setEnvironmentVariable("payload", signedToken);


Code taken from https://gist.github.com/corbanb/db03150abbe899285d6a86cc480f674d .



I've been trying to input the PEM as the secret but does not work. Also can't find any HmacSHA256 overload that takes a PEM.



How can that be done?










share|improve this question























  • Did you manage to get it working in the end?

    – Sébastien Renauld
    Dec 29 '18 at 21:52
















5















I am trying to create a signed JWT in postman with the following code



function base64url(source) {
// Encode in classical base64
encodedSource = CryptoJS.enc.Base64.stringify(source);

// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');

// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/+/g, '-');
encodedSource = encodedSource.replace(///g, '_');

return encodedSource;
}

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "HS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var secret = 'myjwtsecret';

// encode header
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signature = CryptoJS.HmacSHA256(token, secret);
signature = base64url(signature);
var signedToken = token + "." + signature;

postman.setEnvironmentVariable("payload", signedToken);


Code taken from https://gist.github.com/corbanb/db03150abbe899285d6a86cc480f674d .



I've been trying to input the PEM as the secret but does not work. Also can't find any HmacSHA256 overload that takes a PEM.



How can that be done?










share|improve this question























  • Did you manage to get it working in the end?

    – Sébastien Renauld
    Dec 29 '18 at 21:52














5












5








5








I am trying to create a signed JWT in postman with the following code



function base64url(source) {
// Encode in classical base64
encodedSource = CryptoJS.enc.Base64.stringify(source);

// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');

// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/+/g, '-');
encodedSource = encodedSource.replace(///g, '_');

return encodedSource;
}

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "HS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var secret = 'myjwtsecret';

// encode header
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signature = CryptoJS.HmacSHA256(token, secret);
signature = base64url(signature);
var signedToken = token + "." + signature;

postman.setEnvironmentVariable("payload", signedToken);


Code taken from https://gist.github.com/corbanb/db03150abbe899285d6a86cc480f674d .



I've been trying to input the PEM as the secret but does not work. Also can't find any HmacSHA256 overload that takes a PEM.



How can that be done?










share|improve this question














I am trying to create a signed JWT in postman with the following code



function base64url(source) {
// Encode in classical base64
encodedSource = CryptoJS.enc.Base64.stringify(source);

// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');

// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/+/g, '-');
encodedSource = encodedSource.replace(///g, '_');

return encodedSource;
}

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "HS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var secret = 'myjwtsecret';

// encode header
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signature = CryptoJS.HmacSHA256(token, secret);
signature = base64url(signature);
var signedToken = token + "." + signature;

postman.setEnvironmentVariable("payload", signedToken);


Code taken from https://gist.github.com/corbanb/db03150abbe899285d6a86cc480f674d .



I've been trying to input the PEM as the secret but does not work. Also can't find any HmacSHA256 overload that takes a PEM.



How can that be done?







javascript jwt postman cryptojs






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 28 '18 at 23:37









AleksandarAleksandar

1,99642040




1,99642040













  • Did you manage to get it working in the end?

    – Sébastien Renauld
    Dec 29 '18 at 21:52



















  • Did you manage to get it working in the end?

    – Sébastien Renauld
    Dec 29 '18 at 21:52

















Did you manage to get it working in the end?

– Sébastien Renauld
Dec 29 '18 at 21:52





Did you manage to get it working in the end?

– Sébastien Renauld
Dec 29 '18 at 21:52












1 Answer
1






active

oldest

votes


















2





+300









The mention of postman changed this. I have a solution for you, but it's not exactly a clean way by any mean.



You'll need to create a request that you will need to execute whenever you open postman. Go as follows:



Side-loading jsrsasign-js



The purpose of this request is to side-load jsrsasign-js and storing it in a global Postman variable.



Once this is done, you can then use this content elsewhere. For every request you need a RSA256 JWT signature, the following pre-request script will update a variable (here, token) with the token:



var navigator = {};
var window = {};
eval(pm.globals.get("jsrsasign-js"));

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}

var header = {"alg" : "RS256","typ" : "JWT"};
var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcrqH0L91/j8sglOeroGyuKr1ABvTkZj0ATLBcvsA91/C7fipAsOn
RqRPZr4Ja+MCx0Qvdc6JKXa5tSb51bNwxwIDAQABAkBPzI5LE+DuRuKeg6sLlgrJ
h5+Bw9kUnF6btsH3R78UUANOk0gGlu9yUkYKUkT0SC9c6HDEKpSqILAUsXdx6SOB
AiEA1FbR++FJ56CEw1BiP7l1drM9Mr1UVvUp8W71IsoZb1MCIQCKUafDLg+vPj1s
HiEdrPZ3pvzvteXLSuniH15AKHEuPQIhAIsgB519UysMpXBDbtxJ64jGj8Z6/pOr
NrwV80/EEz45AiBlgTLZ2w2LjuNIWnv26R0eBZ+M0jHGlD06wcZK0uLsCQIgT1kC
uNcDTERjwEbFKJpXC8zTLSPcaEOlbiriIKMnpNw=
-----END RSA PRIVATE KEY-----";

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);

var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, privateKey);

pm.variables.set('token', sJWT);


In order:
- I define mock window and navigator objects as jsrsasign-js needs them.
- I then eval() the content of what we fetched earlier in order to rehydrate everything
- The rest of your code is simple usage of jsrsasign-js. Your token info is there, and I've defined a private key there. You can change this or use an environment variable; it's just there for demo purposes. I then simply use the rehydrated library to sign it, and set the variable to the value of the signed JWT.





A PEM, as you refer to it, is a container format specifying a combination of public and/or private key. You're using it to sign using HMAC-SHA256, which operates on a shared secret. This obviously isn't going to work (unless you take the poor man's approach and use your public key as the shared secret).



Fortunately enough, there are other signature methods defined in the RFCs. For instance, there is a way to sign using RSA, and a very convenient way of defining a public key as a JSON web key (JWK). We're going to be leveraging both.



I've generated a key pair for testing, they're named out and out.pub. Generation tool is genrsa (and as such, they're an RSA keypair).



In order to sign, we're going to have to change a few things:




  • We're changing algorithms from HS256 to RS256, as explained above

  • We're going to need a new library to do the signing itself, as crypto-js does not support asymmetric key crypto. We'll fall back to the native crypto module, though there are pure-JS alternatives


The code:



var CryptoJS = require("crypto-js");
var keyFileContent = require("fs").readFileSync("./out");
var pubkey = require("fs").readFileSync("./out.pub");
var base64url = require("base64url");
var nJwt = require("njwt");
function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "RS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

// encode header
var stringifiedHeader = JSON.stringify(header);
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = JSON.stringify(data);
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signatureAlg = require("crypto").createSign("sha256");
signatureAlg.update(token);
var signature = signatureAlg.sign(keyFileContent);
signature = base64url(signature);
var signedToken = token + "." + signature;

console.log(signedToken);

// Verify
var verifier = new nJwt.Verifier();
verifier.setSigningAlgorithm('RS256');
verifier.setSigningKey(pubkey);
verifier.verify(signedToken, function() {
console.log(arguments);
});


And that's it! It's quite literally that simple, although I would not recommend rewriting the sign() function from crypto from scratch. Leave it to a library that has had thorough inspection by the community, and crypto is pretty serious business.






share|improve this answer


























  • I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

    – Aleksandar
    Dec 30 '18 at 10:55











  • Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

    – janniks
    Jan 3 at 19:32













  • That's going to be really fun then, as cryptojs doesn't support RSA.

    – Sébastien Renauld
    Jan 4 at 2:38











  • In other words without creating a custom javascript code for running this, there is no way?

    – Aleksandar
    Jan 7 at 17:44











  • @Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

    – Sébastien Renauld
    Jan 7 at 18:32











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965446%2fhow-to-sign-a-jwt-with-a-private-key-pem-in-cryptojs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2





+300









The mention of postman changed this. I have a solution for you, but it's not exactly a clean way by any mean.



You'll need to create a request that you will need to execute whenever you open postman. Go as follows:



Side-loading jsrsasign-js



The purpose of this request is to side-load jsrsasign-js and storing it in a global Postman variable.



Once this is done, you can then use this content elsewhere. For every request you need a RSA256 JWT signature, the following pre-request script will update a variable (here, token) with the token:



var navigator = {};
var window = {};
eval(pm.globals.get("jsrsasign-js"));

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}

var header = {"alg" : "RS256","typ" : "JWT"};
var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcrqH0L91/j8sglOeroGyuKr1ABvTkZj0ATLBcvsA91/C7fipAsOn
RqRPZr4Ja+MCx0Qvdc6JKXa5tSb51bNwxwIDAQABAkBPzI5LE+DuRuKeg6sLlgrJ
h5+Bw9kUnF6btsH3R78UUANOk0gGlu9yUkYKUkT0SC9c6HDEKpSqILAUsXdx6SOB
AiEA1FbR++FJ56CEw1BiP7l1drM9Mr1UVvUp8W71IsoZb1MCIQCKUafDLg+vPj1s
HiEdrPZ3pvzvteXLSuniH15AKHEuPQIhAIsgB519UysMpXBDbtxJ64jGj8Z6/pOr
NrwV80/EEz45AiBlgTLZ2w2LjuNIWnv26R0eBZ+M0jHGlD06wcZK0uLsCQIgT1kC
uNcDTERjwEbFKJpXC8zTLSPcaEOlbiriIKMnpNw=
-----END RSA PRIVATE KEY-----";

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);

var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, privateKey);

pm.variables.set('token', sJWT);


In order:
- I define mock window and navigator objects as jsrsasign-js needs them.
- I then eval() the content of what we fetched earlier in order to rehydrate everything
- The rest of your code is simple usage of jsrsasign-js. Your token info is there, and I've defined a private key there. You can change this or use an environment variable; it's just there for demo purposes. I then simply use the rehydrated library to sign it, and set the variable to the value of the signed JWT.





A PEM, as you refer to it, is a container format specifying a combination of public and/or private key. You're using it to sign using HMAC-SHA256, which operates on a shared secret. This obviously isn't going to work (unless you take the poor man's approach and use your public key as the shared secret).



Fortunately enough, there are other signature methods defined in the RFCs. For instance, there is a way to sign using RSA, and a very convenient way of defining a public key as a JSON web key (JWK). We're going to be leveraging both.



I've generated a key pair for testing, they're named out and out.pub. Generation tool is genrsa (and as such, they're an RSA keypair).



In order to sign, we're going to have to change a few things:




  • We're changing algorithms from HS256 to RS256, as explained above

  • We're going to need a new library to do the signing itself, as crypto-js does not support asymmetric key crypto. We'll fall back to the native crypto module, though there are pure-JS alternatives


The code:



var CryptoJS = require("crypto-js");
var keyFileContent = require("fs").readFileSync("./out");
var pubkey = require("fs").readFileSync("./out.pub");
var base64url = require("base64url");
var nJwt = require("njwt");
function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "RS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

// encode header
var stringifiedHeader = JSON.stringify(header);
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = JSON.stringify(data);
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signatureAlg = require("crypto").createSign("sha256");
signatureAlg.update(token);
var signature = signatureAlg.sign(keyFileContent);
signature = base64url(signature);
var signedToken = token + "." + signature;

console.log(signedToken);

// Verify
var verifier = new nJwt.Verifier();
verifier.setSigningAlgorithm('RS256');
verifier.setSigningKey(pubkey);
verifier.verify(signedToken, function() {
console.log(arguments);
});


And that's it! It's quite literally that simple, although I would not recommend rewriting the sign() function from crypto from scratch. Leave it to a library that has had thorough inspection by the community, and crypto is pretty serious business.






share|improve this answer


























  • I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

    – Aleksandar
    Dec 30 '18 at 10:55











  • Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

    – janniks
    Jan 3 at 19:32













  • That's going to be really fun then, as cryptojs doesn't support RSA.

    – Sébastien Renauld
    Jan 4 at 2:38











  • In other words without creating a custom javascript code for running this, there is no way?

    – Aleksandar
    Jan 7 at 17:44











  • @Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

    – Sébastien Renauld
    Jan 7 at 18:32
















2





+300









The mention of postman changed this. I have a solution for you, but it's not exactly a clean way by any mean.



You'll need to create a request that you will need to execute whenever you open postman. Go as follows:



Side-loading jsrsasign-js



The purpose of this request is to side-load jsrsasign-js and storing it in a global Postman variable.



Once this is done, you can then use this content elsewhere. For every request you need a RSA256 JWT signature, the following pre-request script will update a variable (here, token) with the token:



var navigator = {};
var window = {};
eval(pm.globals.get("jsrsasign-js"));

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}

var header = {"alg" : "RS256","typ" : "JWT"};
var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcrqH0L91/j8sglOeroGyuKr1ABvTkZj0ATLBcvsA91/C7fipAsOn
RqRPZr4Ja+MCx0Qvdc6JKXa5tSb51bNwxwIDAQABAkBPzI5LE+DuRuKeg6sLlgrJ
h5+Bw9kUnF6btsH3R78UUANOk0gGlu9yUkYKUkT0SC9c6HDEKpSqILAUsXdx6SOB
AiEA1FbR++FJ56CEw1BiP7l1drM9Mr1UVvUp8W71IsoZb1MCIQCKUafDLg+vPj1s
HiEdrPZ3pvzvteXLSuniH15AKHEuPQIhAIsgB519UysMpXBDbtxJ64jGj8Z6/pOr
NrwV80/EEz45AiBlgTLZ2w2LjuNIWnv26R0eBZ+M0jHGlD06wcZK0uLsCQIgT1kC
uNcDTERjwEbFKJpXC8zTLSPcaEOlbiriIKMnpNw=
-----END RSA PRIVATE KEY-----";

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);

var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, privateKey);

pm.variables.set('token', sJWT);


In order:
- I define mock window and navigator objects as jsrsasign-js needs them.
- I then eval() the content of what we fetched earlier in order to rehydrate everything
- The rest of your code is simple usage of jsrsasign-js. Your token info is there, and I've defined a private key there. You can change this or use an environment variable; it's just there for demo purposes. I then simply use the rehydrated library to sign it, and set the variable to the value of the signed JWT.





A PEM, as you refer to it, is a container format specifying a combination of public and/or private key. You're using it to sign using HMAC-SHA256, which operates on a shared secret. This obviously isn't going to work (unless you take the poor man's approach and use your public key as the shared secret).



Fortunately enough, there are other signature methods defined in the RFCs. For instance, there is a way to sign using RSA, and a very convenient way of defining a public key as a JSON web key (JWK). We're going to be leveraging both.



I've generated a key pair for testing, they're named out and out.pub. Generation tool is genrsa (and as such, they're an RSA keypair).



In order to sign, we're going to have to change a few things:




  • We're changing algorithms from HS256 to RS256, as explained above

  • We're going to need a new library to do the signing itself, as crypto-js does not support asymmetric key crypto. We'll fall back to the native crypto module, though there are pure-JS alternatives


The code:



var CryptoJS = require("crypto-js");
var keyFileContent = require("fs").readFileSync("./out");
var pubkey = require("fs").readFileSync("./out.pub");
var base64url = require("base64url");
var nJwt = require("njwt");
function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "RS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

// encode header
var stringifiedHeader = JSON.stringify(header);
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = JSON.stringify(data);
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signatureAlg = require("crypto").createSign("sha256");
signatureAlg.update(token);
var signature = signatureAlg.sign(keyFileContent);
signature = base64url(signature);
var signedToken = token + "." + signature;

console.log(signedToken);

// Verify
var verifier = new nJwt.Verifier();
verifier.setSigningAlgorithm('RS256');
verifier.setSigningKey(pubkey);
verifier.verify(signedToken, function() {
console.log(arguments);
});


And that's it! It's quite literally that simple, although I would not recommend rewriting the sign() function from crypto from scratch. Leave it to a library that has had thorough inspection by the community, and crypto is pretty serious business.






share|improve this answer


























  • I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

    – Aleksandar
    Dec 30 '18 at 10:55











  • Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

    – janniks
    Jan 3 at 19:32













  • That's going to be really fun then, as cryptojs doesn't support RSA.

    – Sébastien Renauld
    Jan 4 at 2:38











  • In other words without creating a custom javascript code for running this, there is no way?

    – Aleksandar
    Jan 7 at 17:44











  • @Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

    – Sébastien Renauld
    Jan 7 at 18:32














2





+300







2





+300



2




+300





The mention of postman changed this. I have a solution for you, but it's not exactly a clean way by any mean.



You'll need to create a request that you will need to execute whenever you open postman. Go as follows:



Side-loading jsrsasign-js



The purpose of this request is to side-load jsrsasign-js and storing it in a global Postman variable.



Once this is done, you can then use this content elsewhere. For every request you need a RSA256 JWT signature, the following pre-request script will update a variable (here, token) with the token:



var navigator = {};
var window = {};
eval(pm.globals.get("jsrsasign-js"));

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}

var header = {"alg" : "RS256","typ" : "JWT"};
var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcrqH0L91/j8sglOeroGyuKr1ABvTkZj0ATLBcvsA91/C7fipAsOn
RqRPZr4Ja+MCx0Qvdc6JKXa5tSb51bNwxwIDAQABAkBPzI5LE+DuRuKeg6sLlgrJ
h5+Bw9kUnF6btsH3R78UUANOk0gGlu9yUkYKUkT0SC9c6HDEKpSqILAUsXdx6SOB
AiEA1FbR++FJ56CEw1BiP7l1drM9Mr1UVvUp8W71IsoZb1MCIQCKUafDLg+vPj1s
HiEdrPZ3pvzvteXLSuniH15AKHEuPQIhAIsgB519UysMpXBDbtxJ64jGj8Z6/pOr
NrwV80/EEz45AiBlgTLZ2w2LjuNIWnv26R0eBZ+M0jHGlD06wcZK0uLsCQIgT1kC
uNcDTERjwEbFKJpXC8zTLSPcaEOlbiriIKMnpNw=
-----END RSA PRIVATE KEY-----";

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);

var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, privateKey);

pm.variables.set('token', sJWT);


In order:
- I define mock window and navigator objects as jsrsasign-js needs them.
- I then eval() the content of what we fetched earlier in order to rehydrate everything
- The rest of your code is simple usage of jsrsasign-js. Your token info is there, and I've defined a private key there. You can change this or use an environment variable; it's just there for demo purposes. I then simply use the rehydrated library to sign it, and set the variable to the value of the signed JWT.





A PEM, as you refer to it, is a container format specifying a combination of public and/or private key. You're using it to sign using HMAC-SHA256, which operates on a shared secret. This obviously isn't going to work (unless you take the poor man's approach and use your public key as the shared secret).



Fortunately enough, there are other signature methods defined in the RFCs. For instance, there is a way to sign using RSA, and a very convenient way of defining a public key as a JSON web key (JWK). We're going to be leveraging both.



I've generated a key pair for testing, they're named out and out.pub. Generation tool is genrsa (and as such, they're an RSA keypair).



In order to sign, we're going to have to change a few things:




  • We're changing algorithms from HS256 to RS256, as explained above

  • We're going to need a new library to do the signing itself, as crypto-js does not support asymmetric key crypto. We'll fall back to the native crypto module, though there are pure-JS alternatives


The code:



var CryptoJS = require("crypto-js");
var keyFileContent = require("fs").readFileSync("./out");
var pubkey = require("fs").readFileSync("./out.pub");
var base64url = require("base64url");
var nJwt = require("njwt");
function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "RS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

// encode header
var stringifiedHeader = JSON.stringify(header);
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = JSON.stringify(data);
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signatureAlg = require("crypto").createSign("sha256");
signatureAlg.update(token);
var signature = signatureAlg.sign(keyFileContent);
signature = base64url(signature);
var signedToken = token + "." + signature;

console.log(signedToken);

// Verify
var verifier = new nJwt.Verifier();
verifier.setSigningAlgorithm('RS256');
verifier.setSigningKey(pubkey);
verifier.verify(signedToken, function() {
console.log(arguments);
});


And that's it! It's quite literally that simple, although I would not recommend rewriting the sign() function from crypto from scratch. Leave it to a library that has had thorough inspection by the community, and crypto is pretty serious business.






share|improve this answer















The mention of postman changed this. I have a solution for you, but it's not exactly a clean way by any mean.



You'll need to create a request that you will need to execute whenever you open postman. Go as follows:



Side-loading jsrsasign-js



The purpose of this request is to side-load jsrsasign-js and storing it in a global Postman variable.



Once this is done, you can then use this content elsewhere. For every request you need a RSA256 JWT signature, the following pre-request script will update a variable (here, token) with the token:



var navigator = {};
var window = {};
eval(pm.globals.get("jsrsasign-js"));

function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}

var header = {"alg" : "RS256","typ" : "JWT"};
var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcrqH0L91/j8sglOeroGyuKr1ABvTkZj0ATLBcvsA91/C7fipAsOn
RqRPZr4Ja+MCx0Qvdc6JKXa5tSb51bNwxwIDAQABAkBPzI5LE+DuRuKeg6sLlgrJ
h5+Bw9kUnF6btsH3R78UUANOk0gGlu9yUkYKUkT0SC9c6HDEKpSqILAUsXdx6SOB
AiEA1FbR++FJ56CEw1BiP7l1drM9Mr1UVvUp8W71IsoZb1MCIQCKUafDLg+vPj1s
HiEdrPZ3pvzvteXLSuniH15AKHEuPQIhAIsgB519UysMpXBDbtxJ64jGj8Z6/pOr
NrwV80/EEz45AiBlgTLZ2w2LjuNIWnv26R0eBZ+M0jHGlD06wcZK0uLsCQIgT1kC
uNcDTERjwEbFKJpXC8zTLSPcaEOlbiriIKMnpNw=
-----END RSA PRIVATE KEY-----";

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);

var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, privateKey);

pm.variables.set('token', sJWT);


In order:
- I define mock window and navigator objects as jsrsasign-js needs them.
- I then eval() the content of what we fetched earlier in order to rehydrate everything
- The rest of your code is simple usage of jsrsasign-js. Your token info is there, and I've defined a private key there. You can change this or use an environment variable; it's just there for demo purposes. I then simply use the rehydrated library to sign it, and set the variable to the value of the signed JWT.





A PEM, as you refer to it, is a container format specifying a combination of public and/or private key. You're using it to sign using HMAC-SHA256, which operates on a shared secret. This obviously isn't going to work (unless you take the poor man's approach and use your public key as the shared secret).



Fortunately enough, there are other signature methods defined in the RFCs. For instance, there is a way to sign using RSA, and a very convenient way of defining a public key as a JSON web key (JWK). We're going to be leveraging both.



I've generated a key pair for testing, they're named out and out.pub. Generation tool is genrsa (and as such, they're an RSA keypair).



In order to sign, we're going to have to change a few things:




  • We're changing algorithms from HS256 to RS256, as explained above

  • We're going to need a new library to do the signing itself, as crypto-js does not support asymmetric key crypto. We'll fall back to the native crypto module, though there are pure-JS alternatives


The code:



var CryptoJS = require("crypto-js");
var keyFileContent = require("fs").readFileSync("./out");
var pubkey = require("fs").readFileSync("./out.pub");
var base64url = require("base64url");
var nJwt = require("njwt");
function addIAT(request) {
var iat = Math.floor(Date.now() / 1000) + 257;
data.iat = iat;
return data;
}


var header = {
"typ": "JWT",
"alg": "RS256"
};

var data = {
"fname": "name",
"lname": "name",
"email": "email@domain.com",
"password": "abc123$"
};

data = addIAT(data);

// encode header
var stringifiedHeader = JSON.stringify(header);
var encodedHeader = base64url(stringifiedHeader);

// encode data
var stringifiedData = JSON.stringify(data);
var encodedData = base64url(stringifiedData);

// build token
var token = encodedHeader + "." + encodedData;

// sign token
var signatureAlg = require("crypto").createSign("sha256");
signatureAlg.update(token);
var signature = signatureAlg.sign(keyFileContent);
signature = base64url(signature);
var signedToken = token + "." + signature;

console.log(signedToken);

// Verify
var verifier = new nJwt.Verifier();
verifier.setSigningAlgorithm('RS256');
verifier.setSigningKey(pubkey);
verifier.verify(signedToken, function() {
console.log(arguments);
});


And that's it! It's quite literally that simple, although I would not recommend rewriting the sign() function from crypto from scratch. Leave it to a library that has had thorough inspection by the community, and crypto is pretty serious business.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 7 at 18:45

























answered Dec 29 '18 at 0:37









Sébastien RenauldSébastien Renauld

12.9k2742




12.9k2742













  • I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

    – Aleksandar
    Dec 30 '18 at 10:55











  • Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

    – janniks
    Jan 3 at 19:32













  • That's going to be really fun then, as cryptojs doesn't support RSA.

    – Sébastien Renauld
    Jan 4 at 2:38











  • In other words without creating a custom javascript code for running this, there is no way?

    – Aleksandar
    Jan 7 at 17:44











  • @Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

    – Sébastien Renauld
    Jan 7 at 18:32



















  • I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

    – Aleksandar
    Dec 30 '18 at 10:55











  • Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

    – janniks
    Jan 3 at 19:32













  • That's going to be really fun then, as cryptojs doesn't support RSA.

    – Sébastien Renauld
    Jan 4 at 2:38











  • In other words without creating a custom javascript code for running this, there is no way?

    – Aleksandar
    Jan 7 at 17:44











  • @Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

    – Sébastien Renauld
    Jan 7 at 18:32

















I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

– Aleksandar
Dec 30 '18 at 10:55





I cant use that in Postman. Postman is refusing to load base64url and njwt modules, for some reason it loads crypto-js

– Aleksandar
Dec 30 '18 at 10:55













Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

– janniks
Jan 3 at 19:32







Postman's sandbox only allows some node modules learning.getpostman.com/docs/postman/scripts/… (crypto-js is the only crypto related module)

– janniks
Jan 3 at 19:32















That's going to be really fun then, as cryptojs doesn't support RSA.

– Sébastien Renauld
Jan 4 at 2:38





That's going to be really fun then, as cryptojs doesn't support RSA.

– Sébastien Renauld
Jan 4 at 2:38













In other words without creating a custom javascript code for running this, there is no way?

– Aleksandar
Jan 7 at 17:44





In other words without creating a custom javascript code for running this, there is no way?

– Aleksandar
Jan 7 at 17:44













@Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

– Sébastien Renauld
Jan 7 at 18:32





@Aleksandar There might be a way. I'm testing something which is slightly hackish but will work for you, I think.

– Sébastien Renauld
Jan 7 at 18:32


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965446%2fhow-to-sign-a-jwt-with-a-private-key-pem-in-cryptojs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas