I'm trying to get the "modulus" from public key and certificate to validate that these pair key and cert match before sign but I can't
I have a web app building in Angular and I use https://www.npmjs.com/package/node-forge.This is a snnipet but I don't know how to achive getting mudulus.
var buffer = forge.util.createBuffer(FirmaUtil.Key, 'raw');
var asn1 = forge.asn1.fromDer(buffer);
var info = forge.pki.decryptPrivateKeyInfo(asn1, 'password');
var privateK = forge.pki.privateKeyFromAsn1(info);
At the end i could achieve the goal compare the modulus from cer and key
doesCertMatchKey: function privateKeyMatchesCertificate(model) {
certificate = {};
certificate.Cer = model.Cert; //AsArrayBuffer .cer file
certificate.Key = model.Key; //AsArrayBuffer .key file
certificate.Pass = model.Pass
let bufferCer = forge.util.createBuffer(certificate.Cer, 'raw');
let asn1Cert = forge.asn1.fromDer(bufferCer);
let cer = forge.pki.certificateFromAsn1(asn1Cert);
let nHexPublicK = cer.publicKey.n.toString(16);
let eHexPublicK = cer.publicKey.e.toString(16);
var bufferKey = forge.util.createBuffer(certificate.Key, 'raw');
var asn1Key = forge.asn1.fromDer(bufferKey);
//Before the next step check password to void exception.
var info = forge.pki.decryptPrivateKeyInfo(asn1Key, certificate.Pass);
var privateKey = forge.pki.privateKeyFromAsn1(info);
var nHexPrivateK = privateKey.n.toString(16);
var eHexPrivaetK = privateKey.e.toString(16);
//If they are identical then the private key matches the certificate.
return nHexPublicK === nHexPrivateK;
}
Related
I am very new to Javascript but I will try to put this in convenient way. I am having this api where I am fetching the rank of a crypto (Ripple; currently ranked 7 and is subject to change overtime ), code below:
function myFunction() {
var url = "https://api.coinpaprika.com/v1/coins/xrp-xrp";
var XRPresponse = UrlFetchApp.fetch(url);
var XRPjson = XRPresponse.getContentText();
var XRPdata = JSON.parse(XRPjson);
var XRPrank = XRPdata.rank;
}
Now this is another function for an api where I extract other infos (having 5000+ crytos listed, including ripple)
function myXRP() {
var url = "https://api.coinpaprika.com/v1/tickers";
var response = UrlFetchApp.fetch(url);
var json = response.getContentText();
var data = JSON.parse(json);
var XRP = data[7].symbol;
// Here instead of [7], I need to put the value extracted from XRPrank above so that whenever the rank is changed I get the latest value on data.[].
If someone could please advise.
In JavaScript there are several ways to achieve what you are looking for. The following is an adaptation of your current code with what I think are the minimal changes that you have to do, 1. use return followed by XRPrank 2. Call myFunction from myXRP and replace the data index by XRPrank.
function myFunction() {
var url = "https://api.coinpaprika.com/v1/coins/xrp-xrp";
var XRPresponse = UrlFetchApp.fetch(url);
var XRPjson = XRPresponse.getContentText();
var XRPdata = JSON.parse(XRPjson);
var XRPrank = XRPdata.rank;
return XRPrank; // add this
}
function myXRP() {
var url = "https://api.coinpaprika.com/v1/tickers";
var response = UrlFetchApp.fetch(url);
var json = response.getContentText();
var data = JSON.parse(json);
var XRPrank = myFunction(); // add this
// var XRP = data[7].symbol; instead of this
var XRP = data[XRPrank].symbol; // use this
}
Resources
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
function SendMail(to,body,sub)
{
var theApp ;
var theMailItem ;
var subject = sub;
var msg = body;
var theApp = new ActiveXObject("Outlook.Application")
var theMailItem = theApp.CreateItem(0);
theMailItem.to = to;
theMailItem.Subject = (subject);
theMailItem.Body = (msg);
theMailItem.send();
}
I'm using above code to send mails from the client machine, but in this i would like to add cc could anyone kindly help me on this or if there is any other methods to send mails from client side help is appreciated. Thanks in advance
The mail item has a CC property. Just set it before send.
theMailItem.CC = "carbon copy recipient goes here";
Also, have in mind that the property names are case sensitive. So change to to To and send to Send
var theApp = new ActiveXObject("Outlook.Application");
var objNS = theApp.GetNameSpace('MAPI');
var theMailItem = theApp.CreateItem(0);
theMailItem.cc = cc;
theMailItem.to = to;
theMailItem.Subject = (subject);
theMailItem.Body = (msg);
theMailItem.send();
I have added this line, var objNS = theApp.GetNameSpace('MAPI'); You should now be able to find the cc attribute.
Hi I've adapted the HTML certificate parser code to use nodejs from here:
https://github.com/GlobalSign/PKI.js/blob/master/examples/certificate-decode-example.html
However, I keep getting Error: Object's schema was not verified against input data for CERT
Obviously, theres a schema verification issue thats seems to be specific to node JS.
Am I missing something here ?
var merge = require("node.extend");
var common = require("asn1js/org/pkijs/common");
var _asn1js = require("asn1js");
var _pkijs = require("pkijs");
var _x509schema = require("pkijs/org/pkijs/x509_schema");
// #region Merging function/object declarations for ASN1js and PKIjs
var asn1js = merge(true, _asn1js, common);
var x509schema = merge(true, _x509schema, asn1js);
var pkijs_1 = merge(true, _pkijs, asn1js);
var pkijs = merge(true, pkijs_1, x509schema);
certb = `
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
`;
var asn1 = pkijs.org.pkijs.fromBER(certb);
var cert_simpl = new pkijs.org.pkijs.simpl.CERT({ schema: asn1.result });
I'm trying to sign data using the WebCrypto API, but instead of creating a private/public key and exporting it to pkcs#1 or 8, I would really like to use a user's PKCS#12 to sign data. I've read the W3C spec, but cannot make much of it and can't find any good material on how to do this. Right now I want to leave ActiveX and Java Applets aside. Is there a way to tweak the following:
var buffer = encode(prompt("Please enter your password"));
//TODO:
//implement a prompt for a pfx or cert
return crypto.subtle.importKey("raw", buffer, "PBKDF2", false, usages);
//TODO:
//instead of importing it, ask for the certificate's pass to sign data
//with crypto.subtle.sign
Any pointers?
UPDATE
Here's the code I've been working
<script src="forge.min.js"></script>
<script>
var errorsReportedByVerifier;
errorsReportedByVerifier = checkStorage() && checkBrowserAPIs();
if (!errorsReportedByVerifier){
console.log("adding click event");
document.getElementById('btnPfx').addEventListener('click', handlePFXFile, false);
storeVariables();
getVariables();
}
function handlePFXFile(evnt) {
console.log("handling pfx")
//alert(document.getElementById('pfx').value);
//error happens in 1st line
//error object does not accept property replace
//forge.min.js Line 1, Column: 17823
var p12Der = forge.util.decode64(document.getElementById('pfx').valueOf());
//var pkcs12Asn1 = forge.asn1.fromDer(p12Der);
//var pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, 'pss');
console.log("pkcs12");
}
</script>
Web cryptography api does not support PKCS # 12. You can use a third party library to decode the p12 as forge https://github.com/digitalbazaar/forge#pkcs12 and load privateKey in webcrypto
Reading the PKCS#12 certificate
PKCS#12 is stored in DER, so first read it from a File or use a pre-stored base64
//Reading certificate from a 'file' form field
var reader = new FileReader();
reader.onload = function(e) {
var contents = e.target.result;
var pkcs12Der = arrayBufferToString(contents)
var pkcs12B64 = forge.util.encode64(pkcs12Der);
//do something else...
}
reader.readAsArrayBuffer(file);
function arrayBufferToString( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return binary;
}
//p12 certificate stored in Base64 format
var pkcs12Der= forge.util.decode64(pkcs12B64);
Decode PKCS#12 with forge and extract private key
Then decode DER format to ASN1, and let forge reads the content
var pkcs12Asn1 = forge.asn1.fromDer(pkcs12Der);
var pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, password);
Then get the private key from pkcs12 of the desired certificate (see forge doc) and convert to PKCS # 8 to be imported with webcrypto
// load keypair and cert chain from safe content(s)
for(var sci = 0; sci < pkcs12.safeContents.length; ++sci) {
var safeContents = pkcs12.safeContents[sci];
for(var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) {
var safeBag = safeContents.safeBags[sbi];
// this bag has a private key
if(safeBag.type === forge.pki.oids.keyBag) {
//Found plain private key
privateKey = safeBag.key;
} else if(safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
// found encrypted private key
privateKey = safeBag.key;
} else if(safeBag.type === forge.pki.oids.certBag) {
// this bag has a certificate...
}
}
}
Convert to PKCS#8
function _privateKeyToPkcs8(privateKey) {
var rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKey);
var privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
var privateKeyInfoDer = forge.asn1.toDer(privateKeyInfo).getBytes();
var privateKeyInfoDerBuff = stringToArrayBuffer(privateKeyInfoDer);
return privateKeyInfoDerBuff;
}
function stringToArrayBuffer(data){
var arrBuff = new ArrayBuffer(data.length);
var writer = new Uint8Array(arrBuff);
for (var i = 0, len = data.length; i < len; i++) {
writer[i] = data.charCodeAt(i);
}
return arrBuff;
}
Import key in Webcrypto
And finally import the key in webcrypto
function _importCryptoKeyPkcs8(privateKey,extractable) {
var privateKeyInfoDerBuff = _privateKeyToPkcs8(privateKey);
//Import the webcrypto key
return crypto.subtle.importKey(
'pkcs8',
privateKeyInfoDerBuff,
{ name: "RSASSA-PKCS1-v1_5", hash:{name:"SHA-256"}},
extractable,
["sign"]);
}
_importCryptoKeyPkcs8(entry.privateKey,extractable).
then(function(cryptoKey) {
//your cryptokey is here!!!
});
Digital signature
With the imported cryptoKey returned from the above method you can sign with webcrypto.
var digestToSign = forge.util.decode64(digestToSignB64);
var digestToSignBuf = stringToArrayBuffer(digestToSign);
crypto.subtle.sign(
{name: "RSASSA-PKCS1-v1_5"},
cryptoKey,
digestToSignBuf)
.then(function(signature){
signatureB64 = forge.util.encode64(arrayBufferToString(signature))
});
I include coding from base64 because data conversions are not trivial
In pkc12 you also have the certification chain if you need to build advanced formats like AdES
I am attempting to verify a signature with a certificate. We have to download the required certificate from the CA, verify the certificate, then verify the signature. I have no idea, and I'm hoping someone can shed some light. Here's what I have / know so far.
To sign a message, I used the following code:
function sign(sk, m, certname) {
var key = new RSAKey();
key.setPrivate(sk.n, sk.e, sk.d);
var h = CryptoJS.SHA256(JSON.stringify(m)).toString(CryptoJS.enc.Hex);
h = new BigInteger(h, 16);
var sig = key.doPrivate(h).toString(16);
var obj = { "type": "SIGNED", "msg": m, "certname": certname, "sig": sig };
return JSON.stringify(obj);
}
To verify a signature, I used the following code:
function verify(pk, signed) {
var key = new RSAKey();
var s = JSON.stringify(signed.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(pk.n, pk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signed.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}
To verify a certificate, I used the following code: (EDIT: this is the new certificate verification function).
function verifyCertificate(signedCert, certname) {
var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}
And that's that. Can anyone please help. I don't know how to go about this.
EDIT: Okay, I think I have solved my own question (with assistance from the responses). This is the code that returns all positive results:
function verifyWithCert(sig) {
// 1. Download the required certificate from the CA
// 2. Verify the certificate
// 3. Verify the message
var certKey = new RSAKey();
var loadedCert = loadCert(sig.certname);
var certS = JSON.stringify(loadedCert.sig).toString(CryptoJS.enc.Hex);
certS = new BigInteger(certS, 16);
certKey.setPublic(CApk.n, CApk.e);
var certV = certKey.doPublic(certS).toString(16);
var certH = CryptoJS.SHA256(JSON.stringify(loadedCert.msg)).toString(CryptoJS.enc.Hex);
var verifyResult;
if (certV == certH) {
verifyResult = true;
}
var Sigkey = new RSAKey();
var s = JSON.stringify(sig.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
Sigkey.setPublic(loadedCert.msg.subject.pk.n, loadedCert.msg.subject.pk.e);
var v = Sigkey.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(sig.msg)).toString(CryptoJS.enc.Hex);
var verifySignature;
if (v == h) {
verifySignature = true;
}
var result = { "certificateFound": loadedCert ,"certificateVerified": verifyResult ,"signatureVerified": verifySignature };
return result;
}
(A note to other members of StackOverflow, I am also in this class so there's a bit of stuff that I mention that comes out of nowhere in regards to variables and other references.)
In the verifyCertificate function:
function verifyCertificate(signedCert, certname) {
var loadedCert = loadCert(certname);
// signedCert is the same as loadedCert above, the button runs the
// loadCert function and outputs the contents into the textarea,
// so the following will always be true.
var originalSig = JSON.stringify(signedCert.sig);
var loadedSig = JSON.stringify(loadedCert.sig);
log(loadedSig);
return (originalSig == loadedSig);
}
How am I supposed to verify the certificate then? What am I comparing the loaded CA certificate to? I thought maybe compare the public key in the certificate to the public key used to sign the message but... I don't know. I'm very confused.
You're on the right track with that though, think about the verify() function, and the details contained in the CApk variable at the top of the file. Can you hash the message from the loadCert() JSON response and match it against the output from:
function verify() {
//[...]
key.setPublic(pk.n, pk.e);
//[...]
}
Assuming you change a few variables?
It's similar to the method I used at least, so I'm hoping it's right. I figure if you can hash the message using the details in CApk, and compare it to a hash of the message contained in the JSON response, that verifies the certificate. Hopefully.
There is an error in 'verify certificate' approach.
you need to test the signature of certificate with public key of CA given in 355a3_main to verify, the code given here will only verify your certificate and will give s false positive for rest
i think this should work
var loadedCert = loadCert(certname);
var originalSig = JSON.stringify(signedCert.sig);
var loadedSig = JSON.stringify(loadedCert.sig);
log(loadedSig,originalSig);
var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);
if (originalSig == loadedSig && v==h)
return true;
else
return false;
That being said what about the long message of arbitrary length?
Except... you know how he says his solutions for the core tasks are between 5 and 10 lines? well this is about 20 lines of code, so i don't know if I should be suspicious of my code
I used the function verify and verifycertificate again in the RSA signature verification with certificate function. That will make your code fairly short. and I really appreciate this post, you're all my life savers.