paypro: split up paypro into node/browser/common.
This commit is contained in:
parent
5fd37cf923
commit
604ac04f47
255
lib/PayPro.js
255
lib/PayPro.js
|
@ -1,244 +1,10 @@
|
|||
'use strict';
|
||||
var protobufjs = protobufjs || require('protobufjs/dist/ProtoBuf');
|
||||
|
||||
var Message = Message || require('./Message');
|
||||
|
||||
var RootCerts = require('./common/RootCerts');
|
||||
|
||||
// BIP 70 - payment protocol
|
||||
function PayPro() {
|
||||
this.messageType = null;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
PayPro.PAYMENT_REQUEST_MAX_SIZE = 50000;
|
||||
PayPro.PAYMENT_MAX_SIZE = 50000;
|
||||
PayPro.PAYMENT_ACK_MAX_SIZE = 60000;
|
||||
PayPro.PAYMENT_REQUEST_CONTENT_TYPE = "application/bitcoin-paymentrequest";
|
||||
PayPro.PAYMENT_CONTENT_TYPE = "application/bitcoin-payment";
|
||||
PayPro.PAYMENT_ACK_CONTENT_TYPE = "application/bitcoin-paymentack";
|
||||
|
||||
PayPro.proto = {};
|
||||
|
||||
PayPro.proto.Output = "message Output {\
|
||||
optional uint64 amount = 1 [default = 0];\
|
||||
optional bytes script = 2;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentDetails = "message PaymentDetails {\
|
||||
optional string network = 1 [default = \"main\"];\
|
||||
repeated Output outputs = 2;\
|
||||
required uint64 time = 3;\
|
||||
optional uint64 expires = 4;\
|
||||
optional string memo = 5;\
|
||||
optional string payment_url = 6;\
|
||||
optional bytes merchant_data = 7;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentRequest = "message PaymentRequest {\
|
||||
optional uint32 payment_details_version = 1 [default = 1];\
|
||||
optional string pki_type = 2 [default = \"none\"];\
|
||||
optional bytes pki_data = 3;\
|
||||
required bytes serialized_payment_details = 4;\
|
||||
optional bytes signature = 5;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.Payment = "message Payment {\
|
||||
optional bytes merchant_data = 1;\
|
||||
repeated bytes transactions = 2;\
|
||||
repeated Output refund_to = 3;\
|
||||
optional string memo = 4;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentACK = "message PaymentACK {\
|
||||
required Payment payment = 1;\
|
||||
optional string memo = 2;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.X509Certificates = "message X509Certificates {\
|
||||
repeated bytes certificate = 1;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.all = "";
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Output;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentDetails;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentRequest;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Payment;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentACK;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.X509Certificates;
|
||||
|
||||
PayPro.builder = protobufjs.loadProto(PayPro.proto.all);
|
||||
|
||||
PayPro.Output = PayPro.builder.build("Output");
|
||||
PayPro.PaymentDetails = PayPro.builder.build("PaymentDetails");
|
||||
PayPro.PaymentRequest = PayPro.builder.build("PaymentRequest");
|
||||
PayPro.Payment = PayPro.builder.build("Payment");
|
||||
PayPro.PaymentACK = PayPro.builder.build("PaymentACK");
|
||||
PayPro.X509Certificates = PayPro.builder.build("X509Certificates");
|
||||
|
||||
PayPro.prototype.makeOutput = function(obj) {
|
||||
this.messageType = 'Output';
|
||||
this.message = new PayPro.Output();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentDetails = function(obj) {
|
||||
this.messageType = 'PaymentDetails';
|
||||
this.message = new PayPro.PaymentDetails();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentRequest = function(obj) {
|
||||
this.messageType = 'PaymentRequest';
|
||||
this.message = new PayPro.PaymentRequest();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePayment = function(obj) {
|
||||
this.messageType = 'Payment';
|
||||
this.message = new PayPro.Payment();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentACK = function(obj) {
|
||||
this.messageType = 'Payment';
|
||||
this.message = new PayPro.PaymentACK();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makeX509Certificates = function(obj) {
|
||||
this.messageType = 'X509Certificates';
|
||||
this.message = new PayPro.X509Certificates();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.isValidSize = function() {
|
||||
var s = this.serialize();
|
||||
if (this.messageType == 'PaymentRequest')
|
||||
return s.length < PayPro.PAYMENT_REQUEST_MAX_SIZE;
|
||||
if (this.messageType == 'Payment')
|
||||
return s.length < PayPro.PAYMENT_MAX_SIZE;
|
||||
if (this.messageType == 'PaymentACK')
|
||||
return s.length < PayPro.PAYMENT_ACK_MAX_SIZE;
|
||||
return true;
|
||||
};
|
||||
|
||||
PayPro.prototype.getContentType = function() {
|
||||
if (this.messageType == 'PaymentRequest')
|
||||
return PayPro.PAYMENT_REQUEST_CONTENT_TYPE;
|
||||
|
||||
if (this.messageType == 'Payment')
|
||||
return PayPro.PAYMENT_CONTENT_TYPE;
|
||||
|
||||
if (this.messageType == 'PaymentACK')
|
||||
return PayPro.PAYMENT_ACK_CONTENT_TYPE;
|
||||
|
||||
throw new Error('No known content type for this message type');
|
||||
};
|
||||
|
||||
PayPro.prototype.set = function(key, val) {
|
||||
this.message.set(key, val);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.get = function(key) {
|
||||
var v = this.message.get(key);
|
||||
|
||||
if (v === null)
|
||||
return v;
|
||||
|
||||
//protobuf supports longs, javascript naturally does not
|
||||
//convert longs (see long.js, e.g. require('long')) to Numbers
|
||||
if (typeof v.low !== 'undefined' && typeof v.high !== 'undefined')
|
||||
return v.toInt();
|
||||
|
||||
if (typeof v.toBuffer !== 'undefined') {
|
||||
var maybebuf = v.toBuffer();
|
||||
return Buffer.isBuffer(maybebuf) ? maybebuf : new Buffer(new Uint8Array(maybebuf));
|
||||
}
|
||||
|
||||
return v;
|
||||
};
|
||||
|
||||
PayPro.prototype.setObj = function(obj) {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
var val = obj[key];
|
||||
this.message.set(key, val);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.serializeForSig = function() {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('serializeForSig is only for PaymentRequest');
|
||||
|
||||
var save = this.message.get('signature');
|
||||
this.message.set('signature', new Buffer([]));
|
||||
var buf = this.serialize();
|
||||
this.message.set('signature', save);
|
||||
return buf;
|
||||
};
|
||||
|
||||
PayPro.prototype.serialize = function() {
|
||||
//protobufjs returns either a Buffer or an ArrayBuffer
|
||||
//but we always want a Buffer (which browserify understands, browser or no)
|
||||
var maybebuf = this.message.toBuffer();
|
||||
var buf = (Buffer.isBuffer(maybebuf)) ? maybebuf : new Buffer(new Uint8Array(maybebuf));
|
||||
return buf;
|
||||
};
|
||||
|
||||
PayPro.prototype.deserialize = function(buf, messageType) {
|
||||
this.messageType = messageType || this.messageType;
|
||||
if (!this.messageType)
|
||||
throw new Error('Must specify messageType');
|
||||
this.message = PayPro[this.messageType].decode(buf);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.sign = function(key) {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Signing can only be performed on a PaymentRequest');
|
||||
|
||||
var pki_type = this.get('pki_type');
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
var sig = this.sinSign(key);
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
var sig = this.x509Sign(key);
|
||||
} else if (pki_type === 'none') {
|
||||
return this;
|
||||
} else {
|
||||
throw new Error('Unsupported pki_type');
|
||||
}
|
||||
|
||||
this.set('signature', sig);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.verify = function() {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Verifying can only be performed on a PaymentRequest');
|
||||
|
||||
var pki_type = this.get('pki_type');
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
return this.sinVerify();
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
return this.x509Verify();
|
||||
} else if (pki_type === 'none') {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error('Unsupported pki_type');
|
||||
};
|
||||
var PayPro = require('./common/PayPro');
|
||||
|
||||
PayPro.prototype.x509Sign = function(key) {
|
||||
var self = this;
|
||||
|
@ -255,6 +21,7 @@ PayPro.prototype.x509Sign = function(key) {
|
|||
});
|
||||
|
||||
if (!trusted) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
|
@ -283,6 +50,7 @@ PayPro.prototype.x509Verify = function() {
|
|||
var pem = self._DERtoPEM(der, 'CERTIFICATE');
|
||||
|
||||
if (!RootCerts.isTrusted(pem)) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
|
@ -290,21 +58,6 @@ PayPro.prototype.x509Verify = function() {
|
|||
});
|
||||
};
|
||||
|
||||
//default signing function for prototype.sign
|
||||
PayPro.prototype.sinSign = function(key) {
|
||||
this.set('pki_data', key.public)
|
||||
var buf = this.serializeForSig();
|
||||
return Message.sign(buf, key);
|
||||
};
|
||||
|
||||
//default verify function
|
||||
PayPro.prototype.sinVerify = function() {
|
||||
var sig = this.get('signature');
|
||||
var pubkey = this.get('pki_data');
|
||||
var buf = this.serializeForSig();
|
||||
return Message.verifyWithPubKey(pubkey, buf, sig);
|
||||
};
|
||||
|
||||
// Helpers
|
||||
|
||||
PayPro.prototype._PEMtoDER = function(pem) {
|
||||
|
|
|
@ -3,93 +3,68 @@
|
|||
var Key = require('./Key');
|
||||
var KJUR = require('jsrsasign');
|
||||
var assert = require('assert');
|
||||
var PayPro = require('../PayPro');
|
||||
var PayPro = require('../common/PayPro');
|
||||
var RootCerts = require('../common/RootCerts');
|
||||
|
||||
PayPro.sign = function(key) {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Signing can only be performed on a PaymentRequest');
|
||||
|
||||
PayPro.prototype.x509Sign = function(key) {
|
||||
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 type = pki_type.split('+')[1].toUpperCase();
|
||||
var buf = this.serializeForSig();
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
var sig = this.sinSign(key);
|
||||
} else if (pki_type === 'x509+sha256' || pki_type === 'x509+sha1') {
|
||||
throw new Error('x509 currently unsuported.');
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
var crypto = require('crypto');
|
||||
var pki_data = this.get('pki_data'); // contains one or more x509 certs
|
||||
var type = pki_type.split('+')[1].toUpperCase();
|
||||
var buf = this.serializeForSig();
|
||||
var trusted = [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||
return RootCerts.isTrusted(pem);
|
||||
});
|
||||
|
||||
var trusted = [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||
return RootCerts.isTrusted(pem);
|
||||
});
|
||||
if (!trusted) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
if (!trusted) {
|
||||
var jsrsaSig = new KJUR.crypto.Signature({
|
||||
alg: type + 'withRSA',
|
||||
prov: 'cryptojs/jsrsa'
|
||||
});
|
||||
|
||||
jsrsaSig.initSign(key);
|
||||
|
||||
jsrsaSig.updateHex(buf.toString('hex'));
|
||||
|
||||
var sig = new Buffer(jsrsasig.sign(), 'hex');
|
||||
//var sig = new Buffer(new Uint8Array(jsrsasig.sign()), 'hex');
|
||||
return sig;
|
||||
};
|
||||
|
||||
PayPro.prototype.x509Verify = function(key) {
|
||||
var sig = this.get('signature');
|
||||
var pki_type = this.get('pki_type');
|
||||
var pki_data = this.get('pki_data');
|
||||
var buf = this.serializeForSig();
|
||||
var type = pki_type.split('+')[1].toUpperCase();
|
||||
|
||||
var jsrsaSig = new KJUR.crypto.Signature({
|
||||
alg: type + 'withRSA',
|
||||
prov: 'cryptojs/jsrsa'
|
||||
});
|
||||
|
||||
return [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||
|
||||
if (!RootCerts.isTrusted(pem)) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
var jsrsaSig = new KJUR.crypto.Signature({
|
||||
alg: type + 'withRSA',
|
||||
prov: 'cryptojs/jsrsa'
|
||||
});
|
||||
|
||||
jsrsaSig.initSign(key);
|
||||
jsrsaSig.initVerifyByCertificatePEM(pem);
|
||||
|
||||
jsrsaSig.updateHex(buf.toString('hex'));
|
||||
|
||||
var sig = new Buffer(jsrsasig.sign(), 'hex');
|
||||
} else if (pki_type === 'none') {
|
||||
return this;
|
||||
} else {
|
||||
throw new Error('Unsupported pki_type');
|
||||
}
|
||||
|
||||
this.set('signature', sig);
|
||||
return this;
|
||||
return jsrsaSig.verify(sig.toString('hex'));
|
||||
});
|
||||
};
|
||||
|
||||
PayPro.verify = function() {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Verifying can only be performed on a PaymentRequest');
|
||||
|
||||
var pki_type = this.get('pki_type');
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
return this.sinVerify();
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
var sig = this.get('signature');
|
||||
var pki_data = this.get('pki_data');
|
||||
var buf = this.serializeForSig();
|
||||
var type = pki_type.split('+')[1].toUpperCase();
|
||||
|
||||
var jsrsaSig = new KJUR.crypto.Signature({
|
||||
alg: type + 'withRSA',
|
||||
prov: 'cryptojs/jsrsa'
|
||||
});
|
||||
|
||||
return [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE');
|
||||
|
||||
if (!RootCerts.isTrusted(pem)) {
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
jsrsaSig.initVerifyByCertificatePEM(pem);
|
||||
|
||||
jsrsaSig.updateHex(buf.toString('hex'));
|
||||
|
||||
return jsrsaSig.verify(sig.toString('hex'));
|
||||
});
|
||||
} else if (pki_type === 'none') {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error('Unsupported pki_type');
|
||||
};
|
||||
|
||||
module.exports = Point;
|
||||
module.exports = PayPro;
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
'use strict';
|
||||
|
||||
var protobufjs = require('protobufjs/dist/ProtoBuf');
|
||||
var Message = require('../Message');
|
||||
|
||||
var RootCerts = require('../common/RootCerts');
|
||||
|
||||
// BIP 70 - payment protocol
|
||||
function PayPro() {
|
||||
this.messageType = null;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
PayPro.PAYMENT_REQUEST_MAX_SIZE = 50000;
|
||||
PayPro.PAYMENT_MAX_SIZE = 50000;
|
||||
PayPro.PAYMENT_ACK_MAX_SIZE = 60000;
|
||||
PayPro.PAYMENT_REQUEST_CONTENT_TYPE = "application/bitcoin-paymentrequest";
|
||||
PayPro.PAYMENT_CONTENT_TYPE = "application/bitcoin-payment";
|
||||
PayPro.PAYMENT_ACK_CONTENT_TYPE = "application/bitcoin-paymentack";
|
||||
|
||||
PayPro.proto = {};
|
||||
|
||||
PayPro.proto.Output = "message Output {\
|
||||
optional uint64 amount = 1 [default = 0];\
|
||||
optional bytes script = 2;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentDetails = "message PaymentDetails {\
|
||||
optional string network = 1 [default = \"main\"];\
|
||||
repeated Output outputs = 2;\
|
||||
required uint64 time = 3;\
|
||||
optional uint64 expires = 4;\
|
||||
optional string memo = 5;\
|
||||
optional string payment_url = 6;\
|
||||
optional bytes merchant_data = 7;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentRequest = "message PaymentRequest {\
|
||||
optional uint32 payment_details_version = 1 [default = 1];\
|
||||
optional string pki_type = 2 [default = \"none\"];\
|
||||
optional bytes pki_data = 3;\
|
||||
required bytes serialized_payment_details = 4;\
|
||||
optional bytes signature = 5;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.Payment = "message Payment {\
|
||||
optional bytes merchant_data = 1;\
|
||||
repeated bytes transactions = 2;\
|
||||
repeated Output refund_to = 3;\
|
||||
optional string memo = 4;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.PaymentACK = "message PaymentACK {\
|
||||
required Payment payment = 1;\
|
||||
optional string memo = 2;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.X509Certificates = "message X509Certificates {\
|
||||
repeated bytes certificate = 1;\
|
||||
}\n";
|
||||
|
||||
PayPro.proto.all = "";
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Output;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentDetails;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentRequest;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Payment;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentACK;
|
||||
PayPro.proto.all = PayPro.proto.all + PayPro.proto.X509Certificates;
|
||||
|
||||
PayPro.builder = protobufjs.loadProto(PayPro.proto.all);
|
||||
|
||||
PayPro.Output = PayPro.builder.build("Output");
|
||||
PayPro.PaymentDetails = PayPro.builder.build("PaymentDetails");
|
||||
PayPro.PaymentRequest = PayPro.builder.build("PaymentRequest");
|
||||
PayPro.Payment = PayPro.builder.build("Payment");
|
||||
PayPro.PaymentACK = PayPro.builder.build("PaymentACK");
|
||||
PayPro.X509Certificates = PayPro.builder.build("X509Certificates");
|
||||
|
||||
PayPro.prototype.makeOutput = function(obj) {
|
||||
this.messageType = 'Output';
|
||||
this.message = new PayPro.Output();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentDetails = function(obj) {
|
||||
this.messageType = 'PaymentDetails';
|
||||
this.message = new PayPro.PaymentDetails();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentRequest = function(obj) {
|
||||
this.messageType = 'PaymentRequest';
|
||||
this.message = new PayPro.PaymentRequest();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePayment = function(obj) {
|
||||
this.messageType = 'Payment';
|
||||
this.message = new PayPro.Payment();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makePaymentACK = function(obj) {
|
||||
this.messageType = 'Payment';
|
||||
this.message = new PayPro.PaymentACK();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.makeX509Certificates = function(obj) {
|
||||
this.messageType = 'X509Certificates';
|
||||
this.message = new PayPro.X509Certificates();
|
||||
this.setObj(obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.isValidSize = function() {
|
||||
var s = this.serialize();
|
||||
if (this.messageType == 'PaymentRequest')
|
||||
return s.length < PayPro.PAYMENT_REQUEST_MAX_SIZE;
|
||||
if (this.messageType == 'Payment')
|
||||
return s.length < PayPro.PAYMENT_MAX_SIZE;
|
||||
if (this.messageType == 'PaymentACK')
|
||||
return s.length < PayPro.PAYMENT_ACK_MAX_SIZE;
|
||||
return true;
|
||||
};
|
||||
|
||||
PayPro.prototype.getContentType = function() {
|
||||
if (this.messageType == 'PaymentRequest')
|
||||
return PayPro.PAYMENT_REQUEST_CONTENT_TYPE;
|
||||
|
||||
if (this.messageType == 'Payment')
|
||||
return PayPro.PAYMENT_CONTENT_TYPE;
|
||||
|
||||
if (this.messageType == 'PaymentACK')
|
||||
return PayPro.PAYMENT_ACK_CONTENT_TYPE;
|
||||
|
||||
throw new Error('No known content type for this message type');
|
||||
};
|
||||
|
||||
PayPro.prototype.set = function(key, val) {
|
||||
this.message.set(key, val);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.get = function(key) {
|
||||
var v = this.message.get(key);
|
||||
|
||||
if (v === null)
|
||||
return v;
|
||||
|
||||
//protobuf supports longs, javascript naturally does not
|
||||
//convert longs (see long.js, e.g. require('long')) to Numbers
|
||||
if (typeof v.low !== 'undefined' && typeof v.high !== 'undefined')
|
||||
return v.toInt();
|
||||
|
||||
if (typeof v.toBuffer !== 'undefined') {
|
||||
var maybebuf = v.toBuffer();
|
||||
return Buffer.isBuffer(maybebuf) ? maybebuf : new Buffer(new Uint8Array(maybebuf));
|
||||
}
|
||||
|
||||
return v;
|
||||
};
|
||||
|
||||
PayPro.prototype.setObj = function(obj) {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
var val = obj[key];
|
||||
this.message.set(key, val);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.serializeForSig = function() {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('serializeForSig is only for PaymentRequest');
|
||||
|
||||
var save = this.message.get('signature');
|
||||
this.message.set('signature', new Buffer([]));
|
||||
var buf = this.serialize();
|
||||
this.message.set('signature', save);
|
||||
return buf;
|
||||
};
|
||||
|
||||
PayPro.prototype.serialize = function() {
|
||||
//protobufjs returns either a Buffer or an ArrayBuffer
|
||||
//but we always want a Buffer (which browserify understands, browser or no)
|
||||
var maybebuf = this.message.toBuffer();
|
||||
var buf = (Buffer.isBuffer(maybebuf)) ? maybebuf : new Buffer(new Uint8Array(maybebuf));
|
||||
return buf;
|
||||
};
|
||||
|
||||
PayPro.prototype.deserialize = function(buf, messageType) {
|
||||
this.messageType = messageType || this.messageType;
|
||||
if (!this.messageType)
|
||||
throw new Error('Must specify messageType');
|
||||
this.message = PayPro[this.messageType].decode(buf);
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.sign = function(key) {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Signing can only be performed on a PaymentRequest');
|
||||
|
||||
var pki_type = this.get('pki_type');
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
var sig = this.sinSign(key);
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
var sig = this.x509Sign(key);
|
||||
} else if (pki_type === 'none') {
|
||||
return this;
|
||||
} else {
|
||||
throw new Error('Unsupported pki_type');
|
||||
}
|
||||
|
||||
this.set('signature', sig);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PayPro.prototype.verify = function() {
|
||||
if (this.messageType !== 'PaymentRequest')
|
||||
throw new Error('Verifying can only be performed on a PaymentRequest');
|
||||
|
||||
var pki_type = this.get('pki_type');
|
||||
|
||||
if (pki_type === 'SIN') {
|
||||
return this.sinVerify();
|
||||
} else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') {
|
||||
return this.x509Verify();
|
||||
} else if (pki_type === 'none') {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error('Unsupported pki_type');
|
||||
};
|
||||
|
||||
//default signing function for prototype.sign
|
||||
PayPro.prototype.sinSign = function(key) {
|
||||
this.set('pki_data', key.public)
|
||||
var buf = this.serializeForSig();
|
||||
return Message.sign(buf, key);
|
||||
};
|
||||
|
||||
//default verify function
|
||||
PayPro.prototype.sinVerify = function() {
|
||||
var sig = this.get('signature');
|
||||
var pubkey = this.get('pki_data');
|
||||
var buf = this.serializeForSig();
|
||||
return Message.verifyWithPubKey(pubkey, buf, sig);
|
||||
};
|
||||
|
||||
module.exports = PayPro;
|
|
@ -4,7 +4,6 @@ var chai = chai || require('chai');
|
|||
var should = chai.should();
|
||||
var expect = chai.expect;
|
||||
var bitcore = bitcore || require('../bitcore');
|
||||
var fs = require('fs');
|
||||
|
||||
var KJUR = require('jsrsasign');
|
||||
|
||||
|
@ -12,15 +11,92 @@ var PayPro = bitcore.PayPro;
|
|||
var Key = bitcore.Key;
|
||||
|
||||
var x509 = {
|
||||
priv: fs.readFileSync(__dirname + '/data/x509.key'),
|
||||
pub: fs.readFileSync(__dirname + '/data/x509.pub'),
|
||||
der: fs.readFileSync(__dirname + '/data/x509.der'),
|
||||
pem: fs.readFileSync(__dirname + '/data/x509.crt'),
|
||||
priv: ''
|
||||
+ 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeFRKdUsyYUdM'
|
||||
+ 'bjFkWEpLRGg0TXdQTFVrbDNISTVwR25HNWFjNGwvMGlobXE4Y3dDCitGVlBnWk1TNTlheWtpc0Ir'
|
||||
+ 'ekM3dnR2a0prL2J2K0JTT1g3b3hkSXN1TDNkS1FGcHVYWFZmcmRiOTV3WW40TSsKL25qRWhYTWxo'
|
||||
+ 'Vk1IL09DaUFnOUpLaFRLV0w2R1JXWkFBaEE3bEJSaGdTTkRUaVRDNTFDYmlLN3hBNnBONCt0UQpI'
|
||||
+ 'eG9tSlBYclpSa2JCMmtsT2ZXd2J2OTNZM0oxS0ZEK2kwUE1RSEx3N3JoRXVteEM5MytISFVWWVZI'
|
||||
+ 'N0gxVFBaCkgxYmRVSkowMmdRZXlsSnNzWUNKeWRaUHpOVC96dXRzL0tKV2RSdjVseHdHOXU5dE1O'
|
||||
+ 'TWdoSmJtQWFNa01HaSsKbzdQTkV5UDNxSEZyWXBZaHM1cHFMSE1STkI3OFFNOUllTmpMRndJREFR'
|
||||
+ 'QUJBb0lCQVFERVJyalBiQUdjbmwxaAorZGIrOTczNGZ0aElBUkpWSko1dTRFK1JKcThSRWhGTEVL'
|
||||
+ 'UFlKNW0yUC94dVZBMXpYV2xnYXhaRUZ6d1VRaUpZCjdsOEpLVjlwSHhReVlaQ1M4dndYZzhpWGtz'
|
||||
+ 'dndQaWRvQmN1YW4vd0RWQ1FCZXk2VkxjVXpSYUd1Ui9sTHNYK1YKN2Z0QjBvUnFsSXFrYmNQZE1N'
|
||||
+ 'dnFUeG93UnVoUG11Q3JWVGpPNHBiTnFuU09OUExPaUovRkFYYjJwZnpGZnBCUgpHeCtFTW16d2Ur'
|
||||
+ 'SEZuSkJHRGhIWjk5bm4vVEJmYUp6TlZDcURZLzNid3o1WDdIUU5ZN1QrSnlUVUZzZVE5NHhzCnpy'
|
||||
+ 'a2lidGRmVGNUanB1K1VoWm80c1p6Q3IrZkhHWm9FOUdEUHF0ZDRnQ3ByazRFS0pzbXFCRVN4QlhT'
|
||||
+ 'RGhZZ04KOXBVRDM4c1pBb0dCQU9yZkRqdDZaL0ZDamFuVThXek5GaWYrOVQxQTJ4b013RDVWU2xN'
|
||||
+ 'dVJyWW1HbGZyMEM5TQpmMUVvZ2l2dVRrYnA3cmtnZFRhWVRTYndmTnFaQkt4Y3R5YzdCaGRwWnhE'
|
||||
+ 'RVdKa2Z5cThxVngvem1Cek1JK1ZzCjJLYi9hcHZXcmJlb3NET0NyeUg1YzhKc1VUOXhUWDNYYnhF'
|
||||
+ 'anlPSlFCU1lHRE1qUHlKNkU5czZMQW9HQkFOYnYKd2d0S2Nra0tLbDJhNXZzaGR2RENnNnFLL1Fn'
|
||||
+ 'T20vNktUSlVKRVNqaHoydFIrZlBWUjcwVEg5UmhoVFJscERXQgpCd3oyU2NCc1RRNDIvTGsxRnky'
|
||||
+ 'MFQvck12S3VmSEw1VE1BNGZ6NWRxMUxIbmN6ejZVazVnWEtBT09rUjlVdVhpClR0eTNoREcyQkM4'
|
||||
+ 'Nk1LTVJ4SjUxRWJxam94d0VSMTAwU2FuTVBmTWxBb0dBSUhLY1pyOHNhUHBHMC9XbFBPREEKZE5v'
|
||||
+ 'V1MxWVFidkxnQkR5SVBpR2doejJRV2lFcjY3em53ZkNVdXpqNiszVUtFKzFXQkNyYVRjemZrdHVj'
|
||||
+ 'OTZyLwphcDRPNDJFZWFnU1dNT0ZoZ1AyYWQ4R1JmRGovcEl4N0NlY3pkVUFkVThnc1A1R0lYR3M0'
|
||||
+ 'QU40eUEwL0Y0dUxHCloxbklRT3ZKS2syZnFvWjZNdHd2dEswQ2dZRUFnSjdGTGVDRTkzUmYyZGdD'
|
||||
+ 'ZFRHWGJZZlpKc3M1bEFLNkV0NUwKNmJ1ZFN5dWw1Z0VPWkgyekNsQlJjZFJSMUFNbSt1V1ZoSW8x'
|
||||
+ 'cERLckFlQ2g1MnIvemRmakxLQXNIejkrQWQ3aQpHUEdzVmw0Vm5jaDFTMzQ0bHJKUGUzQklLZ2dj'
|
||||
+ 'L1hncDNTYnNzcHJMY2orT0wyZElrOUpXbzZ1Y3hmMUJmMkwwCjJlbGhBUWtDZ1lCWHN5elZWL1pK'
|
||||
+ 'cVhOcFdDZzU1TDNVRm9UTHlLU3FsVktNM1dpRzVCS240QWF6VkNITCtHUVUKeHd4U2dSOWZRNElu'
|
||||
+ 'dStyUHJOM0lteWswbEtQR0Y5U3pDUlJUaUpGUjcyc05xbE82bDBWOENXUkFQVFBKY2dxVgoxVThO'
|
||||
+ 'SEs4YjNaaUlvR0orbXNOenBkeHJqNjJIM0E2K1krQXNOWTRTbVVUWEg5eWpnK251a2c9PQotLS0t'
|
||||
+ 'LUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=',
|
||||
pub: ''
|
||||
+ 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FR'
|
||||
+ 'OEFNSUlCQ2dLQ0FRRUF4VEp1SzJhR0xuMWRYSktEaDRNdwpQTFVrbDNISTVwR25HNWFjNGwvMGlo'
|
||||
+ 'bXE4Y3dDK0ZWUGdaTVM1OWF5a2lzQit6Qzd2dHZrSmsvYnYrQlNPWDdvCnhkSXN1TDNkS1FGcHVY'
|
||||
+ 'WFZmcmRiOTV3WW40TSsvbmpFaFhNbGhWTUgvT0NpQWc5SktoVEtXTDZHUldaQUFoQTcKbEJSaGdT'
|
||||
+ 'TkRUaVRDNTFDYmlLN3hBNnBONCt0UUh4b21KUFhyWlJrYkIya2xPZld3YnY5M1kzSjFLRkQraTBQ'
|
||||
+ 'TQpRSEx3N3JoRXVteEM5MytISFVWWVZIN0gxVFBaSDFiZFVKSjAyZ1FleWxKc3NZQ0p5ZFpQek5U'
|
||||
+ 'L3p1dHMvS0pXCmRSdjVseHdHOXU5dE1OTWdoSmJtQWFNa01HaStvN1BORXlQM3FIRnJZcFloczVw'
|
||||
+ 'cUxITVJOQjc4UU05SWVOakwKRndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==',
|
||||
der: ''
|
||||
+ 'MIIDBjCCAe4CCQDI2qWdA3/VpDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTETMBEGA1UE'
|
||||
+ 'CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE0MDcx'
|
||||
+ 'NjAxMzM1MVoXDTE1MDcxNjAxMzM1MVowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh'
|
||||
+ 'dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQAD'
|
||||
+ 'ggEPADCCAQoCggEBAMUybitmhi59XVySg4eDMDy1JJdxyOaRpxuWnOJf9IoZqvHMAvhVT4GTEufW'
|
||||
+ 'spIrAfswu77b5CZP27/gUjl+6MXSLLi93SkBabl11X63W/ecGJ+DPv54xIVzJYVTB/zgogIPSSoU'
|
||||
+ 'yli+hkVmQAIQO5QUYYEjQ04kwudQm4iu8QOqTePrUB8aJiT162UZGwdpJTn1sG7/d2NydShQ/otD'
|
||||
+ 'zEBy8O64RLpsQvd/hx1FWFR+x9Uz2R9W3VCSdNoEHspSbLGAicnWT8zU/87rbPyiVnUb+ZccBvbv'
|
||||
+ 'bTDTIISW5gGjJDBovqOzzRMj96hxa2KWIbOaaixzETQe/EDPSHjYyxcCAwEAATANBgkqhkiG9w0B'
|
||||
+ 'AQUFAAOCAQEAL6AMMfC3TlRcmsIgHxjVD4XYtISlldnrn2X9zvFbJKCpNy8XQQosQxrhyfzPHQKj'
|
||||
+ 'lS2L/KCGMnjx9QkYD2Hlp1MJ1uVv9888th/gcZOv3Or3hQyi5K1Sh5xCG+69lUOqUEGu9B4irsqo'
|
||||
+ 'FomQVbQolSy+t4apdJi7kuEDwFDk4gZiVEfsuX+naN5a6pCnWnhX1Vf4fKwfkLobKKXm2zQVsjxl'
|
||||
+ 'wBAqOEmJGDLoRMXH56qJnEZ/dqsczaJOHQSi9mFEHL0r5rsEDTT5AVxdnBfNnyGaCH7/zANEko+F'
|
||||
+ 'GBj1JdJaJgFTXdbxDoyoPTPD+LJqSK5XYToo46y/T0u9CLveNA==',
|
||||
pem: ''
|
||||
+ 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCakNDQWU0Q0NRREkycVdkQTMvVnBEQU5C'
|
||||
+ 'Z2txaGtpRzl3MEJBUVVGQURCRk1Rc3dDUVlEVlFRR0V3SkIKVlRFVE1CRUdBMVVFQ0F3S1UyOXRa'
|
||||
+ 'UzFUZEdGMFpURWhNQjhHQTFVRUNnd1lTVzUwWlhKdVpYUWdWMmxrWjJsMApjeUJRZEhrZ1RIUmtN'
|
||||
+ 'QjRYRFRFME1EY3hOakF4TXpNMU1Wb1hEVEUxTURjeE5qQXhNek0xTVZvd1JURUxNQWtHCkExVUVC'
|
||||
+ 'aE1DUVZVeEV6QVJCZ05WQkFnTUNsTnZiV1V0VTNSaGRHVXhJVEFmQmdOVkJBb01HRWx1ZEdWeWJt'
|
||||
+ 'VjAKSUZkcFpHZHBkSE1nVUhSNUlFeDBaRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFE'
|
||||
+ 'Q0NBUW9DZ2dFQgpBTVV5Yml0bWhpNTlYVnlTZzRlRE1EeTFKSmR4eU9hUnB4dVduT0pmOUlvWnF2'
|
||||
+ 'SE1BdmhWVDRHVEV1ZldzcElyCkFmc3d1NzdiNUNaUDI3L2dVamwrNk1YU0xMaTkzU2tCYWJsMTFY'
|
||||
+ 'NjNXL2VjR0orRFB2NTR4SVZ6SllWVEIvemcKb2dJUFNTb1V5bGkraGtWbVFBSVFPNVFVWVlFalEw'
|
||||
+ 'NGt3dWRRbTRpdThRT3FUZVByVUI4YUppVDE2MlVaR3dkcApKVG4xc0c3L2QyTnlkU2hRL290RHpF'
|
||||
+ 'Qnk4TzY0Ukxwc1F2ZC9oeDFGV0ZSK3g5VXoyUjlXM1ZDU2ROb0VIc3BTCmJMR0FpY25XVDh6VS84'
|
||||
+ 'N3JiUHlpVm5VYitaY2NCdmJ2YlREVElJU1c1Z0dqSkRCb3ZxT3p6Uk1qOTZoeGEyS1cKSWJPYWFp'
|
||||
+ 'eHpFVFFlL0VEUFNIall5eGNDQXdFQUFUQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFMNkFNTWZD'
|
||||
+ 'MwpUbFJjbXNJZ0h4alZENFhZdElTbGxkbnJuMlg5enZGYkpLQ3BOeThYUVFvc1F4cmh5ZnpQSFFL'
|
||||
+ 'amxTMkwvS0NHCk1uang5UWtZRDJIbHAxTUoxdVZ2OTg4OHRoL2djWk92M09yM2hReWk1SzFTaDV4'
|
||||
+ 'Q0crNjlsVU9xVUVHdTlCNGkKcnNxb0ZvbVFWYlFvbFN5K3Q0YXBkSmk3a3VFRHdGRGs0Z1ppVkVm'
|
||||
+ 'c3VYK25hTjVhNnBDblduaFgxVmY0Zkt3ZgprTG9iS0tYbTJ6UVZzanhsd0JBcU9FbUpHRExvUk1Y'
|
||||
+ 'SDU2cUpuRVovZHFzY3phSk9IUVNpOW1GRUhMMHI1cnNFCkRUVDVBVnhkbkJmTm55R2FDSDcvekFO'
|
||||
+ 'RWtvK0ZHQmoxSmRKYUpnRlRYZGJ4RG95b1BUUEQrTEpxU0s1WFlUb28KNDZ5L1QwdTlDTHZlTkE9'
|
||||
+ 'PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==',
|
||||
sig1: new Buffer(0),
|
||||
sig2: new Buffer(0),
|
||||
sig3: new Buffer(0)
|
||||
};
|
||||
|
||||
x509.priv = new Buffer(x509.priv, 'base64');
|
||||
x509.pub = new Buffer(x509.pub, 'base64');
|
||||
x509.der = new Buffer(x509.der, 'base64');
|
||||
x509.pem = new Buffer(x509.pem, 'base64');
|
||||
|
||||
describe('PayPro', function() {
|
||||
|
||||
it('should be able to create class', function() {
|
||||
|
|
Loading…
Reference in New Issue