Payment Protocol: Added tests and misc formatting
This commit is contained in:
parent
f8d070c3d3
commit
bf5f770a67
|
@ -1,7 +1,6 @@
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
var KJUR = require('jsrsasign');
|
var KJUR = require('jsrsasign');
|
||||||
var assert = require('assert');
|
|
||||||
var PaymentProtocol = require('./common');
|
var PaymentProtocol = require('./common');
|
||||||
var RootCerts = require('./rootcerts');
|
var RootCerts = require('./rootcerts');
|
||||||
var rfc3280 = require('asn1.js/rfc/3280');
|
var rfc3280 = require('asn1.js/rfc/3280');
|
||||||
|
@ -15,15 +14,15 @@ PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
var pki_data = this.get('pki_data'); // contains one or more x509 certs
|
var pki_data = this.get('pki_data'); // contains one or more x509 certs
|
||||||
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
||||||
pki_data = pki_data.certificate;
|
pki_data = pki_data.certificate;
|
||||||
var type = pki_type !== 'none'
|
var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type;
|
||||||
? pki_type.split('+')[1].toUpperCase()
|
|
||||||
: pki_type;
|
|
||||||
var buf = this.serializeForSig();
|
var buf = this.serializeForSig();
|
||||||
|
|
||||||
var rsa = new KJUR.RSAKey();
|
var rsa = new KJUR.RSAKey();
|
||||||
rsa.readPrivateKeyFromPEMString(key.toString());
|
rsa.readPrivateKeyFromPEMString(key.toString());
|
||||||
key = rsa;
|
key = rsa;
|
||||||
|
|
||||||
|
var sig;
|
||||||
|
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
var jsrsaSig = new KJUR.crypto.Signature({
|
var jsrsaSig = new KJUR.crypto.Signature({
|
||||||
alg: type + 'withRSA',
|
alg: type + 'withRSA',
|
||||||
|
@ -34,9 +33,9 @@ PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
|
|
||||||
jsrsaSig.updateHex(buf.toString('hex'));
|
jsrsaSig.updateHex(buf.toString('hex'));
|
||||||
|
|
||||||
var sig = new Buffer(jsrsaSig.sign(), 'hex');
|
sig = new Buffer(jsrsaSig.sign(), 'hex');
|
||||||
} else {
|
} else {
|
||||||
var sig = '';
|
sig = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnTrust) {
|
if (returnTrust) {
|
||||||
|
@ -46,9 +45,7 @@ PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
var caName = RootCerts.getTrusted(pem);
|
var caName = RootCerts.getTrusted(pem);
|
||||||
var selfSigned = 0;
|
var selfSigned = 0;
|
||||||
if (!caName) {
|
if (!caName) {
|
||||||
selfSigned = pki_data.length > 1
|
selfSigned = pki_data.length > 1 ? -1 : 1;
|
||||||
? -1
|
|
||||||
: 1;
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
selfSigned: selfSigned,
|
selfSigned: selfSigned,
|
||||||
|
@ -69,9 +66,11 @@ PaymentProtocol.prototype.x509Verify = function(returnTrust) {
|
||||||
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
||||||
pki_data = pki_data.certificate;
|
pki_data = pki_data.certificate;
|
||||||
var buf = this.serializeForSig();
|
var buf = this.serializeForSig();
|
||||||
var type = pki_type !== 'none'
|
var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type;
|
||||||
? pki_type.split('+')[1].toUpperCase()
|
|
||||||
: pki_type;
|
var der;
|
||||||
|
var pem;
|
||||||
|
var verified;
|
||||||
|
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
var jsrsaSig = new KJUR.crypto.Signature({
|
var jsrsaSig = new KJUR.crypto.Signature({
|
||||||
|
@ -79,24 +78,21 @@ PaymentProtocol.prototype.x509Verify = function(returnTrust) {
|
||||||
prov: 'cryptojs/jsrsa'
|
prov: 'cryptojs/jsrsa'
|
||||||
});
|
});
|
||||||
var signedCert = pki_data[0];
|
var signedCert = pki_data[0];
|
||||||
var der = signedCert.toString('hex');
|
der = signedCert.toString('hex');
|
||||||
// var pem = self._DERtoPEM(der, 'CERTIFICATE');
|
pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
|
||||||
jsrsaSig.initVerifyByCertificatePEM(pem);
|
jsrsaSig.initVerifyByCertificatePEM(pem);
|
||||||
jsrsaSig.updateHex(buf.toString('hex'));
|
jsrsaSig.updateHex(buf.toString('hex'));
|
||||||
var verified = jsrsaSig.verify(sig.toString('hex'));
|
verified = jsrsaSig.verify(sig.toString('hex'));
|
||||||
} else {
|
} else {
|
||||||
var verified = true;
|
verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chain = pki_data;
|
var chain = pki_data;
|
||||||
|
|
||||||
//
|
|
||||||
// Get the CA cert's name
|
// Get the CA cert's name
|
||||||
//
|
|
||||||
var issuer = chain[chain.length - 1];
|
var issuer = chain[chain.length - 1];
|
||||||
der = issuer.toString('hex');
|
der = issuer.toString('hex');
|
||||||
// pem = this._DERtoPEM(der, 'CERTIFICATE');
|
|
||||||
pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||||
var caName = RootCerts.getTrusted(pem);
|
var caName = RootCerts.getTrusted(pem);
|
||||||
|
|
||||||
|
@ -152,7 +148,6 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
}
|
}
|
||||||
return chain.every(function(cert, i) {
|
return chain.every(function(cert, i) {
|
||||||
var der = cert.toString('hex');
|
var der = cert.toString('hex');
|
||||||
// var pem = self._DERtoPEM(der, 'CERTIFICATE');
|
|
||||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||||
var name = RootCerts.getTrusted(pem);
|
var name = RootCerts.getTrusted(pem);
|
||||||
|
|
||||||
|
@ -166,52 +161,37 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var nder = ncert.toString('hex');
|
var nder = ncert.toString('hex');
|
||||||
// var npem = self._DERtoPEM(nder, 'CERTIFICATE');
|
|
||||||
var npem = KJUR.asn1.ASN1Util.getPEMStringFromHex(nder, 'CERTIFICATE');
|
var npem = KJUR.asn1.ASN1Util.getPEMStringFromHex(nder, 'CERTIFICATE');
|
||||||
|
|
||||||
//
|
|
||||||
// Get Next Certificate:
|
// Get Next Certificate:
|
||||||
//
|
|
||||||
var ndata = new Buffer(nder, 'hex');
|
var ndata = new Buffer(nder, 'hex');
|
||||||
var nc = rfc3280.Certificate.decode(ndata, 'der');
|
var nc = rfc3280.Certificate.decode(ndata, 'der');
|
||||||
var npubKeyAlg = PaymentProtocol.getAlgorithm(
|
|
||||||
nc.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm);
|
|
||||||
|
|
||||||
//
|
var npubKey;
|
||||||
// Get Public Key from next certificate (via KJUR because it's a mess):
|
// Get Public Key from next certificate (via KJUR because it's a mess):
|
||||||
//
|
|
||||||
if (sigHashAlg !== 'none') {
|
if (sigHashAlg !== 'none') {
|
||||||
var js = new KJUR.crypto.Signature({
|
var js = new KJUR.crypto.Signature({
|
||||||
alg: sigHashAlg + 'withRSA',
|
alg: sigHashAlg + 'withRSA',
|
||||||
prov: 'cryptojs/jsrsa'
|
prov: 'cryptojs/jsrsa'
|
||||||
});
|
});
|
||||||
js.initVerifyByCertificatePEM(npem);
|
js.initVerifyByCertificatePEM(npem);
|
||||||
var npubKey = js.pubKey;
|
npubKey = js.pubKey;
|
||||||
}
|
}
|
||||||
// XXX Somehow change the pubKey format to npubKeyAlg.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get Signature Value from current certificate:
|
// Get Signature Value from current certificate:
|
||||||
//
|
|
||||||
var data = new Buffer(der, 'hex');
|
var data = new Buffer(der, 'hex');
|
||||||
var c = rfc3280.Certificate.decode(data, 'der');
|
var c = rfc3280.Certificate.decode(data, 'der');
|
||||||
var sigAlg = PaymentProtocol.getAlgorithm(c.signatureAlgorithm.algorithm, 1);
|
|
||||||
var sig = c.signature.data;
|
var sig = c.signature.data;
|
||||||
|
|
||||||
//
|
|
||||||
// Check Validity of Certificates
|
// Check Validity of Certificates
|
||||||
//
|
|
||||||
var validityVerified = PaymentProtocol.validateCertTime(c, nc);
|
var validityVerified = PaymentProtocol.validateCertTime(c, nc);
|
||||||
|
|
||||||
//
|
|
||||||
// Check the Issuer matches the Subject of the next certificate:
|
// Check the Issuer matches the Subject of the next certificate:
|
||||||
//
|
|
||||||
var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc);
|
var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc);
|
||||||
|
|
||||||
//
|
var sigVerified;
|
||||||
// Verify current Certificate signature
|
|
||||||
//
|
|
||||||
|
|
||||||
|
// Verify current Certificate signature
|
||||||
if (sigHashAlg !== 'none') {
|
if (sigHashAlg !== 'none') {
|
||||||
var jsrsaSig = new KJUR.crypto.Signature({
|
var jsrsaSig = new KJUR.crypto.Signature({
|
||||||
alg: sigHashAlg + 'withRSA',
|
alg: sigHashAlg + 'withRSA',
|
||||||
|
@ -225,14 +205,12 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
|
|
||||||
jsrsaSig.updateHex(tbs.toString('hex'));
|
jsrsaSig.updateHex(tbs.toString('hex'));
|
||||||
|
|
||||||
var sigVerified = jsrsaSig.verify(sig.toString('hex'));
|
sigVerified = jsrsaSig.verify(sig.toString('hex'));
|
||||||
} else {
|
} else {
|
||||||
var sigVerified = true;
|
sigVerified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return validityVerified
|
return validityVerified && issuerVerified && sigVerified;
|
||||||
&& issuerVerified
|
|
||||||
&& sigVerified;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ function PaymentProtocol() {
|
||||||
PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE = 50000;
|
PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE = 50000;
|
||||||
PaymentProtocol.PAYMENT_MAX_SIZE = 50000;
|
PaymentProtocol.PAYMENT_MAX_SIZE = 50000;
|
||||||
PaymentProtocol.PAYMENT_ACK_MAX_SIZE = 60000;
|
PaymentProtocol.PAYMENT_ACK_MAX_SIZE = 60000;
|
||||||
PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE = "application/bitcoin-paymentrequest";
|
PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE = 'application/bitcoin-paymentrequest';
|
||||||
PaymentProtocol.PAYMENT_CONTENT_TYPE = "application/bitcoin-payment";
|
PaymentProtocol.PAYMENT_CONTENT_TYPE = 'application/bitcoin-payment';
|
||||||
PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE = "application/bitcoin-paymentack";
|
PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE = 'application/bitcoin-paymentack';
|
||||||
|
|
||||||
// https://www.google.com/search?q=signatureAlgorithm+1.2.840.113549.1.1.1
|
// 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
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379057(v=vs.85).aspx
|
||||||
|
@ -43,7 +43,7 @@ PaymentProtocol.getAlgorithm = function(value, index) {
|
||||||
value = value.join('.');
|
value = value.join('.');
|
||||||
}
|
}
|
||||||
value = PaymentProtocol.X509_ALGORITHM[value];
|
value = PaymentProtocol.X509_ALGORITHM[value];
|
||||||
if (index != null) {
|
if (typeof(index) !== 'undefined') {
|
||||||
value = value.split('_');
|
value = value.split('_');
|
||||||
if (index === true) {
|
if (index === true) {
|
||||||
return {
|
return {
|
||||||
|
@ -66,7 +66,7 @@ PaymentProtocol.getTBSCertificate = function(data) {
|
||||||
// [ 48, 130, 5, 32, 48, 130, 4, 8, 160, 3 ]
|
// [ 48, 130, 5, 32, 48, 130, 4, 8, 160, 3 ]
|
||||||
var start = 0;
|
var start = 0;
|
||||||
var starts = 0;
|
var starts = 0;
|
||||||
for (var start = 0; start < data.length; start++) {
|
for (start = 0; start < data.length; start++) {
|
||||||
if (starts === 1 && data[start] === 48) {
|
if (starts === 1 && data[start] === 48) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ PaymentProtocol.getTBSCertificate = function(data) {
|
||||||
// SEQ of the TBSCertificate.
|
// SEQ of the TBSCertificate.
|
||||||
var end = 0;
|
var end = 0;
|
||||||
var ends = 0;
|
var ends = 0;
|
||||||
for (var end = data.length - 1; end > 0; end--) {
|
for (end = data.length - 1; end > 0; end--) {
|
||||||
if (ends === 2 && data[end] === 48) {
|
if (ends === 2 && data[end] === 48) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,7 @@ PaymentProtocol.validateCertIssuer = function(c, nc) {
|
||||||
var issuerObjectValue = issuerObject.value.toString('hex');
|
var issuerObjectValue = issuerObject.value.toString('hex');
|
||||||
var subjectObjectValue = subjectObject.value.toString('hex');
|
var subjectObjectValue = subjectObject.value.toString('hex');
|
||||||
|
|
||||||
return issuerObjectType === subjectObjectType
|
return issuerObjectType === subjectObjectType && issuerObjectValue === subjectObjectValue;
|
||||||
&& issuerObjectValue === subjectObjectValue;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return issuerVerified;
|
return issuerVerified;
|
||||||
|
@ -137,12 +136,12 @@ PaymentProtocol.RootCerts = RootCerts;
|
||||||
|
|
||||||
PaymentProtocol.proto = {};
|
PaymentProtocol.proto = {};
|
||||||
|
|
||||||
PaymentProtocol.proto.Output = "message Output {\
|
PaymentProtocol.proto.Output = 'message Output {\
|
||||||
optional uint64 amount = 1 [default = 0];\
|
optional uint64 amount = 1 [default = 0];\
|
||||||
optional bytes script = 2;\
|
optional bytes script = 2;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.PaymentDetails = "message PaymentDetails {\
|
PaymentProtocol.proto.PaymentDetails = 'message PaymentDetails {\
|
||||||
optional string network = 1 [default = \"main\"];\
|
optional string network = 1 [default = \"main\"];\
|
||||||
repeated Output outputs = 2;\
|
repeated Output outputs = 2;\
|
||||||
required uint64 time = 3;\
|
required uint64 time = 3;\
|
||||||
|
@ -150,33 +149,33 @@ PaymentProtocol.proto.PaymentDetails = "message PaymentDetails {\
|
||||||
optional string memo = 5;\
|
optional string memo = 5;\
|
||||||
optional string payment_url = 6;\
|
optional string payment_url = 6;\
|
||||||
optional bytes merchant_data = 7;\
|
optional bytes merchant_data = 7;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.PaymentRequest = "message PaymentRequest {\
|
PaymentProtocol.proto.PaymentRequest = 'message PaymentRequest {\
|
||||||
optional uint32 payment_details_version = 1 [default = 1];\
|
optional uint32 payment_details_version = 1 [default = 1];\
|
||||||
optional string pki_type = 2 [default = \"none\"];\
|
optional string pki_type = 2 [default = \"none\"];\
|
||||||
optional bytes pki_data = 3;\
|
optional bytes pki_data = 3;\
|
||||||
required bytes serialized_payment_details = 4;\
|
required bytes serialized_payment_details = 4;\
|
||||||
optional bytes signature = 5;\
|
optional bytes signature = 5;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.Payment = "message Payment {\
|
PaymentProtocol.proto.Payment = 'message Payment {\
|
||||||
optional bytes merchant_data = 1;\
|
optional bytes merchant_data = 1;\
|
||||||
repeated bytes transactions = 2;\
|
repeated bytes transactions = 2;\
|
||||||
repeated Output refund_to = 3;\
|
repeated Output refund_to = 3;\
|
||||||
optional string memo = 4;\
|
optional string memo = 4;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.PaymentACK = "message PaymentACK {\
|
PaymentProtocol.proto.PaymentACK = 'message PaymentACK {\
|
||||||
required Payment payment = 1;\
|
required Payment payment = 1;\
|
||||||
optional string memo = 2;\
|
optional string memo = 2;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.X509Certificates = "message X509Certificates {\
|
PaymentProtocol.proto.X509Certificates = 'message X509Certificates {\
|
||||||
repeated bytes certificate = 1;\
|
repeated bytes certificate = 1;\
|
||||||
}\n";
|
}\n';
|
||||||
|
|
||||||
PaymentProtocol.proto.all = "";
|
PaymentProtocol.proto.all = '';
|
||||||
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.Output;
|
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.Output;
|
||||||
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentDetails;
|
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentDetails;
|
||||||
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentRequest;
|
PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentRequest;
|
||||||
|
@ -186,12 +185,12 @@ PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.X5
|
||||||
|
|
||||||
PaymentProtocol.builder = protobufjs.loadProto(PaymentProtocol.proto.all);
|
PaymentProtocol.builder = protobufjs.loadProto(PaymentProtocol.proto.all);
|
||||||
|
|
||||||
PaymentProtocol.Output = PaymentProtocol.builder.build("Output");
|
PaymentProtocol.Output = PaymentProtocol.builder.build('Output');
|
||||||
PaymentProtocol.PaymentDetails = PaymentProtocol.builder.build("PaymentDetails");
|
PaymentProtocol.PaymentDetails = PaymentProtocol.builder.build('PaymentDetails');
|
||||||
PaymentProtocol.PaymentRequest = PaymentProtocol.builder.build("PaymentRequest");
|
PaymentProtocol.PaymentRequest = PaymentProtocol.builder.build('PaymentRequest');
|
||||||
PaymentProtocol.Payment = PaymentProtocol.builder.build("Payment");
|
PaymentProtocol.Payment = PaymentProtocol.builder.build('Payment');
|
||||||
PaymentProtocol.PaymentACK = PaymentProtocol.builder.build("PaymentACK");
|
PaymentProtocol.PaymentACK = PaymentProtocol.builder.build('PaymentACK');
|
||||||
PaymentProtocol.X509Certificates = PaymentProtocol.builder.build("X509Certificates");
|
PaymentProtocol.X509Certificates = PaymentProtocol.builder.build('X509Certificates');
|
||||||
|
|
||||||
PaymentProtocol.prototype.makeOutput = function(obj) {
|
PaymentProtocol.prototype.makeOutput = function(obj) {
|
||||||
this.messageType = 'Output';
|
this.messageType = 'Output';
|
||||||
|
@ -237,24 +236,30 @@ PaymentProtocol.prototype.makeX509Certificates = function(obj) {
|
||||||
|
|
||||||
PaymentProtocol.prototype.isValidSize = function() {
|
PaymentProtocol.prototype.isValidSize = function() {
|
||||||
var s = this.serialize();
|
var s = this.serialize();
|
||||||
if (this.messageType == 'PaymentRequest')
|
if (this.messageType === 'PaymentRequest') {
|
||||||
return s.length < PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE;
|
return s.length < PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE;
|
||||||
if (this.messageType == 'Payment')
|
}
|
||||||
|
if (this.messageType === 'Payment') {
|
||||||
return s.length < PaymentProtocol.PAYMENT_MAX_SIZE;
|
return s.length < PaymentProtocol.PAYMENT_MAX_SIZE;
|
||||||
if (this.messageType == 'PaymentACK')
|
}
|
||||||
|
if (this.messageType === 'PaymentACK') {
|
||||||
return s.length < PaymentProtocol.PAYMENT_ACK_MAX_SIZE;
|
return s.length < PaymentProtocol.PAYMENT_ACK_MAX_SIZE;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
PaymentProtocol.prototype.getContentType = function() {
|
PaymentProtocol.prototype.getContentType = function() {
|
||||||
if (this.messageType == 'PaymentRequest')
|
if (this.messageType === 'PaymentRequest') {
|
||||||
return PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE;
|
return PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.messageType == 'Payment')
|
if (this.messageType === 'Payment') {
|
||||||
return PaymentProtocol.PAYMENT_CONTENT_TYPE;
|
return PaymentProtocol.PAYMENT_CONTENT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.messageType == 'PaymentACK')
|
if (this.messageType === 'PaymentACK') {
|
||||||
return PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE;
|
return PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error('No known content type for this message type');
|
throw new Error('No known content type for this message type');
|
||||||
};
|
};
|
||||||
|
@ -267,13 +272,15 @@ PaymentProtocol.prototype.set = function(key, val) {
|
||||||
PaymentProtocol.prototype.get = function(key) {
|
PaymentProtocol.prototype.get = function(key) {
|
||||||
var v = this.message.get(key);
|
var v = this.message.get(key);
|
||||||
|
|
||||||
if (v === null)
|
if (v === null) {
|
||||||
return v;
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
//protobuf supports longs, javascript naturally does not
|
//protobuf supports longs, javascript naturally does not
|
||||||
//convert longs (see long.js, e.g. require('long')) to Numbers
|
//convert longs (see long.js, e.g. require('long')) to Numbers
|
||||||
if (typeof v.low !== 'undefined' && typeof v.high !== 'undefined')
|
if (typeof v.low !== 'undefined' && typeof v.high !== 'undefined') {
|
||||||
return v.toInt();
|
return v.toInt();
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof v.toBuffer !== 'undefined') {
|
if (typeof v.toBuffer !== 'undefined') {
|
||||||
var maybebuf = v.toBuffer();
|
var maybebuf = v.toBuffer();
|
||||||
|
@ -294,8 +301,9 @@ PaymentProtocol.prototype.setObj = function(obj) {
|
||||||
};
|
};
|
||||||
|
|
||||||
PaymentProtocol.prototype.serializeForSig = function() {
|
PaymentProtocol.prototype.serializeForSig = function() {
|
||||||
if (this.messageType !== 'PaymentRequest')
|
if (this.messageType !== 'PaymentRequest') {
|
||||||
throw new Error('serializeForSig is only for PaymentRequest');
|
throw new Error('serializeForSig is only for PaymentRequest');
|
||||||
|
}
|
||||||
|
|
||||||
var save = this.message.get('signature');
|
var save = this.message.get('signature');
|
||||||
this.message.set('signature', new Buffer([]));
|
this.message.set('signature', new Buffer([]));
|
||||||
|
@ -314,22 +322,25 @@ PaymentProtocol.prototype.serialize = function() {
|
||||||
|
|
||||||
PaymentProtocol.prototype.deserialize = function(buf, messageType) {
|
PaymentProtocol.prototype.deserialize = function(buf, messageType) {
|
||||||
this.messageType = messageType || this.messageType;
|
this.messageType = messageType || this.messageType;
|
||||||
if (!this.messageType)
|
if (!this.messageType) {
|
||||||
throw new Error('Must specify messageType');
|
throw new Error('Must specify messageType');
|
||||||
|
}
|
||||||
this.message = PaymentProtocol[this.messageType].decode(buf);
|
this.message = PaymentProtocol[this.messageType].decode(buf);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
PaymentProtocol.prototype.sign = function(key, returnTrust) {
|
PaymentProtocol.prototype.sign = function(key, returnTrust) {
|
||||||
if (this.messageType !== 'PaymentRequest')
|
if (this.messageType !== 'PaymentRequest') {
|
||||||
throw new Error('Signing can only be performed on a PaymentRequest');
|
throw new Error('Signing can only be performed on a PaymentRequest');
|
||||||
|
}
|
||||||
|
|
||||||
var pki_type = this.get('pki_type');
|
var pki_type = this.get('pki_type');
|
||||||
|
|
||||||
|
var sig;
|
||||||
if (pki_type === 'SIN') {
|
if (pki_type === 'SIN') {
|
||||||
var sig = this.sinSign(key);
|
sig = this.sinSign(key);
|
||||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||||
var sig = this.x509Sign(key, returnTrust);
|
sig = this.x509Sign(key, returnTrust);
|
||||||
} else if (pki_type === 'none') {
|
} else if (pki_type === 'none') {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
|
@ -342,8 +353,9 @@ PaymentProtocol.prototype.sign = function(key, returnTrust) {
|
||||||
};
|
};
|
||||||
|
|
||||||
PaymentProtocol.prototype.verify = function(returnTrust) {
|
PaymentProtocol.prototype.verify = function(returnTrust) {
|
||||||
if (this.messageType !== 'PaymentRequest')
|
if (this.messageType !== 'PaymentRequest') {
|
||||||
throw new Error('Verifying can only be performed on a PaymentRequest');
|
throw new Error('Verifying can only be performed on a PaymentRequest');
|
||||||
|
}
|
||||||
|
|
||||||
var pki_type = this.get('pki_type');
|
var pki_type = this.get('pki_type');
|
||||||
|
|
||||||
|
@ -366,7 +378,7 @@ function magicHash(str) {
|
||||||
var buf = Buffer.concat([prefix1, magicBytes, prefix2, message]);
|
var buf = Buffer.concat([prefix1, magicBytes, prefix2, message]);
|
||||||
var hash = sha256sha256(buf);
|
var hash = sha256sha256(buf);
|
||||||
return hash;
|
return hash;
|
||||||
};
|
}
|
||||||
|
|
||||||
//default signing function for prototype.sign
|
//default signing function for prototype.sign
|
||||||
PaymentProtocol.prototype.sinSign = function(privateKey) {
|
PaymentProtocol.prototype.sinSign = function(privateKey) {
|
||||||
|
@ -413,7 +425,9 @@ PaymentProtocol.prototype._PEMtoDERParam = function(pem, param) {
|
||||||
var type = /-----BEGIN ([^-]+)-----/.exec(part)[1];
|
var type = /-----BEGIN ([^-]+)-----/.exec(part)[1];
|
||||||
part = part.replace(/-----BEGIN ([^-]+)-----/g, '');
|
part = part.replace(/-----BEGIN ([^-]+)-----/g, '');
|
||||||
part = part.replace(/\s+/g, '');
|
part = part.replace(/\s+/g, '');
|
||||||
if (!param || type !== param) return;
|
if (!param || type !== param) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return new Buffer(part, 'base64');
|
return new Buffer(part, 'base64');
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
};
|
};
|
||||||
|
@ -423,14 +437,14 @@ PaymentProtocol.prototype._DERtoPEM = function(der, type) {
|
||||||
if (typeof der === 'string') {
|
if (typeof der === 'string') {
|
||||||
der = new Buffer(der, 'hex');
|
der = new Buffer(der, 'hex');
|
||||||
}
|
}
|
||||||
var type = type || 'PRIVACY-ENHANCED MESSAGE';
|
type = type || 'PRIVACY-ENHANCED MESSAGE';
|
||||||
der = der.toString('base64');
|
der = der.toString('base64');
|
||||||
der = der.replace(/(.{64})/g, '$1\r\n');
|
der = der.replace(/(.{64})/g, '$1\r\n');
|
||||||
der = der.replace(/\r\n$/, '');
|
der = der.replace(/\r\n$/, '');
|
||||||
return ''
|
return '' +
|
||||||
+ '-----BEGIN ' + type + '-----\r\n'
|
'-----BEGIN ' + type + '-----\r\n' +
|
||||||
+ der
|
der +
|
||||||
+ '\r\n-----END ' + type + '-----\r\n';
|
'\r\n-----END ' + type + '-----\r\n';
|
||||||
};
|
};
|
||||||
|
|
||||||
// Expose RootCerts
|
// Expose RootCerts
|
||||||
|
|
|
@ -6,24 +6,20 @@ var PaymentProtocol = require('./common');
|
||||||
var rfc3280 = require('asn1.js/rfc/3280');
|
var rfc3280 = require('asn1.js/rfc/3280');
|
||||||
|
|
||||||
PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
var self = this;
|
|
||||||
var pki_type = this.get('pki_type');
|
var pki_type = this.get('pki_type');
|
||||||
var pki_data = this.get('pki_data');
|
var pki_data = this.get('pki_data');
|
||||||
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
||||||
pki_data = pki_data.certificate;
|
pki_data = pki_data.certificate;
|
||||||
var details = this.get('serialized_payment_details');
|
var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type;
|
||||||
var type = pki_type !== 'none'
|
|
||||||
? pki_type.split('+')[1].toUpperCase()
|
|
||||||
: pki_type;
|
|
||||||
|
|
||||||
|
var sig;
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
var signature = crypto.createSign('RSA-' + type);
|
var signature = crypto.createSign('RSA-' + type);
|
||||||
var buf = this.serializeForSig();
|
var buf = this.serializeForSig();
|
||||||
signature.update(buf);
|
signature.update(buf);
|
||||||
var sig = signature.sign(key);
|
sig = signature.sign(key);
|
||||||
} else {
|
} else {
|
||||||
var buf = this.serializeForSig();
|
sig = '';
|
||||||
var sig = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnTrust) {
|
if (returnTrust) {
|
||||||
|
@ -33,9 +29,7 @@ PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
var caName = RootCerts.getTrusted(pem);
|
var caName = RootCerts.getTrusted(pem);
|
||||||
var selfSigned = 0;
|
var selfSigned = 0;
|
||||||
if (!caName) {
|
if (!caName) {
|
||||||
selfSigned = pki_data.length > 1
|
selfSigned = pki_data.length > 1 ? -1 : 1;
|
||||||
? -1
|
|
||||||
: 1;
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
selfSigned: selfSigned,
|
selfSigned: selfSigned,
|
||||||
|
@ -50,34 +44,32 @@ PaymentProtocol.prototype.x509Sign = function(key, returnTrust) {
|
||||||
};
|
};
|
||||||
|
|
||||||
PaymentProtocol.prototype.x509Verify = function(returnTrust) {
|
PaymentProtocol.prototype.x509Verify = function(returnTrust) {
|
||||||
var self = this;
|
|
||||||
var pki_type = this.get('pki_type');
|
var pki_type = this.get('pki_type');
|
||||||
var sig = this.get('signature');
|
var sig = this.get('signature');
|
||||||
var pki_data = this.get('pki_data');
|
var pki_data = this.get('pki_data');
|
||||||
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
pki_data = PaymentProtocol.X509Certificates.decode(pki_data);
|
||||||
pki_data = pki_data.certificate;
|
pki_data = pki_data.certificate;
|
||||||
var details = this.get('serialized_payment_details');
|
|
||||||
var buf = this.serializeForSig();
|
var buf = this.serializeForSig();
|
||||||
var type = pki_type !== 'none'
|
var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type;
|
||||||
? pki_type.split('+')[1].toUpperCase()
|
|
||||||
: pki_type;
|
var verified;
|
||||||
|
var der;
|
||||||
|
var pem;
|
||||||
|
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
var verifier = crypto.createVerify('RSA-' + type);
|
var verifier = crypto.createVerify('RSA-' + type);
|
||||||
verifier.update(buf);
|
verifier.update(buf);
|
||||||
var signedCert = pki_data[0];
|
var signedCert = pki_data[0];
|
||||||
var der = signedCert.toString('hex');
|
der = signedCert.toString('hex');
|
||||||
var pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE');
|
pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE');
|
||||||
var verified = verifier.verify(pem, sig);
|
verified = verifier.verify(pem, sig);
|
||||||
} else {
|
} else {
|
||||||
var verified = true;
|
verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chain = pki_data;
|
var chain = pki_data;
|
||||||
|
|
||||||
//
|
|
||||||
// Get the CA cert's name
|
// Get the CA cert's name
|
||||||
//
|
|
||||||
var issuer = chain[chain.length - 1];
|
var issuer = chain[chain.length - 1];
|
||||||
der = issuer.toString('hex');
|
der = issuer.toString('hex');
|
||||||
pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE');
|
pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE');
|
||||||
|
@ -139,6 +131,7 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
var name = RootCerts.getTrusted(pem);
|
var name = RootCerts.getTrusted(pem);
|
||||||
|
|
||||||
var ncert = chain[i + 1];
|
var ncert = chain[i + 1];
|
||||||
|
|
||||||
// The root cert, check if it's trusted:
|
// The root cert, check if it's trusted:
|
||||||
if (!ncert || name) {
|
if (!ncert || name) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
|
@ -148,11 +141,8 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var nder = ncert.toString('hex');
|
var nder = ncert.toString('hex');
|
||||||
var npem = PaymentProtocol.DERtoPEM(nder, 'CERTIFICATE');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get Public Key from next certificate:
|
// Get Public Key from next certificate:
|
||||||
//
|
|
||||||
var ndata = new Buffer(nder, 'hex');
|
var ndata = new Buffer(nder, 'hex');
|
||||||
var nc = rfc3280.Certificate.decode(ndata, 'der');
|
var nc = rfc3280.Certificate.decode(ndata, 'der');
|
||||||
var npubKeyAlg = PaymentProtocol.getAlgorithm(
|
var npubKeyAlg = PaymentProtocol.getAlgorithm(
|
||||||
|
@ -160,28 +150,18 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
|
var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
|
||||||
npubKey = PaymentProtocol.DERtoPEM(npubKey, npubKeyAlg + ' PUBLIC KEY');
|
npubKey = PaymentProtocol.DERtoPEM(npubKey, npubKeyAlg + ' PUBLIC KEY');
|
||||||
|
|
||||||
//
|
|
||||||
// Get Signature Value from current certificate:
|
// Get Signature Value from current certificate:
|
||||||
//
|
|
||||||
var data = new Buffer(der, 'hex');
|
var data = new Buffer(der, 'hex');
|
||||||
var c = rfc3280.Certificate.decode(data, 'der');
|
var c = rfc3280.Certificate.decode(data, 'der');
|
||||||
var sigAlg = PaymentProtocol.getAlgorithm(c.signatureAlgorithm.algorithm, 1);
|
|
||||||
var sig = c.signature.data;
|
var sig = c.signature.data;
|
||||||
|
|
||||||
//
|
|
||||||
// Check Validity of Certificates
|
// Check Validity of Certificates
|
||||||
//
|
|
||||||
var validityVerified = PaymentProtocol.validateCertTime(c, nc);
|
var validityVerified = PaymentProtocol.validateCertTime(c, nc);
|
||||||
|
|
||||||
//
|
|
||||||
// Check the Issuer matches the Subject of the next certificate:
|
// Check the Issuer matches the Subject of the next certificate:
|
||||||
//
|
|
||||||
var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc);
|
var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc);
|
||||||
|
|
||||||
//
|
// Verify current Certificate signature:
|
||||||
// Verify current Certificate signature
|
|
||||||
//
|
|
||||||
|
|
||||||
// Get the raw DER TBSCertificate
|
// Get the raw DER TBSCertificate
|
||||||
// from the DER Certificate:
|
// from the DER Certificate:
|
||||||
var tbs = PaymentProtocol.getTBSCertificate(data);
|
var tbs = PaymentProtocol.getTBSCertificate(data);
|
||||||
|
@ -190,9 +170,7 @@ PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) {
|
||||||
verifier.update(tbs);
|
verifier.update(tbs);
|
||||||
var sigVerified = verifier.verify(npubKey, sig);
|
var sigVerified = verifier.verify(npubKey, sig);
|
||||||
|
|
||||||
return validityVerified
|
return validityVerified && issuerVerified && sigVerified;
|
||||||
&& issuerVerified
|
|
||||||
&& sigVerified;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
var RootCerts = exports;
|
var RootCerts = exports;
|
||||||
|
|
||||||
var certs = require('./rootcerts.json');
|
var certs = require('./rootcerts.json');
|
||||||
|
@ -14,13 +16,17 @@ var trusted = Object.keys(certs).reduce(function(trusted, key) {
|
||||||
|
|
||||||
RootCerts.getTrusted = function(pem) {
|
RootCerts.getTrusted = function(pem) {
|
||||||
pem = RootCerts.parsePEM(pem)[0].pem;
|
pem = RootCerts.parsePEM(pem)[0].pem;
|
||||||
if (!Object.prototype.hasOwnProperty.call(trusted, pem)) return;
|
if (!Object.prototype.hasOwnProperty.call(trusted, pem)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return trusted[pem];
|
return trusted[pem];
|
||||||
};
|
};
|
||||||
|
|
||||||
RootCerts.getCert = function(name) {
|
RootCerts.getCert = function(name) {
|
||||||
name = name.replace(/^s+|s+$/g, '');
|
name = name.replace(/^s+|s+$/g, '');
|
||||||
if (!Object.prototype.hasOwnProperty.call(certs, name)) return;
|
if (!Object.prototype.hasOwnProperty.call(certs, name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return certs[name];
|
return certs[name];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,9 +35,13 @@ RootCerts.parsePEM = function(pem) {
|
||||||
var concatted = pem.trim().split(/-----BEGIN [^\-\r\n]+-----/);
|
var concatted = pem.trim().split(/-----BEGIN [^\-\r\n]+-----/);
|
||||||
if (concatted.length > 2) {
|
if (concatted.length > 2) {
|
||||||
return concatted.reduce(function(out, pem) {
|
return concatted.reduce(function(out, pem) {
|
||||||
if (!pem) return out;
|
if (!pem) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
pem = RootCerts.parsePEM(pem)[0].pem;
|
pem = RootCerts.parsePEM(pem)[0].pem;
|
||||||
if (pem) out.push(pem);
|
if (pem) {
|
||||||
|
out.push(pem);
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
@ -51,9 +61,7 @@ RootCerts.parsePEM = function(pem) {
|
||||||
pem = parts.slice(1).join('');
|
pem = parts.slice(1).join('');
|
||||||
}
|
}
|
||||||
pem = pem.replace(/\s+/g, '');
|
pem = pem.replace(/\s+/g, '');
|
||||||
var der = pem
|
var der = pem ? new Buffer(pem, 'base64') : null;
|
||||||
? new Buffer(pem, 'base64')
|
|
||||||
: null;
|
|
||||||
return [{
|
return [{
|
||||||
type: type,
|
type: type,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
|
|
|
@ -297,6 +297,12 @@ describe('PaymentProtocol', function() {
|
||||||
output.get('amount').toInt().should.equal(20);
|
output.get('amount').toInt().should.equal(20);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to make output using "makeOutput"', function() {
|
||||||
|
var output = new PaymentProtocol().makeOutput();
|
||||||
|
output.message.set('amount', 20);
|
||||||
|
output.message.get('amount').toInt().should.equal(20);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#PaymentDetails', function() {
|
describe('#PaymentDetails', function() {
|
||||||
|
@ -380,6 +386,24 @@ describe('PaymentProtocol', function() {
|
||||||
pahex.length.should.be.greaterThan(0);
|
pahex.length.should.be.greaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('makePaymentACK', function() {
|
||||||
|
var payment = new PaymentProtocol.Payment();
|
||||||
|
var ack = new PaymentProtocol().makePaymentACK();
|
||||||
|
ack.set('payment', payment);
|
||||||
|
ack.set('memo', 'this is a memo');
|
||||||
|
ack.get('memo').should.equal('this is a memo');
|
||||||
|
var valid = ack.isValidSize();
|
||||||
|
valid.should.equal(true);
|
||||||
|
var contentType = ack.getContentType();
|
||||||
|
contentType.should.equal(PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE);
|
||||||
|
var serialized = ack.serialize();
|
||||||
|
serialized.length.should.be.greaterThan(0);
|
||||||
|
var ack2 = new PaymentProtocol().makePaymentACK();
|
||||||
|
ack2.deserialize(serialized, 'PaymentACK');
|
||||||
|
var serialized2 = ack2.serialize();
|
||||||
|
serialized.should.deep.equal(serialized2);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#X509Certificates', function() {
|
describe('#X509Certificates', function() {
|
||||||
|
@ -413,6 +437,14 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#getContentType', function() {
|
describe('#getContentType', function() {
|
||||||
|
|
||||||
|
it('should error without a known message type', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
paypro.messageType = 'unknown';
|
||||||
|
expect(function(){
|
||||||
|
paypro.getContentType();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
it('should get a content type for payment', function() {
|
it('should get a content type for payment', function() {
|
||||||
var paypro = new PaymentProtocol();
|
var paypro = new PaymentProtocol();
|
||||||
paypro.makePayment();
|
paypro.makePayment();
|
||||||
|
@ -463,6 +495,14 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#serializeForSig', function() {
|
describe('#serializeForSig', function() {
|
||||||
|
|
||||||
|
it('should error when not a payment request', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
paypro.messageType = 'unknown';
|
||||||
|
expect(function(){
|
||||||
|
paypro.serializeForSig();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
it('should serialize a PaymentRequest and not fail', function() {
|
it('should serialize a PaymentRequest and not fail', function() {
|
||||||
var pd = new PaymentProtocol.PaymentDetails();
|
var pd = new PaymentProtocol.PaymentDetails();
|
||||||
pd.set('time', 0);
|
pd.set('time', 0);
|
||||||
|
@ -472,6 +512,10 @@ describe('PaymentProtocol', function() {
|
||||||
paypro.makePaymentRequest();
|
paypro.makePaymentRequest();
|
||||||
paypro.set('serialized_payment_details', pdbuf);
|
paypro.set('serialized_payment_details', pdbuf);
|
||||||
var buf = paypro.serializeForSig();
|
var buf = paypro.serializeForSig();
|
||||||
|
var valid = paypro.isValidSize();
|
||||||
|
var contentType = paypro.getContentType();
|
||||||
|
contentType.should.equal(PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE);
|
||||||
|
valid.should.equal(true);
|
||||||
buf.length.should.be.greaterThan(0);
|
buf.length.should.be.greaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -494,6 +538,13 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#deserialize', function() {
|
describe('#deserialize', function() {
|
||||||
|
|
||||||
|
it('should error without a message type', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
expect(function(){
|
||||||
|
paypro.deserialize(new Buffer({size: 12}));
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
it('should deserialize a serialized message', function() {
|
it('should deserialize a serialized message', function() {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
var paypro = new PaymentProtocol();
|
var paypro = new PaymentProtocol();
|
||||||
|
@ -511,6 +562,29 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#sign', function() {
|
describe('#sign', function() {
|
||||||
|
|
||||||
|
it('should error when not a payment request', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
expect(function(){
|
||||||
|
paypro.sign();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not sign if the pki_type is "none"', function() {
|
||||||
|
var paypro = new PaymentProtocol().makePaymentRequest();
|
||||||
|
paypro.set('pki_type', 'none');
|
||||||
|
var a = paypro.sign();
|
||||||
|
var signature = a.get('signature');
|
||||||
|
should.not.exist(signature);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error if unkown pki_type', function() {
|
||||||
|
var paypro = new PaymentProtocol().makePaymentRequest();
|
||||||
|
paypro.set('pki_type', 'x508'); //typo
|
||||||
|
expect(function(){
|
||||||
|
paypro.sign();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
it('should sign a payment request', function() {
|
it('should sign a payment request', function() {
|
||||||
// SIN
|
// SIN
|
||||||
var pd = new PaymentProtocol.PaymentDetails();
|
var pd = new PaymentProtocol.PaymentDetails();
|
||||||
|
@ -549,6 +623,28 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#verify', function() {
|
describe('#verify', function() {
|
||||||
|
|
||||||
|
it('should error if not a payment request', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
expect(function(){
|
||||||
|
paypro.verify();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if pki_type is set to "none"', function() {
|
||||||
|
var paypro = new PaymentProtocol().makePaymentRequest();
|
||||||
|
paypro.set('pki_type', 'none');
|
||||||
|
var valid = paypro.verify();
|
||||||
|
valid.should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error if unsupported pki_type', function() {
|
||||||
|
var paypro = new PaymentProtocol().makePaymentRequest();
|
||||||
|
paypro.set('pki_type', 'x508'); // typo
|
||||||
|
expect(function(){
|
||||||
|
paypro.verify();
|
||||||
|
}).to.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
it('should verify a signed payment request', function() {
|
it('should verify a signed payment request', function() {
|
||||||
// SIN
|
// SIN
|
||||||
var pd = new PaymentProtocol.PaymentDetails();
|
var pd = new PaymentProtocol.PaymentDetails();
|
||||||
|
@ -595,6 +691,13 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
describe('#sinSign', function() {
|
describe('#sinSign', function() {
|
||||||
|
|
||||||
|
it('should error if not sent an instance of PrivateKey', function() {
|
||||||
|
var paypro = new PaymentProtocol();
|
||||||
|
expect(function(){
|
||||||
|
paypro.sinSign(Number(7)); // not a private key
|
||||||
|
}).to.throw(TypeError);
|
||||||
|
});
|
||||||
|
|
||||||
it('should sign assuming pki_type is SIN', function() {
|
it('should sign assuming pki_type is SIN', function() {
|
||||||
var pd = new PaymentProtocol.PaymentDetails();
|
var pd = new PaymentProtocol.PaymentDetails();
|
||||||
pd.set('time', 0);
|
pd.set('time', 0);
|
||||||
|
@ -648,6 +751,7 @@ describe('PaymentProtocol', function() {
|
||||||
paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs
|
paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs
|
||||||
|
|
||||||
var sig = paypro.x509Sign(x509.priv);
|
var sig = paypro.x509Sign(x509.priv);
|
||||||
|
|
||||||
paypro.set('signature', sig);
|
paypro.set('signature', sig);
|
||||||
|
|
||||||
x509.sig2 = paypro.get('signature');
|
x509.sig2 = paypro.get('signature');
|
||||||
|
@ -708,6 +812,13 @@ describe('PaymentProtocol', function() {
|
||||||
|
|
||||||
paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs
|
paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs
|
||||||
|
|
||||||
|
var sigTrust = paypro.x509Sign(x509.priv, true);
|
||||||
|
sigTrust.selfSigned.should.equal(1);
|
||||||
|
sigTrust.isChain.should.equal(false);
|
||||||
|
sigTrust.signature.length.should.be.greaterThan(0);
|
||||||
|
sigTrust.caTrusted.should.equal(false);
|
||||||
|
should.not.exist(sigTrust.caName);
|
||||||
|
|
||||||
var sig = paypro.x509Sign(x509.priv);
|
var sig = paypro.x509Sign(x509.priv);
|
||||||
paypro.set('signature', sig);
|
paypro.set('signature', sig);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue