From 18c38ae67aa35a386c07593c9c6a3b04d5e13473 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 28 Aug 2014 18:58:58 -0700 Subject: [PATCH] paypro: add returnTrust to sign(). minor improvements. --- lib/PayPro.js | 50 ++++++++++++++++++++++++------------------- lib/browser/PayPro.js | 38 ++++++++++++++++++-------------- lib/common/PayPro.js | 7 ++++-- 3 files changed, 55 insertions(+), 40 deletions(-) diff --git a/lib/PayPro.js b/lib/PayPro.js index 4645485..eb0cd7a 100644 --- a/lib/PayPro.js +++ b/lib/PayPro.js @@ -9,35 +9,41 @@ var PayPro = require('./common/PayPro'); var asn1 = require('asn1.js'); var rfc3280 = require('asn1.js/rfc/3280'); -PayPro.prototype.x509Sign = function(key) { +PayPro.prototype.x509Sign = function(key, returnTrust) { var self = this; var crypto = require('crypto'); var pki_type = this.get('pki_type'); - var pki_data = this.get('pki_data'); // contains one or more x509 certs + var pki_data = this.get('pki_data'); pki_data = PayPro.X509Certificates.decode(pki_data); pki_data = pki_data.certificate; var details = this.get('serialized_payment_details'); var type = pki_type.split('+')[1].toUpperCase(); - var trusted = pki_data.map(function(cert) { - var der = cert.toString('hex'); - var pem = self._DERtoPEM(der, 'CERTIFICATE'); - return RootCerts.getTrusted(pem); - }); - - // XXX Figure out what to do here - if (!trusted.length) { - // throw new Error('Unstrusted certificate.'); - } else { - trusted.forEach(function(name) { - // console.log('Certificate: %s', name); - }); - } - var signature = crypto.createSign('RSA-' + type); var buf = this.serializeForSig(); signature.update(buf); var sig = signature.sign(key); + + if (returnTrust) { + var cert = pki_data[pki_data.length - 1]; + var der = cert.toString('hex'); + var pem = PayPro.DERtoPEM(der, 'CERTIFICATE'); + var caName = RootCerts.getTrusted(pem); + var selfSigned = 0; + if (!caName) { + selfSigned = pki_data.length > 1 + ? -1 + : 1; + } + return { + selfSigned: selfSigned, + isChain: pki_data.length > 1, + signature: sig, + caTrusted: !!caName, + caName: caName || null + }; + } + return sig; }; @@ -58,7 +64,7 @@ PayPro.prototype.x509Verify = function(returnTrust) { var signedCert = pki_data[0]; var der = signedCert.toString('hex'); - var pem = this._DERtoPEM(der, 'CERTIFICATE'); + var pem = PayPro.DERtoPEM(der, 'CERTIFICATE'); var verified = verifier.verify(pem, sig); var chain = pki_data; @@ -68,7 +74,7 @@ PayPro.prototype.x509Verify = function(returnTrust) { // var issuer = chain[chain.length - 1]; der = issuer.toString('hex'); - pem = this._DERtoPEM(der, 'CERTIFICATE'); + pem = PayPro.DERtoPEM(der, 'CERTIFICATE'); var caName = RootCerts.getTrusted(pem); if (chain.length === 1 && !caName) { @@ -103,7 +109,7 @@ PayPro.prototype.x509Verify = function(returnTrust) { var chainVerified = chain.every(function(cert, i) { var der = cert.toString('hex'); - var pem = self._DERtoPEM(der, 'CERTIFICATE'); + var pem = PayPro.DERtoPEM(der, 'CERTIFICATE'); var name = RootCerts.getTrusted(pem); var ncert = chain[i + 1]; @@ -116,7 +122,7 @@ PayPro.prototype.x509Verify = function(returnTrust) { return true; } var nder = ncert.toString('hex'); - var npem = self._DERtoPEM(nder, 'CERTIFICATE'); + var npem = PayPro.DERtoPEM(nder, 'CERTIFICATE'); // // Get Public Key from next certificate: @@ -126,7 +132,7 @@ PayPro.prototype.x509Verify = function(returnTrust) { var npubKeyAlg = PayPro.getAlgorithm( nc.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm); var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; - npubKey = self._DERtoPEM(npubKey, npubKeyAlg + ' PUBLIC KEY'); + npubKey = PayPro.DERtoPEM(npubKey, npubKeyAlg + ' PUBLIC KEY'); // // Get Signature Value from current certificate: diff --git a/lib/browser/PayPro.js b/lib/browser/PayPro.js index 2245109..ce0ffb9 100644 --- a/lib/browser/PayPro.js +++ b/lib/browser/PayPro.js @@ -13,7 +13,7 @@ var rfc3280 = require('asn1.js/rfc/3280'); // http://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.Signature.html#.sign // http://kjur.github.io/jsrsasign/api/symbols/RSAKey.html -PayPro.prototype.x509Sign = function(key) { +PayPro.prototype.x509Sign = function(key, returnTrust) { var pki_type = this.get('pki_type'); var pki_data = this.get('pki_data'); // contains one or more x509 certs pki_data = PayPro.X509Certificates.decode(pki_data); @@ -21,21 +21,6 @@ PayPro.prototype.x509Sign = function(key) { var type = pki_type.split('+')[1].toUpperCase(); var buf = this.serializeForSig(); - var trusted = pki_data.map(function(cert) { - var der = cert.toString('hex'); - var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - return RootCerts.getTrusted(pem); - }); - - // XXX Figure out what to do here - if (!trusted.length) { - // throw new Error('Unstrusted certificate.'); - } else { - trusted.forEach(function(name) { - // console.log('Certificate: %s', name); - }); - } - var rsa = new KJUR.RSAKey(); rsa.readPrivateKeyFromPEMString(key.toString()); key = rsa; @@ -50,6 +35,27 @@ PayPro.prototype.x509Sign = function(key) { jsrsaSig.updateHex(buf.toString('hex')); var sig = new Buffer(jsrsaSig.sign(), 'hex'); + + if (returnTrust) { + var cert = pki_data[pki_data.length - 1]; + var der = cert.toString('hex'); + var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); + var caName = RootCerts.getTrusted(pem); + var selfSigned = 0; + if (!caName) { + selfSigned = pki_data.length > 1 + ? -1 + : 1; + } + return { + selfSigned: selfSigned, + isChain: pki_data.length > 1, + signature: sig, + caTrusted: !!caName, + caName: caName || null + }; + } + return sig; }; diff --git a/lib/common/PayPro.js b/lib/common/PayPro.js index 9b151a4..2f62b84 100644 --- a/lib/common/PayPro.js +++ b/lib/common/PayPro.js @@ -316,7 +316,7 @@ PayPro.prototype.deserialize = function(buf, messageType) { return this; }; -PayPro.prototype.sign = function(key) { +PayPro.prototype.sign = function(key, returnTrust) { if (this.messageType !== 'PaymentRequest') throw new Error('Signing can only be performed on a PaymentRequest'); @@ -325,7 +325,7 @@ PayPro.prototype.sign = function(key) { if (pki_type === 'SIN') { var sig = this.sinSign(key); } else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') { - var sig = this.x509Sign(key); + var sig = this.x509Sign(key, returnTrust); } else if (pki_type === 'none') { return this; } else { @@ -371,10 +371,12 @@ PayPro.prototype.sinVerify = function() { // Helpers +PayPro.PEMtoDER = PayPro.prototype._PEMtoDER = function(pem) { return this._PEMtoDERParam(pem); }; +PayPro.PEMtoDERParam = PayPro.prototype._PEMtoDERParam = function(pem, param) { if (Buffer.isBuffer(pem)) { pem = pem.toString(); @@ -392,6 +394,7 @@ PayPro.prototype._PEMtoDERParam = function(pem, param) { }).filter(Boolean); }; +PayPro.DERtoPEM = PayPro.prototype._DERtoPEM = function(der, type) { if (typeof der === 'string') { der = new Buffer(der, 'hex');