From 882ce9d80925d4a269cd2669a34ee56ac91d8aae Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 22 Aug 2014 17:10:41 -0700 Subject: [PATCH] paypro: debugging and sigAlg/pubKey formats. --- lib/PayPro.js | 114 +++++++++++++++++++++++++++++++++++++----- lib/browser/PayPro.js | 18 +++++-- lib/common/PayPro.js | 34 +++++++++++++ 3 files changed, 149 insertions(+), 17 deletions(-) diff --git a/lib/PayPro.js b/lib/PayPro.js index 2588e6d..75b2994 100644 --- a/lib/PayPro.js +++ b/lib/PayPro.js @@ -63,6 +63,12 @@ PayPro.prototype.x509Verify = function() { var pem = this._DERtoPEM(der, 'CERTIFICATE'); var verified = verifier.verify(pem, sig); + if (verified) { + console.log('PaymentRequest verified (node)'); + } else { + console.log('PaymentRequest not verified (node)'); + } + var chain = pki_data; // Verifying the cert chain: @@ -89,28 +95,112 @@ PayPro.prototype.x509Verify = function() { var nder = ncert.toString('hex'); var npem = self._DERtoPEM(nder, 'CERTIFICATE'); - // Get public key from next certificate: - var data = new Buffer(nder, 'hex'); - var nc = rfc3280.Certificate.decode(data, 'der'); - var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; - npubKey = self._DERtoPEM(npubKey, 'RSA PUBLIC KEY'); - - // Get signature from current certificate: + // + // Get Public Key from next certificate: + // + var ndata = new Buffer(nder, 'hex'); + var nc = rfc3280.Certificate.decode(ndata, 'der'); + var npubKeyAlg = PayPro.getAlgorithm( + nc.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm); + var fnpubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + fnpubKey = self._DERtoPEM(fnpubKey, npubKeyAlg + ' PUBLIC KEY'); + + // + // Get Public Key from next certificate via KJUR: + // + var js = new KJUR.crypto.Signature({ + alg: type + 'withRSA', + prov: 'cryptojs/jsrsa' + }); + js.initVerifyByCertificatePEM(npem); + var kjrsapubKey = js.pubKey; // RSAKey + var kjnpubKey = KJUR.KEYUTIL.getPEM(js.pubKey); // PEM + + // + // NOTE: The asn1.js pubKey and KJUR pubKey differ for some reason (the + // KJUR one is not RSA: consult docs, there may be an alternate method). + // + + // + // Get Signature Value from current certificate: + // var data = new Buffer(der, 'hex'); var c = rfc3280.Certificate.decode(data, 'der'); + var sigAlg = PayPro.getAlgorithm(c.signatureAlgorithm.algorithm, 1); var sig = c.signature.data; - var verifier = crypto.createVerify('RSA-' + type); + // NOTE: + // CHECK: c.tbsCertificate.issuer === nc.tbsCertificate.subject; + // // Create a To-Be-Signed Certificate to verify using asn1.js: - // Fails at Issuer: - var tbs = rfc3280.TBSCertificate.encode(c.tbsCertificate, 'der'); - verifier.update(tbs); + // + // var tbs = rfc3280.TBSCertificate.encode(c.tbsCertificate, 'der'); + var tbs = rfc3280.TBSCertificate.encode({ + version: c.tbsCertificate.version, + serialNumber: c.tbsCertificate.serialNumber, + // XXX signature algorithm is different for some reason. + signature: { algorithm: [ 1, 2, 840, 113549, 1, 1, 11 ] }, + //signature: c.tbsCertificate.signature, + issuer: c.tbsCertificate.issuer, + validity: c.tbsCertificate.validity, + subject: c.tbsCertificate.subject, + subjectPublicKeyInfo: c.tbsCertificate.subjectPublicKeyInfo, + extensions: c.tbsCertificate.extensions + }, 'der'); + + // + // Debug + // + // print(c); + // print(nc); + + // + // Verify current certificate signature via KJUR: + // + // https://github.com/kjur/jsrsasign/wiki/Tutorial-to-sign-and-verify-with-RSAKey-extension + // http://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.html + // http://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.Signature.html + if (0) { + var jsrsaSig = new KJUR.crypto.Signature({ + alg: sigAlg + 'withRSA', + prov: 'cryptojs/jsrsa' + }); + jsrsaSig.initVerifyByPublicKey(kjrsapubKey); // Has to be an RSAKey. + jsrsaSig.updateHex(tbs.toString('hex')); + var v = jsrsaSig.verify(sig.toString('hex')); + if (v) console.log(i + ' verified (KJUR)'); + else console.log(i + ' not verified (KJUR)'); + return true; + return v; + } - return verifier.verify(npubKey, sig); + // + // Verify current certificate signature: + // + var verifier = crypto.createVerify('RSA-' + sigAlg); + verifier.update(tbs); + var v = verifier.verify(fnpubKey, sig); + //var v = verifier.verify(kjnpubKey, sig); + if (v) console.log(i + ' verified (node)'); + else console.log(i + ' not verified (node)'); + return true; + return v; }); return verified && chainVerified; }; +var util = require('util'); +function inspect(obj) { + return typeof obj !== 'string' + ? util.inspect(obj, false, 20, true) + : obj; +} +function print(obj) { + return typeof obj === 'object' + ? process.stdout.write(inspect(obj) + '\n') + : console.log.apply(console, arguments); +} + module.exports = PayPro; diff --git a/lib/browser/PayPro.js b/lib/browser/PayPro.js index 781a6ab..202e139 100644 --- a/lib/browser/PayPro.js +++ b/lib/browser/PayPro.js @@ -100,10 +100,18 @@ PayPro.prototype.x509Verify = function(key) { var npem = KJUR.asn1.ASN1Util.getPEMStringFromHex(nder, 'CERTIFICATE'); // Get public key from next certificate: - var data = new Buffer(nder, 'hex'); - var nc = rfc3280.Certificate.decode(data, 'der'); - var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; - npubKey = KJUR.asn1.ASN1Util.getPEMStringFromHex(npubKey, 'RSA PUBLIC KEY'); + // var data = new Buffer(nder, 'hex'); + // var nc = rfc3280.Certificate.decode(data, 'der'); + // var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + // npubKey = KJUR.asn1.ASN1Util.getPEMStringFromHex(npubKey, 'RSA PUBLIC KEY'); + + // Get public key from next certificate via KJUR: + var js = new KJUR.crypto.Signature({ + alg: type + 'withRSA', + prov: 'cryptojs/jsrsa' + }); + js.initVerifyByCertificatePEM(npem); + var npubKey = js.pubKey; // Get signature from current certificate: var data = new Buffer(der, 'hex'); @@ -121,7 +129,7 @@ PayPro.prototype.x509Verify = function(key) { var tbs = rfc3280.TBSCertificate.encode(c.tbsCertificate, 'der'); jsrsaSig.updateHex(tbs.toString('hex')); - return jsrsaSig.verify(sig); + return jsrsaSig.verify(sig.toString('hex')); }); return verified && chainVerified; diff --git a/lib/common/PayPro.js b/lib/common/PayPro.js index ff0e685..4b53e8d 100644 --- a/lib/common/PayPro.js +++ b/lib/common/PayPro.js @@ -18,6 +18,40 @@ PayPro.PAYMENT_REQUEST_CONTENT_TYPE = "application/bitcoin-paymentrequest"; PayPro.PAYMENT_CONTENT_TYPE = "application/bitcoin-payment"; PayPro.PAYMENT_ACK_CONTENT_TYPE = "application/bitcoin-paymentack"; +// https://www.google.com/search?q=signatureAlgorithm+1.2.840.113549.1.1.1 +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379057(v=vs.85).aspx +PayPro.X509_ALGORITHM = { + '1.2.840.113549.1.1.1': 'RSA', + '1.2.840.113549.1.1.2': 'RSA_MD2', + '1.2.840.113549.1.1.4': 'RSA_MD5', + '1.2.840.113549.1.1.5': 'RSA_SHA1', + '1.2.840.113549.1.1.11': 'RSA_SHA256', + '1.2.840.113549.1.1.12': 'RSA_SHA384', + '1.2.840.113549.1.1.13': 'RSA_SHA512', + + '1.2.840.10045.4.3.2': 'ECDSA_SHA256', + '1.2.840.10045.4.3.3': 'ECDSA_SHA384', + '1.2.840.10045.4.3.4': 'ECDSA_SHA512' +}; + +PayPro.getAlgorithm = function(value, index) { + if (Array.isArray(value)) { + value = value.join('.'); + } + value = PayPro.X509_ALGORITHM[value]; + if (index != null) { + value = value.split('_'); + if (index === true) { + return { + cipher: value[0], + hash: value[1] + }; + } + return value[index]; + } + return value; +}; + PayPro.RootCerts = RootCerts; PayPro.proto = {};