Reputation: 851
I am using jsrsasign and I have an RSA public and private key that I generated earlier. I used the following code to generate a signature.
var key = new RSAKey();
key.readPrivateKeyFromPEMString($("#private")[0].value); // "private" is a textarea containing the PEM encoded private key.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
sig.initSign(key);
sig.updateString('message');
var sigValueHex = sig.sign();
This produced the expected hex signature. The documentation for jsrsasign provides the following code to verify signatures.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
sig.initVerifyByCertificatePEM("-----BEGIN CERTIFICATE-----(snip)");
sig.updateString('message');
var isValid = sig.verify(sigValueHex);
My problem is that I do not have a certificate to verify with. sig.sign()
only gives the signature, no certificate. There is also sig.initVerifyByPublicKey(RSAKey)
which seemed promising at first. However, RSAKey only has ways to get the private key, not public key.
So, my question is how can I get this certificate? And if I can't, how can I get an RSAKey object from my public key? And if I can't do that, is there a better way to do digital signatures with javascript?
I am using jsrsasign and jQuery. http://kjur.github.io/jsrsasign/
If there is no way to do this with the methods I am using, is there a better way? My main goal here is to be able to send a message to a server and be sure that the message wasn't tampered with and that it came from the correct place. SSL is not an option here. The message does not need to be encrypted, only protected.
Upvotes: 3
Views: 5141
Reputation: 114
You could generate an X.509 self-signed key/certificate pair by using openssl.
openssl req -newkey rsa:4096 -x509 -nodes -keyout key.pem -out certificate.pem
Then upload certificate.pem
to the server, and use key.pem
to sign messages on the client.
The message and signature can be verified on the server.
Here is the sample code of using jsrsasign:
const jsrsasign = require("jsrsasign");
const fs = require('fs');
// sign
let key = fs.readFileSync("./key.pem", "utf-8");
let sig = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(key);
sig.updateString("message");
const signature = sig.sign();
// verify
let certificate = fs.readFileSync("./certificate.pem", "utf-8");
let ver = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
ver.init(certificate);
ver.updateString("message");
ver.verify(signature); // return true
For your reference.
Upvotes: 2
Reputation: 2974
You can create the public key with KEYUTIL.getKey(param)
, where "param" can be a string with either your certificate or your public key.
Here are the docs for that method
Example:
var publicKey = KEYUTIL.getKey(publicKeyString);
var sig = new r.Signature({"alg": "SHA256withRSA", "prov": "cryptojs/jsrsa"});
sig.initVerifyByPublicKey(publicKey);
sig.updateString(message);
var isValid = sig.verify(signature);
Hope that helps.
Upvotes: 2