Merge pull request #435 from chjj/paypro
WIP: BIP-70 x509 signing and verification
This commit is contained in:
commit
5f81682bd6
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var fs = require('fs');
|
||||
var url = require('url');
|
||||
var http = require('http');
|
||||
var path = require('path');
|
||||
var Stream = require('stream').Stream;
|
||||
var StringDecoder = require('string_decoder').StringDecoder;
|
||||
|
||||
/**
|
||||
* Mozilla Root Cert URL
|
||||
*/
|
||||
|
||||
var certUrl = 'https://raw.githubusercontent.com/joyent/node/master/src/node_root_certs.h';
|
||||
|
||||
/**
|
||||
* Get Root Certs
|
||||
*/
|
||||
|
||||
function getRootCerts(callback) {
|
||||
return request(certUrl, function(err, res, body) {
|
||||
if (err) return callback(err);
|
||||
body = body.replace(/,$/, '');
|
||||
body = 'var RootCerts = [\n' + body + '\n];\n';
|
||||
body = body.replace(/^"/gm, '+ "');
|
||||
body = body.replace(/^\+ "-----B/gm, '"-----B');
|
||||
body += ''
|
||||
+ '\n'
|
||||
+ '// Use hash table for efficiency:\n'
|
||||
+ 'RootCerts = RootCerts.reduce(function(trusted, cert) {\n'
|
||||
+ ' cert = cert.replace(/\\s+/g, "");\n'
|
||||
+ ' trusted[cert] = true;\n'
|
||||
+ ' return trusted;\n'
|
||||
+ '}, {});\n'
|
||||
+ '\n'
|
||||
+ 'function isTrusted(pem) {\n'
|
||||
+ ' pem = pem + "";\n'
|
||||
+ ' pem = pem.replace(/\\s+/g, "");\n'
|
||||
+ ' return !!RootCerts[pem];\n'
|
||||
+ '}\n'
|
||||
+ '\n'
|
||||
+ 'exports = RootCerts;\n'
|
||||
+ 'exports.isTrusted = isTrusted;\n'
|
||||
+ 'module.exports = exports;\n';
|
||||
return callback(null, body);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function request(options, callback) {
|
||||
if (typeof options === 'string' || options.hostname) {
|
||||
options = { uri: options };
|
||||
}
|
||||
|
||||
var uri = options.uri || options.url
|
||||
, body = options.json
|
||||
? JSON.stringify(options.json)
|
||||
: options.body || '';
|
||||
|
||||
if (typeof uri !== 'object') {
|
||||
uri = url.parse(uri);
|
||||
}
|
||||
|
||||
if (options.qs) {
|
||||
var query = uri.query ? qs.parse(uri.query) : {};
|
||||
Object.keys(options.qs).forEach(function(key) {
|
||||
query[key] = options.qs[key];
|
||||
});
|
||||
uri.path = uri.pathname + '?' + qs.stringify(query);
|
||||
}
|
||||
|
||||
var protocol = uri.protocol === 'https:'
|
||||
? require('https')
|
||||
: http;
|
||||
|
||||
options.method = options.method || (body ? 'POST' : 'GET');
|
||||
options.method = options.method.toUpperCase();
|
||||
options.headers = options.headers || {};
|
||||
|
||||
options.headers['Accept'] = options.headers['Accept'] || 'text/plain; charset=utf-8';
|
||||
|
||||
if (options.json) {
|
||||
options.headers['Content-Type'] = 'application/json; charset=utf-8';
|
||||
options.headers['Accept'] = 'application/json';
|
||||
}
|
||||
|
||||
if (options.method !== 'GET' && options.method !== 'HEAD') {
|
||||
options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||
}
|
||||
|
||||
var opt = {
|
||||
auth: uri.auth,
|
||||
host: uri.hostname,
|
||||
port: uri.port || (protocol === http ? 80 : 443),
|
||||
path: uri.path,
|
||||
method: options.method,
|
||||
headers: options.headers
|
||||
};
|
||||
|
||||
|
||||
var req = protocol.request(opt)
|
||||
, response = new Stream;
|
||||
|
||||
req.on('error', function(err) {
|
||||
if (callback) {
|
||||
callback(err);
|
||||
} else {
|
||||
response.emit('error', err);
|
||||
}
|
||||
});
|
||||
|
||||
req.on('response', function(res) {
|
||||
var decoder = new StringDecoder('utf8')
|
||||
, done = false
|
||||
, body = '';
|
||||
|
||||
function end() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
if (callback) {
|
||||
res.body = body;
|
||||
if (options.json) {
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
callback(null, res, body);
|
||||
} else {
|
||||
response.emit('end');
|
||||
}
|
||||
res.socket.removeListener('error', error);
|
||||
res.socket.removeListener('end', end);
|
||||
}
|
||||
|
||||
function error(err) {
|
||||
res.destroy();
|
||||
if (callback) {
|
||||
callback(err);
|
||||
} else {
|
||||
response.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
res.on('data', function(data) {
|
||||
if (callback) {
|
||||
body += decoder.write(data);
|
||||
} else {
|
||||
response.emit('data', data);
|
||||
}
|
||||
});
|
||||
|
||||
res.on('error', error);
|
||||
res.socket.on('error', error);
|
||||
|
||||
res.on('end', end);
|
||||
// An agent socket's `end` sometimes
|
||||
// wont be emitted on the response.
|
||||
res.socket.on('end', end);
|
||||
});
|
||||
|
||||
req.end(body);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*/
|
||||
|
||||
function main(argv, callback) {
|
||||
if (!callback) {
|
||||
callback = argv;
|
||||
argv = null;
|
||||
}
|
||||
return getRootCerts(function(err, certs) {
|
||||
var file = path.resolve(__dirname, '..', 'lib', 'common', 'RootCerts.js');
|
||||
return fs.writeFile(file, certs, callback);
|
||||
});
|
||||
}
|
||||
|
||||
if (!module.parent) {
|
||||
process.title = 'root-certs';
|
||||
main(process.argv.slice(), function(err, code) {
|
||||
if (err) throw err;
|
||||
return process.exit(code || 0);
|
||||
});
|
||||
} else {
|
||||
module.exports = main;
|
||||
}
|
272
lib/PayPro.js
272
lib/PayPro.js
|
@ -1,245 +1,61 @@
|
|||
'use strict';
|
||||
var protobufjs = protobufjs || require('protobufjs/dist/ProtoBuf');
|
||||
|
||||
var Message = Message || require('./Message');
|
||||
|
||||
// BIP 70 - payment protocol
|
||||
function PayPro() {
|
||||
this.messageType = null;
|
||||
this.message = null;
|
||||
}
|
||||
var RootCerts = require('./common/RootCerts');
|
||||
|
||||
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";
|
||||
var PayPro = require('./common/PayPro');
|
||||
|
||||
PayPro.proto = {};
|
||||
PayPro.prototype.x509Sign = function(key) {
|
||||
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 details = this.get('serialized_payment_details');
|
||||
var type = pki_type.split('+')[1].toUpperCase();
|
||||
|
||||
PayPro.proto.Output = "message Output {\
|
||||
optional uint64 amount = 1 [default = 0];\
|
||||
optional bytes script = 2;\
|
||||
}\n";
|
||||
var trusted = [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = self._DERtoPEM(der, 'CERTIFICATE');
|
||||
return RootCerts.isTrusted(pem);
|
||||
});
|
||||
|
||||
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));
|
||||
if (!trusted) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
throw new Error('Unsupported pki_type');
|
||||
};
|
||||
|
||||
//default signing function for prototype.sign
|
||||
PayPro.prototype.sinSign = function(key) {
|
||||
this.set('pki_data', key.public)
|
||||
var signature = crypto.createSign('RSA-' + type);
|
||||
var buf = this.serializeForSig();
|
||||
return Message.sign(buf, key);
|
||||
signature.update(buf);
|
||||
var sig = signature.sign(key);
|
||||
return sig;
|
||||
};
|
||||
|
||||
//default verify function
|
||||
PayPro.prototype.sinVerify = function() {
|
||||
PayPro.prototype.x509Verify = function() {
|
||||
var self = this;
|
||||
var crypto = require('crypto');
|
||||
var pki_type = this.get('pki_type');
|
||||
var sig = this.get('signature');
|
||||
var pubkey = this.get('pki_data');
|
||||
var pki_data = this.get('pki_data');
|
||||
var details = this.get('serialized_payment_details');
|
||||
var buf = this.serializeForSig();
|
||||
return Message.verifyWithPubKey(pubkey, buf, sig);
|
||||
var type = pki_type.split('+')[1].toUpperCase();
|
||||
|
||||
var verifier = crypto.createVerify('RSA-' + type);
|
||||
verifier.update(buf);
|
||||
|
||||
return [].concat(pki_data).every(function(cert) {
|
||||
var der = cert.toString('hex');
|
||||
var pem = self._DERtoPEM(der, 'CERTIFICATE');
|
||||
|
||||
if (!RootCerts.isTrusted(pem)) {
|
||||
// XXX Figure out what to do here
|
||||
// throw new Error('Unstrusted certificate.');
|
||||
}
|
||||
|
||||
return verifier.verify(pem, sig);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = PayPro;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
"use strict";
|
||||
|
||||
var Key = require('./Key');
|
||||
var KJUR = require('jsrsasign');
|
||||
var assert = require('assert');
|
||||
var PayPro = require('../common/PayPro');
|
||||
var RootCerts = require('../common/RootCerts');
|
||||
|
||||
// Documentation:
|
||||
// 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) {
|
||||
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();
|
||||
|
||||
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.');
|
||||
}
|
||||
|
||||
var rsa = new KJUR.RSAKey();
|
||||
rsa.readPrivateKeyFromPEMString(key.toString());
|
||||
key = rsa;
|
||||
|
||||
var jsrsaSig = new KJUR.crypto.Signature({
|
||||
alg: type.toUpperCase() + 'withRSA',
|
||||
prov: 'cryptojs/jsrsa'
|
||||
});
|
||||
|
||||
// XXX Could use this?
|
||||
//jsrsaSig.initSign(key);
|
||||
|
||||
jsrsaSig.init(key);
|
||||
|
||||
jsrsaSig.updateHex(buf.toString('hex'));
|
||||
|
||||
var sig = new Buffer(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.toUpperCase() + '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.');
|
||||
}
|
||||
|
||||
jsrsaSig.initVerifyByCertificatePEM(pem);
|
||||
|
||||
jsrsaSig.updateHex(buf.toString('hex'));
|
||||
|
||||
return jsrsaSig.verify(sig.toString('hex'));
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = PayPro;
|
|
@ -0,0 +1,296 @@
|
|||
'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);
|
||||
};
|
||||
|
||||
// Helpers
|
||||
|
||||
PayPro.prototype._PEMtoDER = function(pem) {
|
||||
return this._PEMtoDERParam(pem);
|
||||
};
|
||||
|
||||
PayPro.prototype._PEMtoDERParam = function(pem, param) {
|
||||
if (Buffer.isBuffer(pem)) {
|
||||
pem = pem.toString();
|
||||
}
|
||||
var start = new RegExp('(?=-----BEGIN ' + (param || '[^-]+') + '-----)', 'i');
|
||||
var end = new RegExp('^-----END ' + (param || '[^-]+') + '-----$', 'gmi');
|
||||
pem = pem.replace(end, '');
|
||||
var parts = pem.split(start);
|
||||
return parts.map(function(part) {
|
||||
var type = /-----BEGIN ([^-]+)-----/.exec(part)[1];
|
||||
part = part.replace(/-----BEGIN ([^-]+)-----/g, '');
|
||||
part = part.replace(/\s+/g, '');
|
||||
if (!param || type !== param) return;
|
||||
return new Buffer(part, 'base64');
|
||||
}).filter(Boolean);
|
||||
};
|
||||
|
||||
PayPro.prototype._DERtoPEM = function(der, type) {
|
||||
if (typeof der === 'string') {
|
||||
der = new Buffer(der, 'hex');
|
||||
}
|
||||
var type = type || 'UNKNOWN';
|
||||
der = der.toString('base64');
|
||||
der = der.replace(/(.{64})/g, '$1\r\n');
|
||||
der = der.replace(/\r\n$/, '');
|
||||
return ''
|
||||
+ '-----BEGIN ' + type + '-----\r\n'
|
||||
+ der
|
||||
+ '\r\n-----END ' + type + '-----\r\n';
|
||||
};
|
||||
|
||||
module.exports = PayPro;
|
File diff suppressed because it is too large
Load Diff
|
@ -56,7 +56,7 @@
|
|||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-markdown": "~0.5.0",
|
||||
"grunt-mocha-test": "~0.8.2",
|
||||
"grunt-shell": "~0.6.4",
|
||||
"grunt-shell": "~0.6.4",
|
||||
"protobufjs": "=3.0.0",
|
||||
"coveralls": "^2.10.0",
|
||||
"istanbul": "~0.2.6",
|
||||
|
@ -65,6 +65,7 @@
|
|||
"sjcl": "=1.0.1",
|
||||
"hash.js": "=0.3.1",
|
||||
"bn.js": "=0.13.3",
|
||||
"jsrsasign": "=0.0.3",
|
||||
"elliptic": "=0.15.7",
|
||||
"bindings": "=1.1.1",
|
||||
"bufferput": "git://github.com/bitpay/node-bufferput.git",
|
||||
|
@ -104,7 +105,8 @@
|
|||
"./lib/Key.js": "./lib/browser/Key.js",
|
||||
"./lib/Point.js": "./lib/browser/Point.js",
|
||||
"./lib/ECIES.js": "./lib/browser/ECIES.js",
|
||||
"./lib/SecureRandom.js": "./lib/browser/SecureRandom.js"
|
||||
"./lib/SecureRandom.js": "./lib/browser/SecureRandom.js",
|
||||
"./lib/PayPro.js": "./lib/browser/PayPro.js"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe4CCQDI2qWdA3/VpDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE0MDcxNjAxMzM1MVoXDTE1MDcxNjAxMzM1MVowRTELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMUybitmhi59XVySg4eDMDy1JJdxyOaRpxuWnOJf9IoZqvHMAvhVT4GTEufWspIr
|
||||
Afswu77b5CZP27/gUjl+6MXSLLi93SkBabl11X63W/ecGJ+DPv54xIVzJYVTB/zg
|
||||
ogIPSSoUyli+hkVmQAIQO5QUYYEjQ04kwudQm4iu8QOqTePrUB8aJiT162UZGwdp
|
||||
JTn1sG7/d2NydShQ/otDzEBy8O64RLpsQvd/hx1FWFR+x9Uz2R9W3VCSdNoEHspS
|
||||
bLGAicnWT8zU/87rbPyiVnUb+ZccBvbvbTDTIISW5gGjJDBovqOzzRMj96hxa2KW
|
||||
IbOaaixzETQe/EDPSHjYyxcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAL6AMMfC3
|
||||
TlRcmsIgHxjVD4XYtISlldnrn2X9zvFbJKCpNy8XQQosQxrhyfzPHQKjlS2L/KCG
|
||||
Mnjx9QkYD2Hlp1MJ1uVv9888th/gcZOv3Or3hQyi5K1Sh5xCG+69lUOqUEGu9B4i
|
||||
rsqoFomQVbQolSy+t4apdJi7kuEDwFDk4gZiVEfsuX+naN5a6pCnWnhX1Vf4fKwf
|
||||
kLobKKXm2zQVsjxlwBAqOEmJGDLoRMXH56qJnEZ/dqsczaJOHQSi9mFEHL0r5rsE
|
||||
DTT5AVxdnBfNnyGaCH7/zANEko+FGBj1JdJaJgFTXdbxDoyoPTPD+LJqSK5XYToo
|
||||
46y/T0u9CLveNA==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
|
||||
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBAMUybitmhi59XVySg4eDMDy1JJdxyOaRpxuWnOJf
|
||||
9IoZqvHMAvhVT4GTEufWspIrAfswu77b5CZP27/gUjl+6MXSLLi93SkBabl11X63
|
||||
W/ecGJ+DPv54xIVzJYVTB/zgogIPSSoUyli+hkVmQAIQO5QUYYEjQ04kwudQm4iu
|
||||
8QOqTePrUB8aJiT162UZGwdpJTn1sG7/d2NydShQ/otDzEBy8O64RLpsQvd/hx1F
|
||||
WFR+x9Uz2R9W3VCSdNoEHspSbLGAicnWT8zU/87rbPyiVnUb+ZccBvbvbTDTIISW
|
||||
5gGjJDBovqOzzRMj96hxa2KWIbOaaixzETQe/EDPSHjYyxcCAwEAAaAAMA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQCu1Pdo1bKywBtzBXkqGudI5Nab6ixthjtlByTXdRd/7iy9
|
||||
zPMqoM6DBB9VtS6mnco7G1R8VaJu83N/uRoWCM80lb47isXRoMLe1DOrkjWmzjdU
|
||||
/rvwjhEzq2v42OVASgTD/sRziDOJ2DTG5W4VMEDzIEHFCXdbCc2HodA5/iSM9m5i
|
||||
FhhYC9HAHdHXgh1SVulxSGj6zOanOoNs68UBRnyGhS+c4lEDqlWw+WMioxmGgKic
|
||||
XnFvGu5u6g7lzjKUV5H/oHnLhkY3llA67dyz3EK6Nij9+CLfNHfTz4c6DO2J9FQp
|
||||
ME9S6EZSnvyDIKT6pgVk3nDiLzyYpQJ44cDlH2Db
|
||||
-----END CERTIFICATE REQUEST-----
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxTJuK2aGLn1dXJKDh4MwPLUkl3HI5pGnG5ac4l/0ihmq8cwC
|
||||
+FVPgZMS59aykisB+zC7vtvkJk/bv+BSOX7oxdIsuL3dKQFpuXXVfrdb95wYn4M+
|
||||
/njEhXMlhVMH/OCiAg9JKhTKWL6GRWZAAhA7lBRhgSNDTiTC51CbiK7xA6pN4+tQ
|
||||
HxomJPXrZRkbB2klOfWwbv93Y3J1KFD+i0PMQHLw7rhEumxC93+HHUVYVH7H1TPZ
|
||||
H1bdUJJ02gQeylJssYCJydZPzNT/zuts/KJWdRv5lxwG9u9tMNMghJbmAaMkMGi+
|
||||
o7PNEyP3qHFrYpYhs5pqLHMRNB78QM9IeNjLFwIDAQABAoIBAQDERrjPbAGcnl1h
|
||||
+db+9734fthIARJVJJ5u4E+RJq8REhFLEKPYJ5m2P/xuVA1zXWlgaxZEFzwUQiJY
|
||||
7l8JKV9pHxQyYZCS8vwXg8iXksvwPidoBcuan/wDVCQBey6VLcUzRaGuR/lLsX+V
|
||||
7ftB0oRqlIqkbcPdMMvqTxowRuhPmuCrVTjO4pbNqnSONPLOiJ/FAXb2pfzFfpBR
|
||||
Gx+EMmzwe+HFnJBGDhHZ99nn/TBfaJzNVCqDY/3bwz5X7HQNY7T+JyTUFseQ94xs
|
||||
zrkibtdfTcTjpu+UhZo4sZzCr+fHGZoE9GDPqtd4gCprk4EKJsmqBESxBXSDhYgN
|
||||
9pUD38sZAoGBAOrfDjt6Z/FCjanU8WzNFif+9T1A2xoMwD5VSlMuRrYmGlfr0C9M
|
||||
f1EogivuTkbp7rkgdTaYTSbwfNqZBKxctyc7BhdpZxDEWJkfyq8qVx/zmBzMI+Vs
|
||||
2Kb/apvWrbeosDOCryH5c8JsUT9xTX3XbxEjyOJQBSYGDMjPyJ6E9s6LAoGBANbv
|
||||
wgtKckkKKl2a5vshdvDCg6qK/QgOm/6KTJUJESjhz2tR+fPVR70TH9RhhTRlpDWB
|
||||
Bwz2ScBsTQ42/Lk1Fy20T/rMvKufHL5TMA4fz5dq1LHnczz6Uk5gXKAOOkR9UuXi
|
||||
Tty3hDG2BC86MKMRxJ51EbqjoxwER100SanMPfMlAoGAIHKcZr8saPpG0/WlPODA
|
||||
dNoWS1YQbvLgBDyIPiGghz2QWiEr67znwfCUuzj6+3UKE+1WBCraTczfktuc96r/
|
||||
ap4O42EeagSWMOFhgP2ad8GRfDj/pIx7CeczdUAdU8gsP5GIXGs4AN4yA0/F4uLG
|
||||
Z1nIQOvJKk2fqoZ6MtwvtK0CgYEAgJ7FLeCE93Rf2dgCdTGXbYfZJss5lAK6Et5L
|
||||
6budSyul5gEOZH2zClBRcdRR1AMm+uWVhIo1pDKrAeCh52r/zdfjLKAsHz9+Ad7i
|
||||
GPGsVl4Vnch1S344lrJPe3BIKggc/Xgp3SbssprLcj+OL2dIk9JWo6ucxf1Bf2L0
|
||||
2elhAQkCgYBXsyzVV/ZJqXNpWCg55L3UFoTLyKSqlVKM3WiG5BKn4AazVCHL+GQU
|
||||
xwxSgR9fQ4Inu+rPrN3Imyk0lKPGF9SzCRRTiJFR72sNqlO6l0V8CWRAPTPJcgqV
|
||||
1U8NHK8b3ZiIoGJ+msNzpdxrj62H3A6+Y+AsNY4SmUTXH9yjg+nukg==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,46 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe4CCQDI2qWdA3/VpDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE0MDcxNjAxMzM1MVoXDTE1MDcxNjAxMzM1MVowRTELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMUybitmhi59XVySg4eDMDy1JJdxyOaRpxuWnOJf9IoZqvHMAvhVT4GTEufWspIr
|
||||
Afswu77b5CZP27/gUjl+6MXSLLi93SkBabl11X63W/ecGJ+DPv54xIVzJYVTB/zg
|
||||
ogIPSSoUyli+hkVmQAIQO5QUYYEjQ04kwudQm4iu8QOqTePrUB8aJiT162UZGwdp
|
||||
JTn1sG7/d2NydShQ/otDzEBy8O64RLpsQvd/hx1FWFR+x9Uz2R9W3VCSdNoEHspS
|
||||
bLGAicnWT8zU/87rbPyiVnUb+ZccBvbvbTDTIISW5gGjJDBovqOzzRMj96hxa2KW
|
||||
IbOaaixzETQe/EDPSHjYyxcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAL6AMMfC3
|
||||
TlRcmsIgHxjVD4XYtISlldnrn2X9zvFbJKCpNy8XQQosQxrhyfzPHQKjlS2L/KCG
|
||||
Mnjx9QkYD2Hlp1MJ1uVv9888th/gcZOv3Or3hQyi5K1Sh5xCG+69lUOqUEGu9B4i
|
||||
rsqoFomQVbQolSy+t4apdJi7kuEDwFDk4gZiVEfsuX+naN5a6pCnWnhX1Vf4fKwf
|
||||
kLobKKXm2zQVsjxlwBAqOEmJGDLoRMXH56qJnEZ/dqsczaJOHQSi9mFEHL0r5rsE
|
||||
DTT5AVxdnBfNnyGaCH7/zANEko+FGBj1JdJaJgFTXdbxDoyoPTPD+LJqSK5XYToo
|
||||
46y/T0u9CLveNA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxTJuK2aGLn1dXJKDh4MwPLUkl3HI5pGnG5ac4l/0ihmq8cwC
|
||||
+FVPgZMS59aykisB+zC7vtvkJk/bv+BSOX7oxdIsuL3dKQFpuXXVfrdb95wYn4M+
|
||||
/njEhXMlhVMH/OCiAg9JKhTKWL6GRWZAAhA7lBRhgSNDTiTC51CbiK7xA6pN4+tQ
|
||||
HxomJPXrZRkbB2klOfWwbv93Y3J1KFD+i0PMQHLw7rhEumxC93+HHUVYVH7H1TPZ
|
||||
H1bdUJJ02gQeylJssYCJydZPzNT/zuts/KJWdRv5lxwG9u9tMNMghJbmAaMkMGi+
|
||||
o7PNEyP3qHFrYpYhs5pqLHMRNB78QM9IeNjLFwIDAQABAoIBAQDERrjPbAGcnl1h
|
||||
+db+9734fthIARJVJJ5u4E+RJq8REhFLEKPYJ5m2P/xuVA1zXWlgaxZEFzwUQiJY
|
||||
7l8JKV9pHxQyYZCS8vwXg8iXksvwPidoBcuan/wDVCQBey6VLcUzRaGuR/lLsX+V
|
||||
7ftB0oRqlIqkbcPdMMvqTxowRuhPmuCrVTjO4pbNqnSONPLOiJ/FAXb2pfzFfpBR
|
||||
Gx+EMmzwe+HFnJBGDhHZ99nn/TBfaJzNVCqDY/3bwz5X7HQNY7T+JyTUFseQ94xs
|
||||
zrkibtdfTcTjpu+UhZo4sZzCr+fHGZoE9GDPqtd4gCprk4EKJsmqBESxBXSDhYgN
|
||||
9pUD38sZAoGBAOrfDjt6Z/FCjanU8WzNFif+9T1A2xoMwD5VSlMuRrYmGlfr0C9M
|
||||
f1EogivuTkbp7rkgdTaYTSbwfNqZBKxctyc7BhdpZxDEWJkfyq8qVx/zmBzMI+Vs
|
||||
2Kb/apvWrbeosDOCryH5c8JsUT9xTX3XbxEjyOJQBSYGDMjPyJ6E9s6LAoGBANbv
|
||||
wgtKckkKKl2a5vshdvDCg6qK/QgOm/6KTJUJESjhz2tR+fPVR70TH9RhhTRlpDWB
|
||||
Bwz2ScBsTQ42/Lk1Fy20T/rMvKufHL5TMA4fz5dq1LHnczz6Uk5gXKAOOkR9UuXi
|
||||
Tty3hDG2BC86MKMRxJ51EbqjoxwER100SanMPfMlAoGAIHKcZr8saPpG0/WlPODA
|
||||
dNoWS1YQbvLgBDyIPiGghz2QWiEr67znwfCUuzj6+3UKE+1WBCraTczfktuc96r/
|
||||
ap4O42EeagSWMOFhgP2ad8GRfDj/pIx7CeczdUAdU8gsP5GIXGs4AN4yA0/F4uLG
|
||||
Z1nIQOvJKk2fqoZ6MtwvtK0CgYEAgJ7FLeCE93Rf2dgCdTGXbYfZJss5lAK6Et5L
|
||||
6budSyul5gEOZH2zClBRcdRR1AMm+uWVhIo1pDKrAeCh52r/zdfjLKAsHz9+Ad7i
|
||||
GPGsVl4Vnch1S344lrJPe3BIKggc/Xgp3SbssprLcj+OL2dIk9JWo6ucxf1Bf2L0
|
||||
2elhAQkCgYBXsyzVV/ZJqXNpWCg55L3UFoTLyKSqlVKM3WiG5BKn4AazVCHL+GQU
|
||||
xwxSgR9fQ4Inu+rPrN3Imyk0lKPGF9SzCRRTiJFR72sNqlO6l0V8CWRAPTPJcgqV
|
||||
1U8NHK8b3ZiIoGJ+msNzpdxrj62H3A6+Y+AsNY4SmUTXH9yjg+nukg==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxTJuK2aGLn1dXJKDh4Mw
|
||||
PLUkl3HI5pGnG5ac4l/0ihmq8cwC+FVPgZMS59aykisB+zC7vtvkJk/bv+BSOX7o
|
||||
xdIsuL3dKQFpuXXVfrdb95wYn4M+/njEhXMlhVMH/OCiAg9JKhTKWL6GRWZAAhA7
|
||||
lBRhgSNDTiTC51CbiK7xA6pN4+tQHxomJPXrZRkbB2klOfWwbv93Y3J1KFD+i0PM
|
||||
QHLw7rhEumxC93+HHUVYVH7H1TPZH1bdUJJ02gQeylJssYCJydZPzNT/zuts/KJW
|
||||
dRv5lxwG9u9tMNMghJbmAaMkMGi+o7PNEyP3qHFrYpYhs5pqLHMRNB78QM9IeNjL
|
||||
FwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
|
@ -8,6 +8,93 @@ var bitcore = bitcore || require('../bitcore');
|
|||
var PayPro = bitcore.PayPro;
|
||||
var Key = bitcore.Key;
|
||||
|
||||
var x509 = {
|
||||
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() {
|
||||
|
@ -243,6 +330,7 @@ describe('PayPro', function() {
|
|||
describe('#sign', function() {
|
||||
|
||||
it('should sign a payment request', function() {
|
||||
// SIN
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
@ -256,6 +344,19 @@ describe('PayPro', function() {
|
|||
paypro.sign(key);
|
||||
var sig = paypro.get('signature');
|
||||
sig.length.should.be.greaterThan(0);
|
||||
|
||||
// X509
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
var pdbuf = pd.toBuffer();
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha256');
|
||||
paypro.set('pki_data', x509.der);
|
||||
paypro.sign(x509.priv);
|
||||
x509.sig1 = paypro.get('signature');
|
||||
x509.sig1.length.should.be.greaterThan(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -263,6 +364,7 @@ describe('PayPro', function() {
|
|||
describe('#verify', function() {
|
||||
|
||||
it('should verify a signed payment request', function() {
|
||||
// SIN
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
@ -276,6 +378,19 @@ describe('PayPro', function() {
|
|||
paypro.sign(key);
|
||||
var verify = paypro.verify();
|
||||
verify.should.equal(true);
|
||||
|
||||
// X509
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
var pdbuf = pd.toBuffer();
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha256');
|
||||
paypro.set('signature', x509.sig1); // sig buffer
|
||||
paypro.set('pki_data', x509.der); // contains one or more x509 certs
|
||||
var verify = paypro.verify();
|
||||
verify.should.equal(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -319,4 +434,115 @@ describe('PayPro', function() {
|
|||
|
||||
});
|
||||
|
||||
describe('#x509+sha256Sign', function() {
|
||||
it('should sign assuming pki_type is x509+sha256', function() {
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha256');
|
||||
paypro.set('pki_data', x509.der);
|
||||
|
||||
var sig = paypro.x509Sign(x509.priv);
|
||||
paypro.set('signature', sig);
|
||||
|
||||
x509.sig2 = paypro.get('signature');
|
||||
x509.sig2.length.should.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#x509+sha256Verify', function() {
|
||||
it('should verify assuming pki_type is x509+sha256', function() {
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha256');
|
||||
|
||||
paypro.set('signature', x509.sig2); // sig buffer
|
||||
paypro.set('pki_data', x509.der); // contains one or more x509 certs
|
||||
|
||||
var verify = paypro.x509Verify();
|
||||
verify.should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#x509+sha1Sign', function() {
|
||||
it('should sign assuming pki_type is x509+sha1', function() {
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha1');
|
||||
paypro.set('pki_data', x509.der);
|
||||
|
||||
var sig = paypro.x509Sign(x509.priv);
|
||||
paypro.set('signature', sig);
|
||||
|
||||
x509.sig3 = paypro.get('signature');
|
||||
x509.sig3.length.should.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#x509+sha1Verify', function() {
|
||||
it('should verify assuming pki_type is x509+sha1', function() {
|
||||
var pd = new PayPro.PaymentDetails();
|
||||
pd.set('time', 0);
|
||||
|
||||
var pdbuf = pd.toBuffer();
|
||||
|
||||
var paypro = new PayPro();
|
||||
paypro.makePaymentRequest();
|
||||
|
||||
paypro.set('serialized_payment_details', pdbuf);
|
||||
paypro.set('pki_type', 'x509+sha1');
|
||||
|
||||
paypro.set('signature', x509.sig3); // sig buffer
|
||||
paypro.set('pki_data', x509.der); // contains one or more x509 certs
|
||||
|
||||
var verify = paypro.x509Verify();
|
||||
verify.should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#PEMtoDER', function() {
|
||||
it('should convert a PEM cert to DER', function() {
|
||||
var paypro = new PayPro();
|
||||
var der1 = paypro._PEMtoDERParam(x509.pem.toString(), 'CERTIFICATE').map(function(der) {
|
||||
return der.toString('hex');
|
||||
});
|
||||
der1 = der1[0];
|
||||
var der2 = x509.der.toString('hex');
|
||||
der1.should.equal(der2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DERtoPEM', function() {
|
||||
it('convert a DER cert to PEM', function() {
|
||||
var paypro = new PayPro();
|
||||
var pem1 = paypro._DERtoPEM(x509.der, 'CERTIFICATE');
|
||||
//var KJUR = require('jsrsasign');
|
||||
//var pem2 = KJUR.asn1.ASN1Util.getPEMStringFromHex(x509.der.toString('hex'), 'CERTIFICATE');
|
||||
var pem2 = x509.pem.toString();
|
||||
pem1 = pem1.replace(/\s+/g, '');
|
||||
pem2 = pem2.replace(/\s+/g, '');
|
||||
pem1.should.equal(pem2);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue