Ryan X. Charles
11 years ago
13 changed files with 4543 additions and 230 deletions
@ -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; |
|||
} |
@ -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; |
|||
} |
|||
|
|||
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(); |
|||
var Message = Message || require('./Message'); |
|||
|
|||
if (typeof v.toBuffer !== 'undefined') { |
|||
var maybebuf = v.toBuffer(); |
|||
return Buffer.isBuffer(maybebuf) ? maybebuf : new Buffer(new Uint8Array(maybebuf)); |
|||
} |
|||
var RootCerts = require('./common/RootCerts'); |
|||
|
|||
return v; |
|||
}; |
|||
var PayPro = require('./common/PayPro'); |
|||
|
|||
PayPro.prototype.setObj = function(obj) { |
|||
for (var key in obj) { |
|||
if (obj.hasOwnProperty(key)) { |
|||
var val = obj[key]; |
|||
this.message.set(key, val); |
|||
} |
|||
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(); |
|||
|
|||
var trusted = [].concat(pki_data).every(function(cert) { |
|||
var der = cert.toString('hex'); |
|||
var pem = self._DERtoPEM(der, 'CERTIFICATE'); |
|||
return RootCerts.isTrusted(pem); |
|||
}); |
|||
|
|||
if (!trusted) { |
|||
// XXX Figure out what to do here
|
|||
// throw new Error('Unstrusted certificate.');
|
|||
} |
|||
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; |
|||
var signature = crypto.createSign('RSA-' + type); |
|||
var buf = this.serializeForSig(); |
|||
signature.update(buf); |
|||
var sig = signature.sign(key); |
|||
return sig; |
|||
}; |
|||
|
|||
PayPro.prototype.sign = function(key) { |
|||
if (this.messageType !== 'PaymentRequest') |
|||
throw new Error('Signing can only be performed on a PaymentRequest'); |
|||
|
|||
PayPro.prototype.x509Verify = function() { |
|||
var self = this; |
|||
var crypto = require('crypto'); |
|||
var pki_type = this.get('pki_type'); |
|||
var sig = this.get('signature'); |
|||
var pki_data = this.get('pki_data'); |
|||
var details = this.get('serialized_payment_details'); |
|||
var buf = this.serializeForSig(); |
|||
var type = pki_type.split('+')[1].toUpperCase(); |
|||
|
|||
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 verifier = crypto.createVerify('RSA-' + type); |
|||
verifier.update(buf); |
|||
|
|||
var pki_type = this.get('pki_type'); |
|||
return [].concat(pki_data).every(function(cert) { |
|||
var der = cert.toString('hex'); |
|||
var pem = self._DERtoPEM(der, 'CERTIFICATE'); |
|||
|
|||
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 buf = this.serializeForSig(); |
|||
return Message.sign(buf, key); |
|||
}; |
|||
if (!RootCerts.isTrusted(pem)) { |
|||
// XXX Figure out what to do here
|
|||
// throw new Error('Unstrusted certificate.');
|
|||
} |
|||
|
|||
//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); |
|||
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
@ -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----- |
Loading…
Reference in new issue