From d941ed4438b2cdca59f2e02bc9f92bcd9fc83d11 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 7 Jan 2015 13:19:24 -0300 Subject: [PATCH 01/68] Bump package version to 0.8.6 --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index 7fd28d7..ac4c444 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "bitcore", "main": "browser/bitcore.min.js", - "version": "0.8.5", + "version": "0.8.6", "homepage": "http://bitcore.io", "authors": [ "BitPay, Inc." diff --git a/package.json b/package.json index 6ac950f..ca724e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitcore", - "version": "0.8.5", + "version": "0.8.6", "description": "A pure and powerful JavaScript Bitcoin library.", "author": "BitPay ", "main": "index.js", From 9d4056449480b19fb312e9018666b8447f4e1b97 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 7 Jan 2015 19:45:50 -0300 Subject: [PATCH 02/68] adding zuul --- .travis.yml | 4 ++++ .zuul.yml | 10 ++++++++++ package.json | 5 +++-- test/transaction/sighash.js | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 .zuul.yml diff --git a/.travis.yml b/.travis.yml index 85c1de6..f928bdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,7 @@ install: - npm install after_script: - gulp coveralls +env: + global: + - SAUCE_USERNAME=maraoz + - SAUCE_ACCESS_KEY=30055bf8-2def-4e6a-8edd-4adb9fd1de66 diff --git a/.zuul.yml b/.zuul.yml new file mode 100644 index 0000000..15bb7a8 --- /dev/null +++ b/.zuul.yml @@ -0,0 +1,10 @@ +ui: mocha-bdd +browsers: + - name: chrome + version: latest + platform: Windows XP + - name: ie + version: latest + platform: Windows XP +browserify: + - transform: brfs diff --git a/package.json b/package.json index ca724e5..33febb8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "index.js", "scripts": { "lint": "gulp lint", - "test": "gulp test", + "test": "gulp test && ./node_modules/zuul/bin/zuul -- test/*.js", "coverage": "gulp coverage", "build": "gulp", "postinstall": "node ./lib/errors/build.js" @@ -118,7 +118,8 @@ "plato": "^1.3.0", "run-sequence": "^1.0.2", "sinon": "^1.12.2", - "through2": "=0.6.3" + "through2": "=0.6.3", + "zuul": "1.16.3" }, "license": "MIT" } diff --git a/test/transaction/sighash.js b/test/transaction/sighash.js index e2b9c88..9ee89c8 100644 --- a/test/transaction/sighash.js +++ b/test/transaction/sighash.js @@ -2,6 +2,8 @@ var buffer = require('buffer'); +var chai = require('chai'); +var should = chai.should(); var Script = require('../../lib/script'); var Transaction = require('../../lib/transaction'); var sighash = require('../../lib/transaction/sighash'); From b6da2e87be46e75402537c5b1b5245f591708ac0 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 8 Jan 2015 01:51:17 -0500 Subject: [PATCH 03/68] Export messages so that they can be extended from another module. --- lib/transport/messages.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/transport/messages.js b/lib/transport/messages.js index 7503d45..8817463 100644 --- a/lib/transport/messages.js +++ b/lib/transport/messages.js @@ -155,7 +155,9 @@ Message.prototype.serialize = function(network) { message.put(payload); return message.buffer(); -} +}; + +module.exports.Message = Message; /** * Version Message From e57d02c03cccc9fe2e0276c47b534715e505a2b7 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 8 Jan 2015 10:57:46 -0300 Subject: [PATCH 04/68] Use define immutable helper --- lib/address.js | 17 ++++------------- lib/blockheader.js | 1 + lib/hdprivatekey.js | 6 +++--- lib/hdpublickey.js | 5 ++--- lib/opcode.js | 6 +++--- lib/privatekey.js | 18 +++++------------- lib/publickey.js | 18 ++++-------------- lib/transaction/input/input.js | 1 + lib/transaction/output.js | 2 ++ lib/transaction/transaction.js | 1 + 10 files changed, 26 insertions(+), 49 deletions(-) diff --git a/lib/address.js b/lib/address.js index 835f0ba..4ddcd21 100644 --- a/lib/address.js +++ b/lib/address.js @@ -74,19 +74,10 @@ function Address(data, network, type) { info.network = info.network || Networks.get(network) || Networks.defaultNetwork; info.type = info.type || type || Address.PayToPublicKeyHash; - Object.defineProperty(this, 'hashBuffer', { - configurable: false, - value: info.hashBuffer - }); - - Object.defineProperty(this, 'network', { - configurable: false, - value: info.network - }); - - Object.defineProperty(this, 'type', { - configurable: false, - value: info.type + JSUtil.defineImmutable(this, { + hashBuffer: info.hashBuffer, + network: info.network, + type: info.type }); return this; diff --git a/lib/blockheader.js b/lib/blockheader.js index 06e100f..80ad727 100644 --- a/lib/blockheader.js +++ b/lib/blockheader.js @@ -215,6 +215,7 @@ BlockHeader.prototype._getHash = function hash() { var idProperty = { configurable: false, writeable: false, + enumerable: true, /** * @returns {string} - The big endian hash buffer of the header */ diff --git a/lib/hdprivatekey.js b/lib/hdprivatekey.js index 3026aa4..8e40411 100644 --- a/lib/hdprivatekey.js +++ b/lib/hdprivatekey.js @@ -358,9 +358,9 @@ HDPrivateKey.prototype._buildFromBuffers = function(arg) { /* jshint maxstatements: 20 */ HDPrivateKey._validateBufferArguments(arg); - Object.defineProperty(this, '_buffers', { - configurable: false, - value: arg + + JSUtil.defineImmutable(this, { + _buffers: arg }); var sequence = [ diff --git a/lib/hdpublickey.js b/lib/hdpublickey.js index 323b71c..721b18a 100644 --- a/lib/hdpublickey.js +++ b/lib/hdpublickey.js @@ -297,9 +297,8 @@ HDPublicKey.prototype._buildFromBuffers = function (arg) { HDPublicKey._validateBufferArguments(arg); - Object.defineProperty(this, '_buffers', { - configurable: false, - value: arg + JSUtil.defineImmutable(this, { + _buffers: arg }); var sequence = [ diff --git a/lib/opcode.js b/lib/opcode.js index 62a0c51..9e4cfe3 100644 --- a/lib/opcode.js +++ b/lib/opcode.js @@ -3,6 +3,7 @@ var _ = require('lodash'); var $ = require('./util/preconditions'); var BufferUtil = require('./util/buffer'); +var JSUtil = require('./util/js'); function Opcode(num) { if (!(this instanceof Opcode)) { @@ -19,9 +20,8 @@ function Opcode(num) { throw new TypeError('Unrecognized num type: "' + typeof(num) + '" for Opcode'); } - Object.defineProperty(this, 'num', { - configurable: false, - value: value + JSUtil.defineImmutable(this, { + num: value }); return this; diff --git a/lib/privatekey.js b/lib/privatekey.js index ac49996..72620f9 100644 --- a/lib/privatekey.js +++ b/lib/privatekey.js @@ -57,23 +57,15 @@ var PrivateKey = function PrivateKey(data, network) { throw new TypeError('Must specify the network ("livenet" or "testnet")'); } - Object.defineProperty(this, 'bn', { - configurable: false, - value: info.bn - }); - - Object.defineProperty(this, 'compressed', { - configurable: false, - value: info.compressed - }); - - Object.defineProperty(this, 'network', { - configurable: false, - value: info.network + JSUtil.defineImmutable(this, { + bn: info.bn, + compressed: info.compressed, + network: info.network }); Object.defineProperty(this, 'publicKey', { configurable: false, + enumerable: true, get: this.toPublicKey.bind(this) }); diff --git a/lib/publickey.js b/lib/publickey.js index 59afd0a..a5d5e23 100644 --- a/lib/publickey.js +++ b/lib/publickey.js @@ -52,23 +52,13 @@ var PublicKey = function PublicKey(data, extra) { // validation info.point.validate(); - Object.defineProperty(this, 'point', { - configurable: false, - value: info.point - }); - - Object.defineProperty(this, 'compressed', { - configurable: false, - value: info.compressed - }); - - Object.defineProperty(this, 'network', { - configurable: false, - value: info.network || Network.defaultNetwork + JSUtil.defineImmutable(this, { + point: info.point, + compressed: info.compressed, + network: info.network || Network.defaultNetwork }); return this; - }; /** diff --git a/lib/transaction/input/input.js b/lib/transaction/input/input.js index 73041f7..915f718 100644 --- a/lib/transaction/input/input.js +++ b/lib/transaction/input/input.js @@ -22,6 +22,7 @@ function Input(params) { Object.defineProperty(Input.prototype, 'script', { configurable: false, writeable: false, + enumerable: true, get: function() { if (!this._script) { this._script = new Script(this._scriptBuffer); diff --git a/lib/transaction/output.js b/lib/transaction/output.js index 9b31f66..0d48c44 100644 --- a/lib/transaction/output.js +++ b/lib/transaction/output.js @@ -20,6 +20,7 @@ function Output(params) { Object.defineProperty(Output.prototype, 'script', { configurable: false, writeable: false, + enumerable: true, get: function() { if (!this._script) { this._script = new Script(this._scriptBuffer); @@ -31,6 +32,7 @@ Object.defineProperty(Output.prototype, 'script', { Object.defineProperty(Output.prototype, 'satoshis', { configurable: false, writeable: true, + enumerable: true, get: function() { return this._satoshis.toNumber(); }, diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 3a1f833..b86ace0 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -81,6 +81,7 @@ Transaction.shallowCopy = function(transaction) { var hashProperty = { configurable: false, writeable: false, + enumerable: true, get: function() { return new BufferReader(this._getHash()).readReverse().toString('hex'); } From 185126323297876794e44d1b7a3205d1376fcb5b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 8 Jan 2015 11:16:13 -0300 Subject: [PATCH 05/68] add platforms for zuul --- .zuul.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.zuul.yml b/.zuul.yml index 15bb7a8..d89560c 100644 --- a/.zuul.yml +++ b/.zuul.yml @@ -1,10 +1,10 @@ ui: mocha-bdd browsers: - name: chrome - version: latest - platform: Windows XP + version: 27..latest - name: ie version: latest - platform: Windows XP + - name: iphone + version: 6.1 browserify: - transform: brfs From 27f8370186c6772b67660b72ef26bcd51f80f601 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 8 Jan 2015 12:13:30 -0300 Subject: [PATCH 06/68] set specific zuul platforms --- .zuul.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.zuul.yml b/.zuul.yml index d89560c..c56d3e2 100644 --- a/.zuul.yml +++ b/.zuul.yml @@ -1,10 +1,12 @@ ui: mocha-bdd browsers: - name: chrome - version: 27..latest + version: 30..latest + - name: firefox + version: 30..latest - name: ie version: latest - - name: iphone - version: 6.1 + - name: safari + version: latest browserify: - transform: brfs From 05c7f641c1e24aaa8451cd23a40273c17818a56b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 8 Jan 2015 12:35:05 -0300 Subject: [PATCH 07/68] add saucelabs badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3cbd2b9..7aa5da0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Bitcore [![NPM Package](https://img.shields.io/npm/v/bitcore.svg?style=flat-square)](https://www.npmjs.org/package/bitcore) [![Build Status](https://img.shields.io/travis/bitpay/bitcore.svg?branch=master&style=flat-square)](https://travis-ci.org/bitpay/bitcore) [![Coverage Status](https://img.shields.io/coveralls/bitpay/bitcore.svg?style=flat-square)](https://coveralls.io/r/bitpay/bitcore) +[![Sauce Test Status](https://saucelabs.com/browser-matrix/maraoz.svg)](https://saucelabs.com/u/maraoz) A pure and powerful JavaScript Bitcoin library. From a996b465fc6283f9cbbe363e4a07536e849ea6b4 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 8 Jan 2015 12:39:13 -0300 Subject: [PATCH 08/68] add saucelabs badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7aa5da0..9554abf 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Bitcore [![NPM Package](https://img.shields.io/npm/v/bitcore.svg?style=flat-square)](https://www.npmjs.org/package/bitcore) [![Build Status](https://img.shields.io/travis/bitpay/bitcore.svg?branch=master&style=flat-square)](https://travis-ci.org/bitpay/bitcore) [![Coverage Status](https://img.shields.io/coveralls/bitpay/bitcore.svg?style=flat-square)](https://coveralls.io/r/bitpay/bitcore) + [![Sauce Test Status](https://saucelabs.com/browser-matrix/maraoz.svg)](https://saucelabs.com/u/maraoz) A pure and powerful JavaScript Bitcoin library. From 66ed95034336d11c4da191c8292b017c03035948 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 8 Jan 2015 11:14:46 -0500 Subject: [PATCH 09/68] Adjust .jshintrc to allow multiline EOL escaping --- .jshintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.jshintrc b/.jshintrc index 82597a3..1d70b69 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,6 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line + "multistr": true // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", From 53a9a80e0d0b25c59e2ce8b9f4fa811af28cc801 Mon Sep 17 00:00:00 2001 From: Trevin Hofmann Date: Thu, 8 Jan 2015 10:55:28 -0600 Subject: [PATCH 10/68] Add version member to bitcore object var bitcore = require('bitcore'); console.log(bitcore.version); // prints 'v0.8.6' --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index e72952c..0c71f6a 100644 --- a/index.js +++ b/index.js @@ -55,3 +55,6 @@ bitcore.transport = require('./lib/transport'); // Internal usage, exposed for testing/advanced tweaking bitcore._HDKeyCache = require('./lib/hdkeycache'); + +// module information +bitcore.version = 'v'+require('./package.json').version; From fe86abc09352d78a1ed47ec13deffedd3abefb2b Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 5 Jan 2015 12:32:40 -0300 Subject: [PATCH 11/68] Add `change` when serializing transaction --- lib/address.js | 19 +++++++++++++++++++ lib/transaction/transaction.js | 7 +++++++ test/address.js | 2 +- test/transaction/transaction.js | 10 ++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/address.js b/lib/address.js index 96d1a06..221fd96 100644 --- a/lib/address.js +++ b/lib/address.js @@ -112,6 +112,8 @@ Address.prototype._classifyArguments = function(data, network, type) { return Address._transformScript(data, network); } else if (typeof(data) === 'string') { return Address._transformString(data, network, type); + } else if (_.isObject(data)) { + return Address._transformObject(data); } else { throw new TypeError('First argument is an unrecognized data format.'); } @@ -139,6 +141,23 @@ Address._transformHash = function(hash){ return info; }; +/** + * Deserializes an address serialized through `Address#toObject()` + * @param {Object} data + * @param {string} data.hash - the hash that this address encodes + * @param {string} data.type - either 'pubkeyhash' or 'scripthash' + * @param {Network=} data.network - the name of the network associated + * @return {Address} + */ +Address._transformObject = function(data) { + $.checkArgument(data.hash, 'Must provide a `hash` property'); + $.checkArgument(data.type, 'Must provide a `type` property'); + data.hashBuffer = new Buffer(data.hash, 'hex'); + data.network = Networks.get(data.network) || Networks.defaultNetwork; + + return data; +}; + /** * Internal function to discover the network and type based on the first data byte * diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 5370e25..2031094 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -202,6 +202,9 @@ Transaction.prototype.fromJSON = function(json) { outputs.forEach(function(output) { self.outputs.push(Output.fromJSON(output)); }); + if (json.change) { + this.change(json.change); + } this.version = json.version; this.nLockTime = json.nLockTime; return this; @@ -217,6 +220,7 @@ Transaction.prototype.toObject = function toObject() { outputs.push(output.toObject()); }); return { + change: this._change ? this._change.toObject() : undefined, version: this.version, inputs: inputs, outputs: outputs, @@ -232,6 +236,9 @@ Transaction.prototype.fromObject = function(transaction) { _.each(transaction.outputs, function(output) { self.addOutput(new Output(output)); }); + if (transaction.change) { + this.change(transaction.change); + } this.nLockTime = transaction.nLockTime; this.version = transaction.version; }; diff --git a/test/address.js b/test/address.js index b75c7ae..063871b 100644 --- a/test/address.js +++ b/test/address.js @@ -233,7 +233,7 @@ describe('Address', function() { it('should error because of unrecognized data format', function() { (function() { return new Address(new Error()); - }).should.throw('First argument is an unrecognized data format.'); + }).should.throw(bitcore.errors.InvalidArgument); }); it('should error because of incorrect format for pubkey hash', function() { diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 742be1e..8adb53b 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -213,6 +213,16 @@ describe('Transaction', function() { }); }); + describe('serialization', function() { + it('stores the change address correctly', function() { + var serialized = new Transaction() + .change(changeAddress) + .toObject(); + var deserialized = new Transaction(serialized); + expect(deserialized._change.toString()).to.equal(changeAddress); + }); + }); + describe('checked serialize', function() { it('fails if no change address was set', function() { var transaction = new Transaction() From d053599fd248b0d3d2fb10beb1a228d7697b5f06 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 5 Jan 2015 12:32:40 -0300 Subject: [PATCH 12/68] Improve test coverage --- lib/transaction/transaction.js | 4 +++- test/address.js | 10 ++++++++++ test/transaction/transaction.js | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index a76f396..38568fe 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -49,6 +49,8 @@ function Transaction(serialized) { return Transaction.shallowCopy(serialized); } else if (util.isHexa(serialized)) { this.fromString(serialized); + } else if (util.isValidJSON(serialized)) { + this.fromJSON(serialized); } else if (bufferUtil.isBuffer(serialized)) { this.fromBuffer(serialized); } else if (_.isObject(serialized)) { @@ -221,7 +223,7 @@ Transaction.prototype.toObject = function toObject() { outputs.push(output.toObject()); }); return { - change: this._change ? this._change.toObject() : undefined, + change: this._change ? this._change.toString() : undefined, version: this.version, inputs: inputs, outputs: outputs, diff --git a/test/address.js b/test/address.js index 82d8189..17218b8 100644 --- a/test/address.js +++ b/test/address.js @@ -456,6 +456,16 @@ describe('Address', function() { }); }); + it('throws an error if it couldn\'t instantiate', function() { + expect(function() { + return new Address(1); + }).to.throw(TypeError); + }); + it('can roundtrip from/to a object', function() { + var address = new Address(P2SHLivenet[0]); + expect(new Address(address.toObject()).toString()).to.equal(P2SHLivenet[0]); + }); + describe('creating a P2SH address from public keys', function() { var public1 = '02da5798ed0c055e31339eb9b5cef0d3c0ccdec84a62e2e255eb5c006d4f3e7f5b'; diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 2a36acf..9a4ad0e 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -243,6 +243,18 @@ describe('Transaction', function() { }).to.throw(errors.Transaction.FeeError); }); }); + + describe('to and from JSON', function() { + it('takes a string that is a valid JSON and deserializes from it', function() { + var transaction = new Transaction(); + expect(new Transaction(transaction.toJSON()).serialize()).to.equal(transaction.serialize()); + }); + it('serializes the `change` information', function() { + var transaction = new Transaction(); + transaction.change(changeAddress); + expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString()); + }); + }); }); var tx_empty_hex = '01000000000000000000'; From dc6ff322902d1cc6643deecfd9654daaedecf6fa Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 6 Jan 2015 09:26:14 -0300 Subject: [PATCH 13/68] Make serialization roundtrip recover info about inputs --- lib/transaction/input/multisigscripthash.js | 45 ++++++++++++++++++++- lib/transaction/transaction.js | 12 ++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/transaction/input/multisigscripthash.js b/lib/transaction/input/multisigscripthash.js index 1a36a14..d56e1ad 100644 --- a/lib/transaction/input/multisigscripthash.js +++ b/lib/transaction/input/multisigscripthash.js @@ -9,12 +9,13 @@ var $ = require('../../util/preconditions'); var Script = require('../../script'); var Signature = require('../../crypto/signature'); var Sighash = require('../sighash'); +var PublicKey = require('../../publickey'); var BufferUtil = require('../../util/buffer'); /** * @constructor */ -function MultiSigScriptHashInput(input, pubkeys, threshold) { +function MultiSigScriptHashInput(input, pubkeys, threshold, signatures) { Input.apply(this, arguments); var self = this; this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); }); @@ -27,10 +28,50 @@ function MultiSigScriptHashInput(input, pubkeys, threshold) { }); this.threshold = threshold; // Empty array of signatures - this.signatures = new Array(this.publicKeys.length); + this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length); } inherits(MultiSigScriptHashInput, Input); +MultiSigScriptHashInput.prototype.toObject = function() { + var obj = Input.prototype.toObject.apply(this, arguments); + obj.threshold = this.threshold; + obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); }); + obj.signatures = this._serializeSignatures(); + return obj; +}; + +MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) { + return _.map(signatures, function(signature) { + if (!signature) { + return signature; + } + return { + publicKey: new PublicKey(signature.publicKey), + prevTxId: signature.txId, + outputIndex: signature.outputIndex, + inputIndex: signature.inputIndex, + signature: Signature.fromString(signature.signature), + sigtype: signature.sigtype + }; + }); +}; + +MultiSigScriptHashInput.prototype._serializeSignatures = function() { + return _.map(this.signatures, function(signature) { + if (!signature) { + return signature; + } + return { + publicKey: signature.publicKey.toString(), + prevTxId: signature.txId, + outputIndex: signature.outputIndex, + inputIndex: signature.inputIndex, + signature: signature.signature.toString(), + sigtype: signature.sigtype + }; + }); +}; + MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) { $.checkState(this.output instanceof Output); sigtype = sigtype || Signature.SIGHASH_ALL; diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 38568fe..f7c73fb 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -234,6 +234,18 @@ Transaction.prototype.toObject = function toObject() { Transaction.prototype.fromObject = function(transaction) { var self = this; _.each(transaction.inputs, function(input) { + if (input.output.script) { + input.output.script = new Script(input.output.script); + if (input.output.script.isPublicKeyHashOut()) { + self.addInput(new Input.PublicKeyHash(input)); + return; + } else if (input.output.script.isScriptHashOut() && input.publicKeys && input.threshold) { + self.addInput(new Input.MultiSigScriptHash( + input, input.publicKeys, input.threshold, input.signatures + )); + return; + } + } self.addInput(new Input(input)); }); _.each(transaction.outputs, function(output) { From ff82ccec7148eee9b6b8bf451bad91f9c5478810 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Thu, 8 Jan 2015 16:18:20 -0300 Subject: [PATCH 14/68] Return undefined instead of a null signature --- lib/transaction/input/multisigscripthash.js | 4 ++-- lib/transaction/unspentoutput.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/transaction/input/multisigscripthash.js b/lib/transaction/input/multisigscripthash.js index d56e1ad..e8a6286 100644 --- a/lib/transaction/input/multisigscripthash.js +++ b/lib/transaction/input/multisigscripthash.js @@ -43,7 +43,7 @@ MultiSigScriptHashInput.prototype.toObject = function() { MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) { return _.map(signatures, function(signature) { if (!signature) { - return signature; + return undefined; } return { publicKey: new PublicKey(signature.publicKey), @@ -59,7 +59,7 @@ MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) MultiSigScriptHashInput.prototype._serializeSignatures = function() { return _.map(this.signatures, function(signature) { if (!signature) { - return signature; + return undefined; } return { publicKey: signature.publicKey.toString(), diff --git a/lib/transaction/unspentoutput.js b/lib/transaction/unspentoutput.js index f8aee61..f02dc79 100644 --- a/lib/transaction/unspentoutput.js +++ b/lib/transaction/unspentoutput.js @@ -98,7 +98,7 @@ UnspentOutput.prototype.toJSON = function() { */ UnspentOutput.prototype.toObject = function() { return { - address: this.address.toString(), + address: this.address ? this.address.toString() : undefined, txid: this.txId, vout: this.outputIndex, scriptPubKey: this.script.toBuffer().toString('hex'), From d99d1c9cc240acb3a6c5be1750225d90ee1b2e2b Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Thu, 8 Jan 2015 17:41:15 -0300 Subject: [PATCH 15/68] Add tests for serialization roundtrip of inputs --- .jshintrc | 2 +- test/transaction/transaction.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index 1d70b69..40fd8c6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,7 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line - "multistr": true // Allow use of multiline EOL escaping + "multistr": true, // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 9a4ad0e..00b4f57 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -222,6 +222,13 @@ describe('Transaction', function() { var deserialized = new Transaction(serialized); expect(deserialized._change.toString()).to.equal(changeAddress); }); + it('can avoid checked serialize', function() { + var transaction = new Transaction() + .from(simpleUtxoWith1BTC) + .to(fromAddress, 1); + expect(function() { return transaction.serialize(); }).to.throw(); + expect(function() { return transaction.serialize(true); }).to.not.throw(); + }); }); describe('checked serialize', function() { @@ -255,6 +262,30 @@ describe('Transaction', function() { expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString()); }); }); + + describe('serialization of inputs', function() { + it('can serialize and deserialize a P2PKH input', function() { + var transaction = new Transaction() + .from(simpleUtxoWith1BTC); + var deserialized = new Transaction(transaction.toObject()); + expect(deserialized.inputs[0] instanceof Transaction.Input.PublicKeyHash).to.equal(true); + }); + it('can serialize and deserialize a P2SH input', function() { + var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976'; + var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890'; + var public1 = new PrivateKey(private1).publicKey; + var public2 = new PrivateKey(private2).publicKey; + var transaction = new Transaction() + .from({ + txId: private1, + outputIndex: 0, + script: Script.buildScriptHashOut(Script.buildMultisigOut([public1, public2], 2)), + satoshis: 10000 + }, [public1, public2], 2); + var deserialized = new Transaction(transaction.toObject()); + expect(deserialized.inputs[0] instanceof Transaction.Input.MultiSigScriptHash).to.equal(true); + }); + }); }); var tx_empty_hex = '01000000000000000000'; From 0f73c3f7a38a04c3865a3c6fbf5689771cce168a Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Thu, 8 Jan 2015 16:38:43 -0300 Subject: [PATCH 16/68] Throw error if dust amount is detected --- .jshintrc | 2 +- lib/errors/spec.js | 3 +++ lib/transaction/transaction.js | 15 +++++++++++++++ test/transaction/deserialize.js | 4 ++-- test/transaction/transaction.js | 10 ++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.jshintrc b/.jshintrc index 1d70b69..40fd8c6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,7 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line - "multistr": true // Allow use of multiline EOL escaping + "multistr": true, // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", diff --git a/lib/errors/spec.js b/lib/errors/spec.js index a3e42bc..70fbeac 100644 --- a/lib/errors/spec.js +++ b/lib/errors/spec.js @@ -61,6 +61,9 @@ module.exports = [{ }, { name: 'UnableToVerifySignature', message: format('Unable to verify signature: {0}') + }, { + name: 'DustOutputs', + message: format('Dust amount detected in one output') }, { name: 'FeeError', message: format('Fees are not correctly set {0}'), diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index a76f396..54ac4bc 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -126,6 +126,9 @@ Transaction.prototype.checkedSerialize = Transaction.prototype.toString = functi throw new errors.Transaction.FeeError(feeError); } } + if (this._hasDustOutputs()) { + throw new errors.Transaction.DustOutputs(); + } return this.uncheckedSerialize(); }; @@ -143,6 +146,18 @@ Transaction.prototype._validateChange = function() { } }; +Transaction.DUST_AMOUNT = 5460; + +Transaction.prototype._hasDustOutputs = function() { + var output; + for (output in this.outputs) { + if (this.outputs[output].satoshis < Transaction.DUST_AMOUNT) { + return true; + } + } + return false; +}; + Transaction.prototype.inspect = function() { return ''; }; diff --git a/test/transaction/deserialize.js b/test/transaction/deserialize.js index 499a151..28993d9 100644 --- a/test/transaction/deserialize.js +++ b/test/transaction/deserialize.js @@ -12,7 +12,7 @@ describe('Transaction deserialization', function() { vectors_valid.forEach(function(vector) { if (vector.length > 1) { var hexa = vector[1]; - Transaction(hexa).serialize().should.equal(hexa); + Transaction(hexa).serialize(true).should.equal(hexa); index++; } }); @@ -22,7 +22,7 @@ describe('Transaction deserialization', function() { vectors_invalid.forEach(function(vector) { if (vector.length > 1) { var hexa = vector[1]; - Transaction(hexa).serialize().should.equal(hexa); + Transaction(hexa).serialize(true).should.equal(hexa); index++; } }); diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 2a36acf..c42ae24 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -242,6 +242,16 @@ describe('Transaction', function() { return transaction.serialize(); }).to.throw(errors.Transaction.FeeError); }); + it('fails if a dust transaction is created', function() { + var transaction = new Transaction() + .from(simpleUtxoWith1BTC) + .to(toAddress, 1) + .change(changeAddress) + .sign(privateKey); + expect(function() { + return transaction.serialize(); + }).to.throw(errors.Transaction.DustOutputs); + }); }); }); From fd88637a3130531e78e12ea9404e0cf4c1e5573d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 8 Jan 2015 19:19:52 -0300 Subject: [PATCH 17/68] remove zuul from travis --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 33febb8..0bad982 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "index.js", "scripts": { "lint": "gulp lint", - "test": "gulp test && ./node_modules/zuul/bin/zuul -- test/*.js", + "test": "gulp test", "coverage": "gulp coverage", "build": "gulp", "postinstall": "node ./lib/errors/build.js" From b38f7fa319eb1da7f8fe18c6c1076fc1e18f4150 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 8 Jan 2015 17:43:59 -0500 Subject: [PATCH 18/68] Added getID to PublicKey - Tests in BloomFilter in [bitcoin core](https://github.com/bitcoin/bitcoin/blob/master/src/test/bloom_tests.cpp#L85) use the CPubKey.GetID as input into the BloomFilter - The hash is calculated when generating an Address however the hash itself is not currently available --- lib/publickey.js | 10 ++++++++++ test/publickey.js | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/publickey.js b/lib/publickey.js index a5d5e23..0bba32a 100644 --- a/lib/publickey.js +++ b/lib/publickey.js @@ -3,6 +3,7 @@ var Address = require('./address'); var BN = require('./crypto/bn'); var Point = require('./crypto/point'); +var Hash = require('./crypto/hash'); var JSUtil = require('./util/js'); var Network = require('./networks'); var _ = require('lodash'); @@ -384,6 +385,15 @@ PublicKey.prototype.toBuffer = PublicKey.prototype.toDER = function() { } }; +/* + * Will return a sha256 + ripemd160 hash of the serialized public key + * @see https://github.com/bitcoin/bitcoin/blob/master/src/pubkey.h#L141 + * @returns {Buffer} + */ +PublicKey.prototype.getID = function getID() { + return Hash.sha256ripemd160(this.toBuffer()) +} + /** * Will return an address for the public key * diff --git a/test/publickey.js b/test/publickey.js index 22f4ae4..3843f5d 100644 --- a/test/publickey.js +++ b/test/publickey.js @@ -8,6 +8,7 @@ var Point = bitcore.crypto.Point; var BN = bitcore.crypto.BN; var PublicKey = bitcore.PublicKey; var PrivateKey = bitcore.PrivateKey; +var Address = bitcore.Address; var Networks = bitcore.Networks; /* jshint maxlen: 200 */ @@ -340,6 +341,25 @@ describe('PublicKey', function() { }); + describe('hashes', function() { + + // wif private key, address + // see: https://github.com/bitcoin/bitcoin/blob/master/src/test/key_tests.cpp#L20 + var data = [ + ['5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj', '1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ'], + ['5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3', '1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ'], + ['Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw', '1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs'], + ['L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g', '1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs'] + ]; + + data.forEach(function(d){ + var publicKey = PrivateKey.fromWIF(d[0]).toPublicKey(); + var address = Address.fromString(d[1]); + address.hashBuffer.should.deep.equal(publicKey.getID()); + }); + + }); + describe('#toString', function() { it('should print this known public key', function() { From 81fa162a7fa40b97316fc4a08ff3ded9c0c467f8 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 9 Jan 2015 10:08:01 -0500 Subject: [PATCH 19/68] Fix .jshintrc and add missing semis --- .jshintrc | 2 +- lib/publickey.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.jshintrc b/.jshintrc index 1d70b69..40fd8c6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,7 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line - "multistr": true // Allow use of multiline EOL escaping + "multistr": true, // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", diff --git a/lib/publickey.js b/lib/publickey.js index 0bba32a..0ce572c 100644 --- a/lib/publickey.js +++ b/lib/publickey.js @@ -391,8 +391,8 @@ PublicKey.prototype.toBuffer = PublicKey.prototype.toDER = function() { * @returns {Buffer} */ PublicKey.prototype.getID = function getID() { - return Hash.sha256ripemd160(this.toBuffer()) -} + return Hash.sha256ripemd160(this.toBuffer()); +}; /** * Will return an address for the public key From 84cc1a004207c07f33ae0c71b5670383778b1f86 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 9 Jan 2015 10:15:48 -0500 Subject: [PATCH 20/68] Indicate internal use of getID with an underscore. --- lib/publickey.js | 4 ++-- test/publickey.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/publickey.js b/lib/publickey.js index 0ce572c..6977e1c 100644 --- a/lib/publickey.js +++ b/lib/publickey.js @@ -385,12 +385,12 @@ PublicKey.prototype.toBuffer = PublicKey.prototype.toDER = function() { } }; -/* +/** * Will return a sha256 + ripemd160 hash of the serialized public key * @see https://github.com/bitcoin/bitcoin/blob/master/src/pubkey.h#L141 * @returns {Buffer} */ -PublicKey.prototype.getID = function getID() { +PublicKey.prototype._getID = function _getID() { return Hash.sha256ripemd160(this.toBuffer()); }; diff --git a/test/publickey.js b/test/publickey.js index 3843f5d..f778b5c 100644 --- a/test/publickey.js +++ b/test/publickey.js @@ -355,7 +355,7 @@ describe('PublicKey', function() { data.forEach(function(d){ var publicKey = PrivateKey.fromWIF(d[0]).toPublicKey(); var address = Address.fromString(d[1]); - address.hashBuffer.should.deep.equal(publicKey.getID()); + address.hashBuffer.should.deep.equal(publicKey._getID()); }); }); From 26e688ae0637ee1b41cabf6866d5df412ed6cb3e Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 9 Jan 2015 16:09:36 -0300 Subject: [PATCH 21/68] Add .toScriptHashOut() to scripts - Also sort gulpfile dependencies --- gulpfile.js | 13 +++++++------ lib/script/script.js | 7 +++++++ test/transaction/transaction.js | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 0618136..ed80a78 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -32,19 +32,20 @@ 'use strict'; var gulp = require('gulp'); + +var bump = require('gulp-bump'); var coveralls = require('gulp-coveralls'); +var git = require('gulp-git'); +var gutil = require('gulp-util'); +var jsdoc2md = require('jsdoc-to-markdown'); var jshint = require('gulp-jshint'); +var mfs = require('more-fs'); var mocha = require('gulp-mocha'); +var rename = require('gulp-rename'); var runSequence = require('run-sequence'); var shell = require('gulp-shell'); var through = require('through2'); -var gutil = require('gulp-util'); -var jsdoc2md = require('jsdoc-to-markdown'); -var mfs = require('more-fs'); var uglify = require('gulp-uglify'); -var rename = require('gulp-rename'); -var bump = require('gulp-bump'); -var git = require('gulp-git'); var files = ['lib/**/*.js']; diff --git a/lib/script/script.js b/lib/script/script.js index 7785918..9eab646 100644 --- a/lib/script/script.js +++ b/lib/script/script.js @@ -715,6 +715,13 @@ Script.prototype.toAddress = function(network) { throw new Error('The script type needs to be PayToPublicKeyHash or PayToScriptHash'); }; +/** + * @return {Script} + */ +Script.prototype.toScriptHashOut = function() { + return Script.buildScriptHashOut(this); +}; + /** * Analagous to bitcoind's FindAndDelete. Find and delete equivalent chunks, * typically used with push data chunks. Note that this will find and delete diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 00b4f57..e5f2f4d 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -277,9 +277,9 @@ describe('Transaction', function() { var public2 = new PrivateKey(private2).publicKey; var transaction = new Transaction() .from({ - txId: private1, + txId: '0000', // Not relevant outputIndex: 0, - script: Script.buildScriptHashOut(Script.buildMultisigOut([public1, public2], 2)), + script: Script.buildMultisigOut([public1, public2], 2).toScriptHashOut(), satoshis: 10000 }, [public1, public2], 2); var deserialized = new Transaction(transaction.toObject()); From bdeac4e67d33cee3ad4b0ee109e5dda665b79408 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 9 Jan 2015 16:53:50 -0300 Subject: [PATCH 22/68] Add inspect method to output --- .jshintrc | 2 +- lib/transaction/output.js | 19 ++++++++---- lib/transaction/transaction.js | 2 +- test/transaction/output.js | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 test/transaction/output.js diff --git a/.jshintrc b/.jshintrc index 1d70b69..40fd8c6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,7 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line - "multistr": true // Allow use of multiline EOL escaping + "multistr": true, // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", diff --git a/lib/transaction/output.js b/lib/transaction/output.js index 0d48c44..fcbab1d 100644 --- a/lib/transaction/output.js +++ b/lib/transaction/output.js @@ -13,6 +13,9 @@ function Output(params) { return new Output(params); } if (params) { + if (JSUtil.isValidJSON(params)) { + return Output.fromJSON(params); + } return this._fromObject(params); } } @@ -34,13 +37,15 @@ Object.defineProperty(Output.prototype, 'satoshis', { writeable: true, enumerable: true, get: function() { - return this._satoshis.toNumber(); + return this._satoshis; }, set: function(num) { if (num instanceof BN) { - this._satoshis = num; + this._satoshisBN = num; + this._satoshis = num.toNumber(); } else { - this._satoshis = BN.fromNumber(num); + this._satoshisBN = BN.fromNumber(num); + this._satoshis = num; } } }); @@ -90,9 +95,13 @@ Output.prototype.setScript = function(script) { return this; }; +Output.prototype.inspect = function() { + return ''; +}; + Output.fromBufferReader = function(br) { var output = new Output(); - output._satoshis = br.readUInt64LEBN(); + output.satoshis = br.readUInt64LEBN(); var size = br.readVarintNum(); if (size !== 0) { output._scriptBuffer = br.read(size); @@ -106,7 +115,7 @@ Output.prototype.toBufferWriter = function(writer) { if (!writer) { writer = new BufferWriter(); } - writer.writeUInt64LEBN(this._satoshis); + writer.writeUInt64LEBN(this._satoshisBN); var script = this._scriptBuffer; writer.writeVarintNum(script.length); writer.write(script); diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 38568fe..c219a7c 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -666,7 +666,7 @@ Transaction.prototype.verify = function() { var valueoutbn = BN(0); for (var i = 0; i < this.outputs.length; i++) { var txout = this.outputs[i]; - var valuebn = txout._satoshis; + var valuebn = txout._satoshisBN; if (valuebn.lt(0)) { return 'transaction txout ' + i + ' negative'; } diff --git a/test/transaction/output.js b/test/transaction/output.js new file mode 100644 index 0000000..529233c --- /dev/null +++ b/test/transaction/output.js @@ -0,0 +1,54 @@ +'use strict'; + +/* jshint unused: false */ +/* jshint latedef: false */ +var should = require('chai').should(); +var expect = require('chai').expect; +var _ = require('lodash'); + +var bitcore = require('../..'); +var BN = bitcore.crypto.BN; +var BufferWriter = bitcore.encoding.BufferWriter; +var BufferReader = bitcore.encoding.BufferReader; +var Output = bitcore.Transaction.Output; +var Script = bitcore.Script; + +var errors = bitcore.errors; + +describe('Output', function() { + + var output = new Output({satoshis: 0, script: Script.empty()}); + + it('can be assigned a satoshi amount in big number', function() { + var newOutput = new Output({satoshis: new BN(100), script: Script.empty()}); + newOutput.satoshis.should.equal(100); + }); + + var expectEqualOutputs = function(a, b) { + a.satoshis.should.equal(b.satoshis); + a.script.toString().should.equal(b.script.toString()); + }; + + it('deserializes correctly a simple output', function() { + var writer = new BufferWriter(); + output.toBufferWriter(writer); + var deserialized = Output.fromBufferReader(new BufferReader(writer.toBuffer())); + expectEqualOutputs(output, deserialized); + }); + + it('roundtrips to/from object', function() { + var newOutput = new Output({satoshis: 50, script: new Script().add(0)}); + var otherOutput = new Output(newOutput.toObject()); + expectEqualOutputs(newOutput, otherOutput); + }); + + it('can set a script from a buffer', function() { + var newOutput = Output(output); + newOutput.setScript(Script().add(0).toBuffer()); + newOutput.inspect().should.equal('>'); + }); + + it('has a inspect property', function() { + output.inspect().should.equal('>'); + }); +}); From 4fba2bc86c3aaee1d3104e373ed7eb19449a1d45 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 9 Jan 2015 16:58:44 -0300 Subject: [PATCH 23/68] Drop all rpc code/docs --- docs/guide/jsonrpc.md | 44 -------- lib/transport/index.js | 3 +- lib/transport/rpc.js | 249 ----------------------------------------- test/transport/rpc.js | 62 ---------- 4 files changed, 1 insertion(+), 357 deletions(-) delete mode 100644 docs/guide/jsonrpc.md delete mode 100644 lib/transport/rpc.js delete mode 100644 test/transport/rpc.js diff --git a/docs/guide/jsonrpc.md b/docs/guide/jsonrpc.md deleted file mode 100644 index 454cb87..0000000 --- a/docs/guide/jsonrpc.md +++ /dev/null @@ -1,44 +0,0 @@ -title: JSON-RPC -description: A simple interface to connect and make RPC calls to bitcoind. ---- -# JSON-RPC - -## Description - -Bitcoind provides a direct interface to the bitcoin network and it also exposes a `JSON-RPC` API. This class will connect to a local instance of a bitcoind server and make simple or batch RPC calls to it. - -## Connection to bitcoind - -First you will need a running instance of bitcoind, setting up a username and password to connect with it. For more information about running bitcoind please refer to the [official documentation](https://en.bitcoin.it/wiki/Running_Bitcoin). - -The code for creating and configuring an instance of the RPC client looks like this: - -``` -var bitcore = require('bitcore'); -var RPC = bitcore.transport.RPC; - -var client = new RPC('username', 'password', { - host: 'localhost', - port: 18332, - secure: false, - disableAgent: true, - rejectUnauthorized: true -}); -``` - - -## Examples - -For more information please refer to the [API reference](https://en.bitcoin.it/wiki/API_reference_%28JSON-RPC%29). - -``` -var bitcore = require('bitcore'); -var blockHash = '0000000000000000045d581af7fa3b6110266ece8131424d95bf490af828be1c'; - -var client = new bitcore.transport.RPC('username', 'password'); - -client.getBlock(blockHash, function(err, block) { - // do something with the block -}); - -``` diff --git a/lib/transport/index.js b/lib/transport/index.js index 185732e..7d25662 100644 --- a/lib/transport/index.js +++ b/lib/transport/index.js @@ -5,6 +5,5 @@ module.exports = { explorers: require('./explorers'), Messages: require('./messages'), Peer: require('./peer'), - Pool: require('./pool'), - RPC: require('./rpc') + Pool: require('./pool') }; diff --git a/lib/transport/rpc.js b/lib/transport/rpc.js deleted file mode 100644 index b297ae5..0000000 --- a/lib/transport/rpc.js +++ /dev/null @@ -1,249 +0,0 @@ -'use strict'; - -var http = require('http'); -var https = require('https'); - -/** - * A JSON RPC client for bitcoind. An instances of RPC connects to a bitcoind - * server and enables simple and batch RPC calls. - * - * @example - * ```javascript - * - * var client = new RPC('user', 'pass'); - * client.getInfo(function(err, info) { - * // do something with the info - * }); - * ``` - * - * @param {String} user - username used to connect bitcoind - * @param {String} password - password used to connect bitcoind - * @param {Object} opts - Connection options: host, port, secure, disableAgent, rejectUnauthorized - * @returns {RPC} - * @constructor - */ -function RPC(user, password, opts) { - if (!(this instanceof RPC)) { - return new RPC(user, password, opts); - } - - this.user = user; - this.pass = password; - - opts = opts || {}; - this.host = opts.host || '127.0.0.1'; - this.port = opts.port || 8332; - - this.secure = typeof opts.secure === 'undefined' ? true : opts.secure; - this._client = opts.secure ? https : http; - - this.batchedCalls = null; - this.disableAgent = opts.disableAgent || false; - this.rejectUnauthorized = opts.rejectUnauthorized || false; -} - -/** - * Allows to excecute RPC calls in batch. - * - * @param {Function} batchCallback - Function that makes all calls to be excecuted in bach - * @param {Function} resultCallbak - Function to be called on result - */ -RPC.prototype.batch = function(batchCallback, resultCallback) { - this.batchedCalls = []; - batchCallback(); - this._request(this.batchedCalls, resultCallback); - this.batchedCalls = null; -} - -/** - * Internal function to make an RPC call - * - * @param {Object} request - Object to be serialized and sent to bitcoind - * @param {Function} callbak - Function to be called on result - */ -RPC.prototype._request = function(request, callback) { - var self = this; - - var request = JSON.stringify(request); - var auth = Buffer(self.user + ':' + self.pass).toString('base64'); - - var options = { - host: self.host, - path: '/', - method: 'POST', - port: self.port, - rejectUnauthorized: self.rejectUnauthorized, - agent: self.disableAgent ? false : undefined - }; - - var req = this._client.request(options, function(res) { - var buf = ''; - res.on('data', function(data) { - buf += data; - }); - - res.on('end', function() { - if (res.statusCode == 401) { - var error = new Error('bitcoin JSON-RPC connection rejected: 401 unauthorized'); - return callback(error); - } - - if (res.statusCode == 403) { - var error = new Error('bitcoin JSON-RPC connection rejected: 403 forbidden'); - return callback(error); - } - - try { - var parsedBuf = JSON.parse(buf); - } catch (e) { - return callback(e); - } - - callback(parsedBuf.error, parsedBuf); - }); - }); - - req.on('error', function(e) { - var err = new Error('Could not connect to bitcoin via RPC at host: ' + self.host + ' port: ' + self.port + ' Error: ' + e.message); - callback(err); - }); - - req.setHeader('Content-Length', request.length); - req.setHeader('Content-Type', 'application/json'); - req.setHeader('Authorization', 'Basic ' + auth); - req.write(request); - req.end(); -}; - -var callspec = { - addMultiSigAddress: '', - addNode: '', - backupWallet: '', - createMultiSig: '', - createRawTransaction: '', - decodeRawTransaction: '', - dumpPrivKey: '', - encryptWallet: '', - getAccount: '', - getAccountAddress: 'str', - getAddedNodeInfo: '', - getAddressesByAccount: '', - getBalance: 'str int', - getBestBlockHash: '', - getBlock: '', - getBlockCount: '', - getBlockHash: 'int', - getBlockNumber: '', - getBlockTemplate: '', - getConnectionCount: '', - getDifficulty: '', - getGenerate: '', - getHashesPerSec: '', - getInfo: '', - getMemoryPool: '', - getMiningInfo: '', - getNewAddress: '', - getPeerInfo: '', - getRawMemPool: '', - getRawTransaction: 'str int', - getReceivedByAccount: 'str int', - getReceivedByAddress: 'str int', - getTransaction: '', - getTxOut: 'str int bool', - getTxOutSetInfo: '', - getWork: '', - help: '', - importAddress: 'str str bool', - importPrivKey: 'str str bool', - keyPoolRefill: '', - listAccounts: 'int', - listAddressGroupings: '', - listReceivedByAccount: 'int bool', - listReceivedByAddress: 'int bool', - listSinceBlock: 'str int', - listTransactions: 'str int int', - listUnspent: 'int int', - listLockUnspent: 'bool', - lockUnspent: '', - move: 'str str float int str', - sendFrom: 'str str float int str str', - sendMany: 'str str int str', //not sure this is will work - sendRawTransaction: '', - sendToAddress: 'str float str str', - setAccount: '', - setGenerate: 'bool int', - setTxFee: 'float', - signMessage: '', - signRawTransaction: '', - stop: '', - submitBlock: '', - validateAddress: '', - verifyMessage: '', - walletLock: '', - walletPassPhrase: 'string int', - walletPassphraseChange: '', -}; - - -var slice = function(arr, start, end) { - return Array.prototype.slice.call(arr, start, end); -}; - -function generateRPCMethods(constructor, apiCalls) { - function createRPCMethod(methodName, argMap) { - return function() { - var limit = arguments.length - 1; - if (this.batchedCalls) var limit = arguments.length; - for (var i = 0; i < limit; i++) { - if (argMap[i]) arguments[i] = argMap[i](arguments[i]); - }; - if (this.batchedCalls) { - this.batchedCalls.push({ - jsonrpc: '2.0', - method: methodName, - params: slice(arguments) - }); - } else { - this._request({ - method: methodName, - params: slice(arguments, 0, arguments.length - 1) - }, arguments[arguments.length - 1]); - } - }; - }; - - var types = { - str: function(arg) { - return arg.toString(); - }, - int: function(arg) { - return parseFloat(arg); - }, - float: function(arg) { - return parseFloat(arg); - }, - bool: function(arg) { - return (arg === true || arg == '1' || arg == 'true' || arg.toString().toLowerCase() == 'true'); - }, - }; - - for (var k in apiCalls) { - if (apiCalls.hasOwnProperty(k)) { - var spec = apiCalls[k].split(' '); - for (var i = 0; i < spec.length; i++) { - if (types[spec[i]]) { - spec[i] = types[spec[i]]; - } else { - spec[i] = types.string; - } - } - var methodName = k.toLowerCase(); - constructor.prototype[k] = createRPCMethod(methodName, spec); - constructor.prototype[methodName] = constructor.prototype[k]; - } - } -} - -generateRPCMethods(RPC, callspec); - -module.exports = RPC; diff --git a/test/transport/rpc.js b/test/transport/rpc.js deleted file mode 100644 index 0b29266..0000000 --- a/test/transport/rpc.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var should = chai.should(); - -var bitcore = require('../..'); -var RPC = bitcore.transport.RPC; - -describe('RPC', function() { - it('should be able to create instance', function() { - var client = new RPC('user', 'pass'); - should.exist(client); - }); - - it('should set default config', function() { - var client = new RPC('user', 'pass'); - client.user.should.be.equal('user'); - client.pass.should.be.equal('pass'); - - client.host.should.be.equal('127.0.0.1'); - client.port.should.be.equal(8332); - client.secure.should.be.equal(true); - client.disableAgent.should.be.equal(false); - client.rejectUnauthorized.should.be.equal(false); - }); - - it('should allow setting custom host and port', function() { - var client = new RPC('user', 'pass', { - host: 'localhost', - port: 18332 - }); - - client.host.should.be.equal('localhost'); - client.port.should.be.equal(18332); - }); - - it('should honor request options', function() { - var client = new RPC('user', 'pass', { - host: 'localhost', - port: 18332, - rejectUnauthorized: true, - disableAgent: true - }); - - client._client = {}; - client._client.request = function(options, callback) { - options.host.should.be.equal('localhost'); - options.port.should.be.equal(18332); - options.rejectUnauthorized.should.be.equal(true); - options.agent.should.be.false; - return { - on: function() {}, - setHeader: function() {}, - write: function() {}, - end: function() {} - }; - }; - - client._request({}, function() {}); - }); - -}); From 2edae5564e7f5f37f1855502ca806bf483577115 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 9 Jan 2015 18:57:20 -0300 Subject: [PATCH 24/68] remove ECIES docs --- docs/guide/ecies.md | 46 --------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 docs/guide/ecies.md diff --git a/docs/guide/ecies.md b/docs/guide/ecies.md deleted file mode 100644 index c95879b..0000000 --- a/docs/guide/ecies.md +++ /dev/null @@ -1,46 +0,0 @@ -title: ECIES -description: Uses ECIES symmetric key negotiation from public keys to encrypt arbitrarily long data streams. ---- -# ECIES - -## Description - -Bitcore implements [Elliptic Curve Integrated Encryption Scheme (ECIES)](http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme), which is a public key encryption system that performs bulk encryption on data using a symmetric cipher and a random key. - -For more information refer to the [bitcore-ecies](https://github.com/bitpay/bitcore-ecies) github repo. - -## Installation - -ECIES is implemented as a separate module and you must add it to your dependencies: - -For node projects: -``` -npm install bitcore-ecies --save -``` - -For client-side projects: -``` -bower install bitcore-ecies --save -``` - -## Example - -``` -var bitcore = require('bitcore'); -var ECIES = require('bitcore-ecies'); - -var alicePrivateKey = new bitcore.PrivateKey(); -var bobPrivateKey = new bitcore.PrivateKey(); - -var data = new Buffer('The is a raw data example'); - -// Encrypt data -var cypher1 = ECIES.privateKey(alicePrivateKey).publicKey(bobPrivateKey.publicKey); -var encrypted = cypher.encrypt(data); - -// Decrypt data -var cypher2 = ECIES.privateKey(bobPrivateKey).publicKey(alicePrivateKey.publicKey); -var decrypted = cypher.decrypt(encrypted); - -assert(data.toString(), decrypted.toString()); -``` From 0e96ee79388a54757e90765846b400010934edb9 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 9 Jan 2015 19:01:23 -0300 Subject: [PATCH 25/68] remove ECIES from doc guide index --- docs/guide/index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 0f2cc56..18e4dc0 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -34,7 +34,6 @@ To get started, just `npm install bitcore` or `bower install bitcore`. ## Extra * [Crypto](crypto.md) * [Encoding](encoding.md) -* [ECIES](ecies.md) ## Module Development * [Browser Builds](browser.md) From 8d68e9cb029d9268543bc195a2f7a29ebe46c0c5 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 9 Jan 2015 19:51:23 -0300 Subject: [PATCH 26/68] Use satoshisBN internally --- .jshintrc | 2 +- lib/transaction/transaction.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.jshintrc b/.jshintrc index 1d70b69..40fd8c6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -28,7 +28,7 @@ "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) "maxdepth": 4, // Maximum depth of nested control structures "maxlen": 120, // Maximum number of cols in a line - "multistr": true // Allow use of multiline EOL escaping + "multistr": true, // Allow use of multiline EOL escaping "predef": [ // Extra globals. "after", diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 38568fe..c219a7c 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -666,7 +666,7 @@ Transaction.prototype.verify = function() { var valueoutbn = BN(0); for (var i = 0; i < this.outputs.length; i++) { var txout = this.outputs[i]; - var valuebn = txout._satoshis; + var valuebn = txout._satoshisBN; if (valuebn.lt(0)) { return 'transaction txout ' + i + ' negative'; } From ca1d8e9eeb7d8bb863fac8612a09e4786e8c2953 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 9 Jan 2015 20:20:58 -0300 Subject: [PATCH 27/68] Drop payment protocol submodule --- docs/guide/paymentprotocol.md | 184 ------ index.js | 1 - lib/paymentprotocol/browser.js | 217 ------- lib/paymentprotocol/common.js | 457 ------------- lib/paymentprotocol/index.js | 5 - lib/paymentprotocol/node.js | 177 ------ lib/paymentprotocol/rootcerts.js | 75 --- lib/paymentprotocol/rootcerts.json | 144 ----- package.json | 3 - test/paymentprotocol/index.js | 985 ----------------------------- 10 files changed, 2248 deletions(-) delete mode 100644 docs/guide/paymentprotocol.md delete mode 100644 lib/paymentprotocol/browser.js delete mode 100644 lib/paymentprotocol/common.js delete mode 100644 lib/paymentprotocol/index.js delete mode 100644 lib/paymentprotocol/node.js delete mode 100644 lib/paymentprotocol/rootcerts.js delete mode 100644 lib/paymentprotocol/rootcerts.json delete mode 100644 test/paymentprotocol/index.js diff --git a/docs/guide/paymentprotocol.md b/docs/guide/paymentprotocol.md deleted file mode 100644 index 1412a1a..0000000 --- a/docs/guide/paymentprotocol.md +++ /dev/null @@ -1,184 +0,0 @@ -title: Payment Protocol -description: A powerful interface for serialize, deserialize, sign and verify payment protocol messsages. ---- -# Payment Protocol - -## Description - -`PaymentProtocol` and associated functions and methods will serialize, deserialize, sign and verify payment protocol messages both in Node.js and web browsers. Both X.509 and [bitcoin identity protocol](https://en.bitcoin.it/wiki/Identity_protocol_v1) are supported. For detailed technical information, please view [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki). - -```javascript -var bitcore = require('bitcore'); -var PaymentProtocol = bitcore.PaymentProtocol; -``` - -## Make Payment Details - -Here the merchant's server will construct the payment details message: - -```javascript -var now = Date.now() / 1000 | 0; - -// construct the payment details -var details = new PaymentProtocol().makePaymentDetails(); -details.set('network', 'test'); -details.set('outputs', outputs); -details.set('time', now); -details.set('expires', now + 60 * 60 * 24); -details.set('memo', 'A payment request from the merchant.'); -details.set('payment_url', 'https://localhost/-/pay'); -details.set('merchant_data', new Buffer({size: 7})); // identify the request - -``` - -For more information about these fields please visit [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#paymentdetailspaymentrequest) - - -## Sign a Payment Request - -The merchant's server will then construct a payment request and send it to the customer: - -```javascript -// load the X509 certificate -var certificates = new PaymentProtocol().makeX509Certificates(); -certificates.set('certificate', [file_with_x509_der_cert]); - -// form the request -var request = new PaymentRequest().makePaymentRequest(); -request.set('payment_details_version', 1); -request.set('pki_type', 'x509+sha256'); -request.set('pki_data', certificates.serialize()); -request.set('serialized_payment_details', details.serialize()); -request.sign(file_with_x509_private_key); - -// serialize the request -var rawbody = request.serialize(); - -// Example HTTP Response Headers: -// Content-Type: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE -// Content-Length: request.length -// Content-Transfer-Encoding: 'binary' - -``` - -## Verify a Payment Request - -The customers wallet would then verify the payment request as follows (after asking for the payment request message): - -```javascript - -// Example HTTP Request Headers: -// Method: GET -// Accept: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE, PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE -// Content-Type: 'application/octet-stream' -// Content-Length: 0 - -var body = PaymentProtocol.PaymentRequest.decode(rawbody); -var request = new PaymentProtocol().makePaymentRequest(body); - -var version = pr.get('payment_details_version'); -var pki_type = pr.get('pki_type'); -var pki_data = pr.get('pki_data'); -var serializedDetails = pr.get('serialized_payment_details'); -var signature = pr.get('signature'); - -// Verify the signature -var verified = request.verify(); - -// Get the payment details -var decodedDetails = PaymentProtocol.PaymentDetails.decode(serializedDetails); -var details = new PaymentProtocol().makePaymentDetails(decodedDetails); -var network = details.get('network'); -var outputs = details.get('outputs'); -var time = details.get('time'); -var expires = details.get('expires'); -var memo = details.get('memo'); -var payment_url = details.get('payment_url'); -var merchant_data = details.get('merchant_data'); - -``` - -## Send a Payment - -After the request is verified a payment can be sent to the merchant from the customer's wallet: - -```javascript - -// send the payment transaction -var payment = new PaymentProtocol().makePayment(); -payment.set('merchant_data', merchant_data); -payment.set('transactions', [transaction_with_outputs]); // as from payment details - -// define the refund outputs -var refund_outputs = []; -var outputs = new PaymentProtocol().makeOutput(); -outputs.set('amount', 0); -outputs.set('script', script.toBuffer()); // an instance of script -refund_outputs.push(outputs.message); - -payment.set('refund_to', refund_outputs); -payment.set('memo', 'Here is a payment'); - -// serialize and send -var rawbody = pay.serialize(); - -// Example Request Headers: -// Method: 'POST', -// Accept: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE, PaymentPrococl.PAYMENT_ACK_CONTENT_TYPE -// Content-Type: PaymentProtocol.PAYMENT_CONTENT_TYPE -// Content-Length: payment.length -// Content-Transfer-Encoding: 'binary' - -``` - -## Receive a Payment - -The merchant would then receive the payment as follows: - -```javascript - -var body = PaymentProtocol.Payment.decode(rawbody); -var payment = new PaymentProtocol().makePayment(body); -var merchant_data = payment.get('merchant_data'); -var transactions = payment.get('transactions'); -var refund_to = payment.get('refund_to'); -var memo = payment.get('memo'); - -// send the transaction to the bitcoin network - -``` - -## Send a Payment Acknowledgement - -After the payment has been broadcasted, a payment acknowledgement can be sent in response: - -```javascript - -// make a payment acknowledgement -var ack = new PaymentProtocol().makePaymentACK(); -ack.set('payment', payment.message); -ack.set('memo', 'Thank you for your payment!'); -var rawbody = ack.serialize(); - -// Example Response Headers: -// Content-Type: PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE -// Content-Length: ack.length -// Content-Transfer-Encoding: 'binary' - -``` - -## Receive an Acknowledgement - -The customer's wallet can then receive an acknowledgement of payment as follows: - -```javascript -var body = PaymentProtocol.PaymentACK.decode(rawbody); -var ack = new PaymentProtocol().makePaymentACK(body); -var serializedPayment = ack.get('payment'); -var memo = ack.get('memo'); -var decodedPayment = PaymentProtocol.Payment.decode(serializedPayment); -var payment = new PaymentProtocol().makePayment(decodedPayment); -var tx = payment.message.transactions[0]; -``` - -For detailed diagram of the exchange of messages, please see the [Protocol section of BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#protocol). diff --git a/index.js b/index.js index 0c71f6a..9d514f3 100644 --- a/index.js +++ b/index.js @@ -35,7 +35,6 @@ bitcore.HDPrivateKey = require('./lib/hdprivatekey.js'); bitcore.HDPublicKey = require('./lib/hdpublickey.js'); bitcore.Networks = require('./lib/networks'); bitcore.Opcode = require('./lib/opcode'); -bitcore.PaymentProtocol = require('./lib/paymentprotocol'); bitcore.PrivateKey = require('./lib/privatekey'); bitcore.PublicKey = require('./lib/publickey'); bitcore.Script = require('./lib/script'); diff --git a/lib/paymentprotocol/browser.js b/lib/paymentprotocol/browser.js deleted file mode 100644 index 18b1d2d..0000000 --- a/lib/paymentprotocol/browser.js +++ /dev/null @@ -1,217 +0,0 @@ -'use strict'; - -var KJUR = require('jsrsasign'); -var PaymentProtocol = require('./common'); -var RootCerts = require('./rootcerts'); -var rfc3280 = require('asn1.js/rfc/3280'); - -// Documentation: -// http://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.Signature.html#.sign -// http://kjur.github.io/jsrsasign/api/symbols/RSAKey.html - -PaymentProtocol.prototype.x509Sign = function(key, returnTrust) { - var pki_type = this.get('pki_type'); - var pki_data = this.get('pki_data'); // contains one or more x509 certs - pki_data = PaymentProtocol.X509Certificates.decode(pki_data); - pki_data = pki_data.certificate; - var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type; - var buf = this.serializeForSig(); - - var rsa = new KJUR.RSAKey(); - rsa.readPrivateKeyFromPEMString(key.toString()); - key = rsa; - - var sig; - - if (type !== 'none') { - var jsrsaSig = new KJUR.crypto.Signature({ - alg: type + 'withRSA', - prov: 'cryptojs/jsrsa' - }); - - jsrsaSig.init(key); - - jsrsaSig.updateHex(buf.toString('hex')); - - sig = new Buffer(jsrsaSig.sign(), 'hex'); - } else { - sig = ''; - } - - if (returnTrust) { - var cert = pki_data[pki_data.length - 1]; - var der = cert.toString('hex'); - var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - var caName = RootCerts.getTrusted(pem); - var selfSigned = 0; - if (!caName) { - selfSigned = pki_data.length > 1 ? -1 : 1; - } - return { - selfSigned: selfSigned, - isChain: pki_data.length > 1, - signature: sig, - caTrusted: !!caName, - caName: caName || null - }; - } - - return sig; -}; - -PaymentProtocol.prototype.x509Verify = function(returnTrust) { - var sig = this.get('signature'); - var pki_type = this.get('pki_type'); - var pki_data = this.get('pki_data'); - pki_data = PaymentProtocol.X509Certificates.decode(pki_data); - pki_data = pki_data.certificate; - var buf = this.serializeForSig(); - var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type; - - var der; - var pem; - var verified; - - if (type !== 'none') { - var jsrsaSig = new KJUR.crypto.Signature({ - alg: type + 'withRSA', - prov: 'cryptojs/jsrsa' - }); - var signedCert = pki_data[0]; - der = signedCert.toString('hex'); - pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - jsrsaSig.initVerifyByCertificatePEM(pem); - jsrsaSig.updateHex(buf.toString('hex')); - verified = jsrsaSig.verify(sig.toString('hex')); - } else { - verified = true; - } - - var chain = pki_data; - - // Get the CA cert's name - - var issuer = chain[chain.length - 1]; - der = issuer.toString('hex'); - pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - var caName = RootCerts.getTrusted(pem); - - if (chain.length === 1 && !caName) { - if (returnTrust) { - return { - selfSigned: 1, // yes - isChain: false, - verified: verified, - caTrusted: false, - caName: null, - chainVerified: false - }; - } - return verified; - } - - // If there's no trusted root cert, don't - // bother validating the cert chain. - if (!caName) { - if (returnTrust) { - return { - selfSigned: -1, // unknown - isChain: chain.length > 1, - verified: verified, - caTrusted: false, - caName: null, - chainVerified: false - }; - } - return verified; - } - - var chainVerified = PaymentProtocol.verifyCertChain(chain, type); - - if (returnTrust) { - return { - selfSigned: 0, // no - isChain: true, - verified: verified, - caTrusted: !!caName, - caName: caName || null, - chainVerified: chainVerified - }; - } - - return verified && chainVerified; -}; - -PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) { - if (sigHashAlg === 'none') { - return true; - } - return chain.every(function(cert, i) { - var der = cert.toString('hex'); - var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - var name = RootCerts.getTrusted(pem); - - var ncert = chain[i + 1]; - // The root cert, check if it's trusted: - if (!ncert || name) { - if (!name) { - return false; - } - chain.length = 0; - return true; - } - var nder = ncert.toString('hex'); - var npem = KJUR.asn1.ASN1Util.getPEMStringFromHex(nder, 'CERTIFICATE'); - - // Get Next Certificate: - var ndata = new Buffer(nder, 'hex'); - var nc = rfc3280.Certificate.decode(ndata, 'der'); - - var npubKey; - // Get Public Key from next certificate (via KJUR because it's a mess): - if (sigHashAlg !== 'none') { - var js = new KJUR.crypto.Signature({ - alg: sigHashAlg + 'withRSA', - prov: 'cryptojs/jsrsa' - }); - js.initVerifyByCertificatePEM(npem); - npubKey = js.pubKey; - } - - // Get Signature Value from current certificate: - var data = new Buffer(der, 'hex'); - var c = rfc3280.Certificate.decode(data, 'der'); - var sig = c.signature.data; - - // Check Validity of Certificates - var validityVerified = PaymentProtocol.validateCertTime(c, nc); - - // Check the Issuer matches the Subject of the next certificate: - var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc); - - var sigVerified; - - // Verify current Certificate signature - if (sigHashAlg !== 'none') { - var jsrsaSig = new KJUR.crypto.Signature({ - alg: sigHashAlg + 'withRSA', - prov: 'cryptojs/jsrsa' - }); - jsrsaSig.initVerifyByPublicKey(npubKey); - - // Get the raw DER TBSCertificate - // from the DER Certificate: - var tbs = PaymentProtocol.getTBSCertificate(data); - - jsrsaSig.updateHex(tbs.toString('hex')); - - sigVerified = jsrsaSig.verify(sig.toString('hex')); - } else { - sigVerified = true; - } - - return validityVerified && issuerVerified && sigVerified; - }); -}; - -module.exports = PaymentProtocol; diff --git a/lib/paymentprotocol/common.js b/lib/paymentprotocol/common.js deleted file mode 100644 index 8a31802..0000000 --- a/lib/paymentprotocol/common.js +++ /dev/null @@ -1,457 +0,0 @@ -'use strict'; - -var protobufjs = require('protobufjs/dist/ProtoBuf'); -var RootCerts = require('./rootcerts'); -var PublicKey = require('../publickey'); -var PrivateKey = require('../privatekey'); -var Signature = require('../crypto/signature'); -var ECDSA = require('../crypto/ecdsa'); -var sha256sha256 = require('../crypto/hash').sha256sha256; -var varintBufNum = require('../encoding/bufferwriter').varintBufNum; - -// BIP 70 - payment protocol -function PaymentProtocol() { - this.messageType = null; - this.message = null; -} - -PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE = 50000; -PaymentProtocol.PAYMENT_MAX_SIZE = 50000; -PaymentProtocol.PAYMENT_ACK_MAX_SIZE = 60000; -PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE = 'application/bitcoin-paymentrequest'; -PaymentProtocol.PAYMENT_CONTENT_TYPE = 'application/bitcoin-payment'; -PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE = 'application/bitcoin-paymentack'; - -// https://www.google.com/search?q=signatureAlgorithm+1.2.840.113549.1.1.1 -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379057(v=vs.85).aspx -PaymentProtocol.X509_ALGORITHM = { - '1.2.840.113549.1.1.1': 'RSA', - '1.2.840.113549.1.1.2': 'RSA_MD2', - '1.2.840.113549.1.1.4': 'RSA_MD5', - '1.2.840.113549.1.1.5': 'RSA_SHA1', - '1.2.840.113549.1.1.11': 'RSA_SHA256', - '1.2.840.113549.1.1.12': 'RSA_SHA384', - '1.2.840.113549.1.1.13': 'RSA_SHA512', - - '1.2.840.10045.4.3.2': 'ECDSA_SHA256', - '1.2.840.10045.4.3.3': 'ECDSA_SHA384', - '1.2.840.10045.4.3.4': 'ECDSA_SHA512' -}; - -PaymentProtocol.getAlgorithm = function(value, index) { - if (Array.isArray(value)) { - value = value.join('.'); - } - value = PaymentProtocol.X509_ALGORITHM[value]; - if (typeof(index) !== 'undefined') { - value = value.split('_'); - if (index === true) { - return { - cipher: value[0], - hash: value[1] - }; - } - return value[index]; - } - return value; -}; - -// Grab the raw DER To-Be-Signed Certificate -// from a DER Certificate to verify -PaymentProtocol.getTBSCertificate = function(data) { - // We start by slicing off the first SEQ of the - // Certificate (TBSCertificate is its own SEQ). - - // The first 10 bytes usually look like: - // [ 48, 130, 5, 32, 48, 130, 4, 8, 160, 3 ] - var start = 0; - var starts = 0; - for (start = 0; start < data.length; start++) { - if (starts === 1 && data[start] === 48) { - break; - } - if (starts < 1 && data[start] === 48) { - starts++; - } - } - - // The bytes *after* the TBS (including the last TBS byte) will look like - // (note the 48 - the start of the sig, and the 122 - the end of the TBS): - // [ 122, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, ... ] - - // The certificate in these examples has a `start` of 4, and an `end` of - // 1040. The 4 bytes is the DER SEQ of the Certificate, right before the - // SEQ of the TBSCertificate. - var end = 0; - var ends = 0; - for (end = data.length - 1; end > 0; end--) { - if (ends === 2 && data[end] === 48) { - break; - } - if (ends < 2 && data[end] === 0) { - ends++; - } - } - - // Return our raw DER TBSCertificate: - return data.slice(start, end); -}; - -// Check Validity of Certificates -PaymentProtocol.validateCertTime = function(c, nc) { - var validityVerified = true; - var now = Date.now(); - var cBefore = c.tbsCertificate.validity.notBefore.value; - var cAfter = c.tbsCertificate.validity.notAfter.value; - var nBefore = nc.tbsCertificate.validity.notBefore.value; - var nAfter = nc.tbsCertificate.validity.notAfter.value; - if (cBefore > now || cAfter < now || nBefore > now || nAfter < now) { - validityVerified = false; - } - return validityVerified; -}; - -// Check the Issuer matches the Subject of the next certificate: -PaymentProtocol.validateCertIssuer = function(c, nc) { - var issuer = c.tbsCertificate.issuer; - var subject = nc.tbsCertificate.subject; - var issuerVerified = issuer.type === subject.type && issuer.value.every(function(issuerArray, i) { - var subjectArray = subject.value[i]; - return issuerArray.every(function(issuerObject, i) { - var subjectObject = subjectArray[i]; - - var issuerObjectType = issuerObject.type.join('.'); - var subjectObjectType = subjectObject.type.join('.'); - - var issuerObjectValue = issuerObject.value.toString('hex'); - var subjectObjectValue = subjectObject.value.toString('hex'); - - return issuerObjectType === subjectObjectType && issuerObjectValue === subjectObjectValue; - }); - }); - return issuerVerified; -}; - -PaymentProtocol.RootCerts = RootCerts; - -PaymentProtocol.proto = {}; - -PaymentProtocol.proto.Output = 'message Output {\ - optional uint64 amount = 1 [default = 0];\ - optional bytes script = 2;\ -}\n'; - -PaymentProtocol.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'; - -PaymentProtocol.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'; - -PaymentProtocol.proto.Payment = 'message Payment {\ - optional bytes merchant_data = 1;\ - repeated bytes transactions = 2;\ - repeated Output refund_to = 3;\ - optional string memo = 4;\ -}\n'; - -PaymentProtocol.proto.PaymentACK = 'message PaymentACK {\ - required Payment payment = 1;\ - optional string memo = 2;\ -}\n'; - -PaymentProtocol.proto.X509Certificates = 'message X509Certificates {\ - repeated bytes certificate = 1;\ -}\n'; - -PaymentProtocol.proto.all = ''; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.Output; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentDetails; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentRequest; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.Payment; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.PaymentACK; -PaymentProtocol.proto.all = PaymentProtocol.proto.all + PaymentProtocol.proto.X509Certificates; - -PaymentProtocol.builder = protobufjs.loadProto(PaymentProtocol.proto.all); - -PaymentProtocol.Output = PaymentProtocol.builder.build('Output'); -PaymentProtocol.PaymentDetails = PaymentProtocol.builder.build('PaymentDetails'); -PaymentProtocol.PaymentRequest = PaymentProtocol.builder.build('PaymentRequest'); -PaymentProtocol.Payment = PaymentProtocol.builder.build('Payment'); -PaymentProtocol.PaymentACK = PaymentProtocol.builder.build('PaymentACK'); -PaymentProtocol.X509Certificates = PaymentProtocol.builder.build('X509Certificates'); - -PaymentProtocol.prototype.makeOutput = function(obj) { - this.messageType = 'Output'; - this.message = new PaymentProtocol.Output(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.makePaymentDetails = function(obj) { - this.messageType = 'PaymentDetails'; - this.message = new PaymentProtocol.PaymentDetails(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.makePaymentRequest = function(obj) { - this.messageType = 'PaymentRequest'; - this.message = new PaymentProtocol.PaymentRequest(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.makePayment = function(obj) { - this.messageType = 'Payment'; - this.message = new PaymentProtocol.Payment(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.makePaymentACK = function(obj) { - this.messageType = 'PaymentACK'; - this.message = new PaymentProtocol.PaymentACK(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.makeX509Certificates = function(obj) { - this.messageType = 'X509Certificates'; - this.message = new PaymentProtocol.X509Certificates(); - this.setObj(obj); - return this; -}; - -PaymentProtocol.prototype.isValidSize = function() { - var s = this.serialize(); - if (this.messageType === 'PaymentRequest') { - return s.length < PaymentProtocol.PAYMENT_REQUEST_MAX_SIZE; - } - if (this.messageType === 'Payment') { - return s.length < PaymentProtocol.PAYMENT_MAX_SIZE; - } - if (this.messageType === 'PaymentACK') { - return s.length < PaymentProtocol.PAYMENT_ACK_MAX_SIZE; - } - return true; -}; - -PaymentProtocol.prototype.getContentType = function() { - if (this.messageType === 'PaymentRequest') { - return PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE; - } - - if (this.messageType === 'Payment') { - return PaymentProtocol.PAYMENT_CONTENT_TYPE; - } - - if (this.messageType === 'PaymentACK') { - return PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE; - } - - throw new Error('No known content type for this message type'); -}; - -PaymentProtocol.prototype.set = function(key, val) { - this.message.set(key, val); - return this; -}; - -PaymentProtocol.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; -}; - -PaymentProtocol.prototype.setObj = function(obj) { - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - var val = obj[key]; - this.message.set(key, val); - } - } - return this; -}; - -PaymentProtocol.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; -}; - -PaymentProtocol.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; -}; - -PaymentProtocol.prototype.deserialize = function(buf, messageType) { - this.messageType = messageType || this.messageType; - if (!this.messageType) { - throw new Error('Must specify messageType'); - } - this.message = PaymentProtocol[this.messageType].decode(buf); - return this; -}; - -PaymentProtocol.prototype.sign = function(key, returnTrust) { - if (this.messageType !== 'PaymentRequest') { - throw new Error('Signing can only be performed on a PaymentRequest'); - } - - var pki_type = this.get('pki_type'); - - var sig; - if (pki_type === 'SIN') { - sig = this.sinSign(key); - } else if (pki_type === 'x509+sha1' || pki_type === 'x509+sha256') { - sig = this.x509Sign(key, returnTrust); - } else if (pki_type === 'none') { - return this; - } else { - throw new Error('Unsupported pki_type'); - } - - this.set('signature', sig); - - return this; -}; - -PaymentProtocol.prototype.verify = function(returnTrust) { - 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(returnTrust); - } else if (pki_type === 'none') { - return true; - } - - throw new Error('Unsupported pki_type'); -}; - -function magicHash(str) { - var magicBytes = new Buffer('Bitcoin Signed Message:\n'); - var prefix1 = varintBufNum(magicBytes.length); - var message = new Buffer(str); - var prefix2 = varintBufNum(message.length); - var buf = Buffer.concat([prefix1, magicBytes, prefix2, message]); - var hash = sha256sha256(buf); - return hash; -} - -//default signing function for prototype.sign -PaymentProtocol.prototype.sinSign = function(privateKey) { - if ( !(privateKey instanceof PrivateKey) ) { - throw new TypeError('Expects an instance of PrivateKey'); - } - var pubkey = privateKey.toPublicKey().toBuffer(); - this.set('pki_data', pubkey); - var buf = this.serializeForSig(); - var hash = magicHash(buf); - var signature = ECDSA.sign(hash, privateKey); - return signature.toDER(); -}; - -//default verify function -PaymentProtocol.prototype.sinVerify = function() { - var sig = this.get('signature'); - var pubkey = this.get('pki_data'); - var buf = this.serializeForSig(); - var hash = magicHash(buf); - var publicKey = PublicKey.fromBuffer(pubkey); - var signature = new Signature.fromString(sig); - var verified = ECDSA.verify(hash, signature, publicKey); - return verified; -}; - -// Helpers - -PaymentProtocol.PEMtoDER = -PaymentProtocol.prototype._PEMtoDER = function(pem) { - return this._PEMtoDERParam(pem); -}; - -PaymentProtocol.PEMtoDERParam = -PaymentProtocol.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); -}; - -PaymentProtocol.DERtoPEM = -PaymentProtocol.prototype._DERtoPEM = function(der, type) { - if (typeof der === 'string') { - der = new Buffer(der, 'hex'); - } - type = type || 'PRIVACY-ENHANCED MESSAGE'; - 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'; -}; - -// Expose RootCerts -PaymentProtocol.getTrusted = RootCerts.getTrusted; -PaymentProtocol.getCert = RootCerts.getCert; -PaymentProtocol.parsePEM = RootCerts.parsePEM; -PaymentProtocol.certs = RootCerts.certs; -PaymentProtocol.trusted = RootCerts.trusted; - -module.exports = PaymentProtocol; diff --git a/lib/paymentprotocol/index.js b/lib/paymentprotocol/index.js deleted file mode 100644 index 841a6a5..0000000 --- a/lib/paymentprotocol/index.js +++ /dev/null @@ -1,5 +0,0 @@ -if ( typeof(window) === 'undefined' ) { - module.exports = require('./node'); -} else { - module.exports = require('./browser'); -} diff --git a/lib/paymentprotocol/node.js b/lib/paymentprotocol/node.js deleted file mode 100644 index cf45391..0000000 --- a/lib/paymentprotocol/node.js +++ /dev/null @@ -1,177 +0,0 @@ -'use strict'; - -var crypto = require('crypto'); -var RootCerts = require('./rootcerts'); -var PaymentProtocol = require('./common'); -var rfc3280 = require('asn1.js/rfc/3280'); - -PaymentProtocol.prototype.x509Sign = function(key, returnTrust) { - var pki_type = this.get('pki_type'); - var pki_data = this.get('pki_data'); - pki_data = PaymentProtocol.X509Certificates.decode(pki_data); - pki_data = pki_data.certificate; - var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type; - - var sig; - if (type !== 'none') { - var signature = crypto.createSign('RSA-' + type); - var buf = this.serializeForSig(); - signature.update(buf); - sig = signature.sign(key); - } else { - sig = ''; - } - - if (returnTrust) { - var cert = pki_data[pki_data.length - 1]; - var der = cert.toString('hex'); - var pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE'); - var caName = RootCerts.getTrusted(pem); - var selfSigned = 0; - if (!caName) { - selfSigned = pki_data.length > 1 ? -1 : 1; - } - return { - selfSigned: selfSigned, - isChain: pki_data.length > 1, - signature: sig, - caTrusted: !!caName, - caName: caName || null - }; - } - - return sig; -}; - -PaymentProtocol.prototype.x509Verify = function(returnTrust) { - var pki_type = this.get('pki_type'); - var sig = this.get('signature'); - var pki_data = this.get('pki_data'); - pki_data = PaymentProtocol.X509Certificates.decode(pki_data); - pki_data = pki_data.certificate; - var buf = this.serializeForSig(); - var type = pki_type !== 'none' ? pki_type.split('+')[1].toUpperCase() : pki_type; - - var verified; - var der; - var pem; - - if (type !== 'none') { - var verifier = crypto.createVerify('RSA-' + type); - verifier.update(buf); - var signedCert = pki_data[0]; - der = signedCert.toString('hex'); - pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE'); - verified = verifier.verify(pem, sig); - } else { - verified = true; - } - - var chain = pki_data; - - // Get the CA cert's name - var issuer = chain[chain.length - 1]; - der = issuer.toString('hex'); - pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE'); - var caName = RootCerts.getTrusted(pem); - - if (chain.length === 1 && !caName) { - if (returnTrust) { - return { - selfSigned: 1, // yes - isChain: false, - verified: verified, - caTrusted: false, - caName: null, - chainVerified: false - }; - } - return verified; - } - - // If there's no trusted root cert, don't - // bother validating the cert chain. - if (!caName) { - if (returnTrust) { - return { - selfSigned: -1, // unknown - isChain: chain.length > 1, - verified: verified, - caTrusted: false, - caName: null, - chainVerified: false - }; - } - return verified; - } - - var chainVerified = PaymentProtocol.verifyCertChain(chain, type); - - if (returnTrust) { - return { - selfSigned: 0, // no - isChain: true, - verified: verified, - caTrusted: !!caName, - caName: caName || null, - chainVerified: chainVerified - }; - } - - return verified && chainVerified; -}; - -PaymentProtocol.verifyCertChain = function(chain, sigHashAlg) { - if (sigHashAlg === 'none') { - return true; - } - return chain.every(function(cert, i) { - var der = cert.toString('hex'); - var pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE'); - var name = RootCerts.getTrusted(pem); - - var ncert = chain[i + 1]; - - // The root cert, check if it's trusted: - if (!ncert || name) { - if (!name) { - return false; - } - chain.length = 0; - return true; - } - var nder = ncert.toString('hex'); - - // Get Public Key from next certificate: - var ndata = new Buffer(nder, 'hex'); - var nc = rfc3280.Certificate.decode(ndata, 'der'); - var npubKeyAlg = PaymentProtocol.getAlgorithm( - nc.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm); - var npubKey = nc.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; - npubKey = PaymentProtocol.DERtoPEM(npubKey, npubKeyAlg + ' PUBLIC KEY'); - - // Get Signature Value from current certificate: - var data = new Buffer(der, 'hex'); - var c = rfc3280.Certificate.decode(data, 'der'); - var sig = c.signature.data; - - // Check Validity of Certificates - var validityVerified = PaymentProtocol.validateCertTime(c, nc); - - // Check the Issuer matches the Subject of the next certificate: - var issuerVerified = PaymentProtocol.validateCertIssuer(c, nc); - - // Verify current Certificate signature: - // Get the raw DER TBSCertificate - // from the DER Certificate: - var tbs = PaymentProtocol.getTBSCertificate(data); - - var verifier = crypto.createVerify('RSA-' + sigHashAlg); - verifier.update(tbs); - var sigVerified = verifier.verify(npubKey, sig); - - return validityVerified && issuerVerified && sigVerified; - }); -}; - -module.exports = PaymentProtocol; diff --git a/lib/paymentprotocol/rootcerts.js b/lib/paymentprotocol/rootcerts.js deleted file mode 100644 index 855a188..0000000 --- a/lib/paymentprotocol/rootcerts.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -var RootCerts = exports; - -var certs = require('./rootcerts.json'); - -// Use hash table for efficiency: -var trusted = Object.keys(certs).reduce(function(trusted, key) { - var pem = certs[key]; - pem = pem.replace(/-----BEGIN CERTIFICATE-----/g, ''); - pem = pem.replace(/-----END CERTIFICATE-----/g, ''); - pem = pem.replace(/\s+/g, ''); - trusted[pem] = key; - return trusted; -}, {}); - -RootCerts.getTrusted = function(pem) { - pem = RootCerts.parsePEM(pem)[0].pem; - if (!Object.prototype.hasOwnProperty.call(trusted, pem)) { - return; - } - return trusted[pem]; -}; - -RootCerts.getCert = function(name) { - name = name.replace(/^s+|s+$/g, ''); - if (!Object.prototype.hasOwnProperty.call(certs, name)) { - return; - } - return certs[name]; -}; - -RootCerts.parsePEM = function(pem) { - pem = pem + ''; - var concatted = pem.trim().split(/-----BEGIN [^\-\r\n]+-----/); - if (concatted.length > 2) { - return concatted.reduce(function(out, pem) { - if (!pem) { - return out; - } - pem = RootCerts.parsePEM(pem)[0].pem; - if (pem) { - out.push(pem); - } - return out; - }, []); - } - var type = /-----BEGIN ([^\-\r\n]+)-----/.exec(pem)[1]; - pem = pem.replace(/-----BEGIN [^\-\r\n]+-----/, ''); - pem = pem.replace(/-----END [^\-\r\n]+-----/, ''); - var parts = pem.trim().split(/(?:\r?\n){2,}/); - var headers = {}; - if (parts.length > 1) { - headers = parts[0].trim().split(/[\r\n]/).reduce(function(out, line) { - var parts = line.split(/:[ \t]+/); - var key = parts[0].trim().toLowerCase(); - var value = (parts.slice(1).join('') || '').trim(); - out[key] = value; - return out; - }, {}); - pem = parts.slice(1).join(''); - } - pem = pem.replace(/\s+/g, ''); - var der = pem ? new Buffer(pem, 'base64') : null; - return [{ - type: type, - headers: headers, - pem: pem, - der: der, - body: der || new Buffer([0]) - }]; -}; - -RootCerts.certs = certs; -RootCerts.trusted = trusted; diff --git a/lib/paymentprotocol/rootcerts.json b/lib/paymentprotocol/rootcerts.json deleted file mode 100644 index 9e37365..0000000 --- a/lib/paymentprotocol/rootcerts.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "GTE CyberTrust Global Root": "-----BEGIN CERTIFICATE-----\nMIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9H\nVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5j\nLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAw\nWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0\naW9uMScwJQYDVQQLEx5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMT\nGkdURSBDeWJlclRydXN0IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\ngQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwef\nU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4\n04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR\n22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq\n81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0PlZPvy5TYnh+dXIVtx6quTx8i\ntc2VrbqnzPmrC3p/\n-----END CERTIFICATE-----\n", - "Thawte Server CA": "-----BEGIN CERTIFICATE-----\nMIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNV\nBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUg\nQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lv\nbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNl\ncnRzQHRoYXd0ZS5jb20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkG\nA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0w\nGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT\nZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3\nDQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ\nAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC\n6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCXL+eQbcAoQpnXTEPew/UhbVSf\nXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ\nKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllD\nfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAb\ni8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=\n-----END CERTIFICATE-----\n", - "Thawte Premium Server CA": "-----BEGIN CERTIFICATE-----\nMIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNV\nBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUg\nQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lv\nbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlw\ncmVtaXVtLXNlcnZlckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1\nOVowgc4xCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNh\ncGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRp\nZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl\ncnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzAN\nBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhI\nNTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQug2SBhRz1JPLlyoAnFxODLz6\nFVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/qgeN9EJN50CdHDcCAwEAAaMTMBEw\nDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJ\neGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu\n1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcU\nQg==\n-----END CERTIFICATE-----\n", - "Equifax Secure CA": "-----BEGIN CERTIFICATE-----\nMIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4G\nA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0\naG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMx\nEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRl\nIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2R\nFGiYCh7+2gRvE4RiIcPRfM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP\n/PvwDN1Dulsr4R+AcJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/\nFP3gx7kCAwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\nMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUg\nQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjAL\nBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9QwHQYDVR0OBBYE\nFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsF\nVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaS\nbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA\n2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n-----END CERTIFICATE-----\n", - "Digital Signature Trust Co. Global CA 1": "-----BEGIN CERTIFICATE-----\nMIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIG\nA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAe\nFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQK\nExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0G\nCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlR\nEmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR\n6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEg\nMBEGCWCGSAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx\nJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0Eg\nRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIx\nMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4\nMB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2\nfQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160\nL+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038\nbKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6\nw4pl\n-----END CERTIFICATE-----\n", - "Digital Signature Trust Co. Global CA 3": "-----BEGIN CERTIFICATE-----\nMIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIG\nA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAe\nFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQK\nExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0G\nCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fB\nw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyM\nvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEg\nMBEGCWCGSAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx\nJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0Eg\nRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIw\nOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6CTShlgDzJQW6sNS5ay97u+Dlb\nMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2\nfQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMO\nOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+\n7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlih\nw6ID\n-----END CERTIFICATE-----\n", - "Verisign Class 3 Public Primary Certification Authority": "-----BEGIN CERTIFICATE-----\nMIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMC\nVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQ\ncmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgw\nMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYD\nVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGf\nMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ\n2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaO\nIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G\nCSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNh\nkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khV\ndWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ\n-----END CERTIFICATE-----\n", - "Verisign Class 3 Public Primary Certification Authority - G2": "-----BEGIN CERTIFICATE-----\nMIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYT\nAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg\nUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5\nOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZW\nZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVow\ngcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh\nc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYD\nVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5\nMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GN\nADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXX\nwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg013gfqLptQ5GVj0VXXn7F+8qk\nBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFFN\nzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzo\nKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcm\neQD2+A2iMzAo1KpYoJ2daZH9\n-----END CERTIFICATE-----\n", - "GlobalSign Root CA": "-----BEGIN CERTIFICATE-----\nMIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMC\nQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNV\nBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBa\nMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdS\nb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\nA4IBDwAwggEKAoIBAQDaDuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtI\nK+6NiY6arymAZavpxy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCO\nXkNz8kHp1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\nsnUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3\ndLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DP\nAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRg\ne2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUFAAOCAQEA1nPnfE920I2/7LqivjTF\nKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY7\n76BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9\nLhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr\n+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\nHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n-----END CERTIFICATE-----\n", - "GlobalSign Root CA - R2": "-----BEGIN CERTIFICATE-----\nMIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMX\nR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMT\nCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQL\nExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UE\nAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8o\nmUVCxKs+IVSbC9N/hHD6ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7\nSqbKSaZeqKeMWhG8eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQ\nBoZfXklqtTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd\nC9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feq\nCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8E\nBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IHV2ccHsBqBt5ZtJot39wZhi4w\nNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9iYWxzaWduLm5ldC9yb290LXIyLmNy\nbDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEA\nmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkI\nk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRD\nLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd\nAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7TBj0/VLZ\njmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==\n-----END CERTIFICATE-----\n", - "ValiCert Class 1 VA": "-----BEGIN CERTIFICATE-----\nMIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlk\nYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlD\nZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\nOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29t\nMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\nIFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsT\nLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQD\nExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\ncnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu\n9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m\n+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/\ncQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXo\nP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ\n4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI\n-----END CERTIFICATE-----\n", - "ValiCert Class 2 VA": "-----BEGIN CERTIFICATE-----\nMIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlk\nYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlD\nZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\nOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29t\nMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\nIFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsT\nLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQD\nExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\ncnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2\nVUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQ\nb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p\n9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6\nEILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2az\nSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd\n-----END CERTIFICATE-----\n", - "RSA Root Certificate 1": "-----BEGIN CERTIFICATE-----\nMIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlk\nYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlD\nZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\nOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29t\nMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\nIFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsT\nLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQD\nExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\ncnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+e\npvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChM\nMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBV\nPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs3x/be0kz9dNnnfS0ChCzycUs4pJq\ncXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu\n1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu\n-----END CERTIFICATE-----\n", - "Verisign Class 3 Public Primary Certification Authority - G3": "-----BEGIN CERTIFICATE-----\nMIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQG\nEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0\nIE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv\ncml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1h\ncnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3\nMTYyMzU5NTlaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAd\nBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlT\naWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu\nIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCC\nASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2\nR/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6\nyaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFU\nokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyo\nw0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBte\nHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my\n/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe\nDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC/Y4wjylG\nsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0xuKh\nXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa\nt20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==\n-----END CERTIFICATE-----\n", - "Verisign Class 4 Public Primary Certification Authority - G3": "-----BEGIN CERTIFICATE-----\nMIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQG\nEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0\nIE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv\ncml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1h\ncnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3\nMTYyMzU5NTlaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAd\nBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlT\naWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu\nIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCC\nASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYl\nS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0\nqJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM8BDcVHOLBKFGMzNcF0C5nk3T875V\ng+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i\n8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0\nZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1Wr\nIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq\ng6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKmfjaF3H48\nZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJdRTjD\nOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG\nUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==\n-----END CERTIFICATE-----\n", - "Entrust.net Secure Server CA": "-----BEGIN CERTIFICATE-----\nMIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29y\ncC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5u\nZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZp\nY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQsw\nCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0\nLm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykg\nMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg\nU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCB\nhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHIN\niC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl\n+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcwggHTMBEGCWCGSAGG+EIBAQQEAwIA\nBzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UE\nChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi\neSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBM\naW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp\nb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVudHJ1c3Qu\nbmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkwNTI1\nMTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow\nHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9\nB0EABAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7\nRw7/JXyNEwr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7\nqIcyunL2POI9n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G\n+bI=\n-----END CERTIFICATE-----\n", - "Entrust.net Premium 2048 Secure Server CA": "-----BEGIN CERTIFICATE-----\nMIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVz\ndC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJl\nZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0\nZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4\nKTAeFw05OTEyMjQxNzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0\nLm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVm\nLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl\nZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtK\nTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/EC\nDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ\n/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUyVYr9smRM\nDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVC\nwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0j\nBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJ\nFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA\nWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMooPS7mmNz\n7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcSo8f0\nFbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z\n2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof888\n6ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==\n-----END CERTIFICATE-----\n", - "Baltimore CyberTrust Root": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAG\nA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1v\ncmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjEL\nMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEi\nMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2ygu\nzmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo\n6vWrJYeKmpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\nXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3z\nyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkC\nAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1UdEwEB/wQIMAYB\nAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27\nTyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukM\nJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhS\nNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67\nG7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\nR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n-----END CERTIFICATE-----\n", - "Equifax Secure Global eBusiness CA": "-----BEGIN CERTIFICATE-----\nMIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UE\nChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFs\nIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkG\nA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlm\nYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\ngYkCgYEAuucXkAJlsTRVPEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/Ka\nelpzmKNc6fuKcxtc58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuo\nWcDNM50/o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH\nMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYD\nVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf\n2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA\n4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIYNMR1pHMc8Y3c7635s3a0kr/clRAe\nvsvIO1qEYBlWlKlV\n-----END CERTIFICATE-----\n", - "Equifax Secure eBusiness CA 1": "-----BEGIN CERTIFICATE-----\nMIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UE\nChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2lu\nZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJV\nUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1\ncmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fe\nk6lfWg0XTzQaDJj0ItlZ1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2D\nKocKIdMSODRsjQBuWqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6r\nXyo4YgKwEnv+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD\nAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZ\nFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnm\nJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2\nsUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==\n-----END CERTIFICATE-----\n", - "Equifax Secure eBusiness CA 2": "-----BEGIN CERTIFICATE-----\nMIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUG\nA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVz\ncyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMx\nFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVz\naW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF\n7Y6yEb3+6+e0dMKP/wXn2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsg\ncDKqQM2mll/EcTc/BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/A\natbfIb0CAwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX\nMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNp\nbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjAL\nBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBqy/3YIHqngnYwHQYDVR0OBBYE\nFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsF\nVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe\n68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE\n1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN\n-----END CERTIFICATE-----\n", - "AddTrust Low-Value Services Root": "-----BEGIN CERTIFICATE-----\nMIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UE\nChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQD\nExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAz\nODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk\nZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3Qw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH\n+9ZOEQpnXvUGW2ulCDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7\nBo8wBN6ntGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl\ndI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0\nK7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG\n9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+\nwa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MIGPBgNVHSMEgYcwgYSAFJWx\ntPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1\nc3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVz\ndCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0\nMkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz\n43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MYeDdXL+gz\nB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xrmYbv\nP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj\nccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=\n-----END CERTIFICATE-----\n", - "AddTrust External Root": "-----BEGIN CERTIFICATE-----\nMIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UE\nChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3Jr\nMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoX\nDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYw\nJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1\nc3QgRXh0ZXJuYWwgQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3\nGjPm8gAELTngTlvtH7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCw\nSXrbLpX9uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX\nmk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63u\nbUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5\naWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0WicCAwEAAaOB3DCB2TAdBgNV\nHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMB\nAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYT\nAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwg\nVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJ\nKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH\nYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw56wwCURQt\njr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355e6cJ\nDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u\nG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49O\nhgQ=\n-----END CERTIFICATE-----\n", - "AddTrust Public Services Root": "-----BEGIN CERTIFICATE-----\nMIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UE\nChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQD\nExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQx\nNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRk\nVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4\njsIMEZBRpS9mVEBV6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrH\nAZcHF/nXGCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP\ndzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2ro\nyBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9\nBBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQWBBSBPjfYkrAfd59ctKtzquf2\nNGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfY\nkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0\nIEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3Qg\nUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmu\nG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/\niHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/AoGEjwxrzQ\nvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9Yjll\npu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H\nEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=\n-----END CERTIFICATE-----\n", - "AddTrust Qualified Certificates Root": "-----BEGIN CERTIFICATE-----\nMIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UE\nChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQD\nExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAx\nMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMU\nQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBS\nb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTb\nYjx5eLfpMLXsDBwqxBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqz\nZwFZ8V1G87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i\n2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mH\nfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvES\na0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6\nWA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGG\ngBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0Fk\nZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRk\nVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2Vh\nlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm\nhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6XdgWTP5XH\nAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9zeRXEw\nMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB\niFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=\n-----END CERTIFICATE-----\n", - "Entrust Root Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAU\nBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMg\naW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwg\nSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X\nDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQK\nEw1FbnRydXN0LCBJbmMuMTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29y\ncG9yYXRlZCBieSByZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4x\nLTArBgNVBAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ\nKoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poB\nj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypo\nwCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+\nSKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rV\nvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2\nHNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB\n/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSME\nGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE\nvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQCT\n1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISMY/YP\nyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa\nv52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE\n2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPc\nj2A781q0tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8\n-----END CERTIFICATE-----\n", - "RSA Security 2048 v3": "-----BEGIN CERTIFICATE-----\nMIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYD\nVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAe\nFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0\neSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEF\nAAOCAQ8AMIIBCgKCAQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37\nRqtBaB4Y6lXIL5F4iSj7Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3\nOTsor8udGuorryGlwSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYq\nODGBDSnhAMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2\nPcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszA\nCwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAW\ngBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NRMKSq6UWuNST6/yQsM9CxnYww\nDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmYv/3VEhF5Ug7uMYm83X/50cYVIeiK\nAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8X\nDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6C\nCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEk\nllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3\n7CAFYd4=\n-----END CERTIFICATE-----\n", - "GeoTrust Global CA": "-----BEGIN CERTIFICATE-----\nMIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYD\nVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIw\nNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2Vv\nVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEH\nCIjaWC9mOSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu\nT8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386D\nGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+\nbw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvo\ncWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9\nqn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1luMrMTjANBgkqhkiG9w0BAQUF\nAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VS\nsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfO\nEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQd\ntqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeX\nxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==\n-----END CERTIFICATE-----\n", - "GeoTrust Global CA 2": "-----BEGIN CERTIFICATE-----\nMIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UE\nChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQw\nMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2Vv\nVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6Csgncbz\nYEbYwbLVjDHZ3CB5JIG/NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5S\nJBri1WeR0IIQ13hLTytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHq\nZ38MN5aL5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7\nS4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/\nXvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266\nZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUapEBVYIAUJMA4GA1UdDwEB/wQE\nAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7srJerJsOflN4WT5CBP51o62sgU7X\nAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5\nFntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW4\n1uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa\n4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz\n4iIprn2DQKi6bA==\n-----END CERTIFICATE-----\n", - "GeoTrust Universal CA": "-----BEGIN CERTIFICATE-----\nMIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UE\nChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0\nMDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdl\nb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZI\nhvcNAQEBBQADggIPADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckU\nHUWCq8YdgNY96xCcOq9tJPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDg\nFgDgEB8rMQ7XlFTTQjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEY\nfyh3peFhF7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v\nc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+\n59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xdVHppCZbW2xHBjXWo\ntM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCXteGYO8A3ZNY9lO4L4fUorgtW\nv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2\nDs735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3\nwySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGj\nYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8G\nA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG\n9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRcaanQmjg8\n+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2qaav\ndy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL\noJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG\n8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzn\ns0ccjkxFKyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3k\nt0tm7wNFYGm2DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkD\nMBmhLMi9ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt\nDF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6\nZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=\n-----END CERTIFICATE-----\n", - "GeoTrust Universal CA 2": "-----BEGIN CERTIFICATE-----\nMIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UE\nChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcN\nMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN\nR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0G\nCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6Gq\ndHtXr0om/Nj1XqduGdt0DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSC\negx2oG9NzkEtoBUGFF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O\n64ceJHdqXbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL\nse4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaq\nW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IEr\nKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73y/Zl92zxlfgCOzJWgjl6W70v\niRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuU\nYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xf\nBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQID\nAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQ\nKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ\nKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+zdXkzoS9t\ncBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ4T7G\nzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+\nmbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEn\ncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8p\nRPPphXpgY+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp\n8RW04eWe3fiPpm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Bas\nx7InQJJVOCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH\n6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSL\nakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS\n-----END CERTIFICATE-----\n", - "America Online Root Certification Authority 1": "-----BEGIN CERTIFICATE-----\nMIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UE\nChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBD\nZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMw\nMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNV\nBAMTLUFtZXJpY2EgT25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0b\nfA+2l2h9LaaLl+lkhsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmL\nojNoWBym1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW\nOqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qG\nUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCu\nJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Z\no/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Zo/Z59m50qX8zPYEX10zPM94wDgYD\nVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3C\nYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B\n6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTI\ndGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C\nMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6dssPmuujz9\ndLQR6FgNgLzTqIA6me11zEZ7\n-----END CERTIFICATE-----\n", - "America Online Root Certification Authority 2": "-----BEGIN CERTIFICATE-----\nMIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UE\nChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBD\nZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgw\nMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNV\nBAMTLUFtZXJpY2EgT25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw\nDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3d\nxgz6sWYFas14tNwC206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238h\nZK+GvFciKtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2\nJxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBY\nBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMD\nbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8BPeraunzgWGcXuVjgiIZGZ2yd\nEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn6KVuY8INXWHQjNJsWiEOyiijzirp\nlcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp\n2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1\nuAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124Hhn\nAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj\nFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQEAwIBhjAN\nBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FYT15R\n/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p\n+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R\n+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMR\nn0T//ZoyzH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy\n7aULTd3oyWgOZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7\nlyoKZy2FAjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX\nOm/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y\n3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiC\nmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=\n-----END CERTIFICATE-----\n", - "Visa eCommerce Root": "-----BEGIN CERTIFICATE-----\nMIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYD\nVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNl\ncnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIw\nNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT\nQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAa\nBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQCvV95WHm6h2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVI\nsZHBAk4ElpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV\nZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzz\nlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0\nlUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBA\nMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMe\nzUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytM\niUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1k\nk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGI\nxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw\n++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt398znM/j\nra6O1I7mT1GvFpLgXPYHDw==\n-----END CERTIFICATE-----\n", - "Certum Root CA": "-----BEGIN CERTIFICATE-----\nMIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYD\nVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTEx\nMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRv\nIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAM6xwS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYV\nM42sLQnFdvkrOYCJ5JdLkKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82Kxu\njZlakE403Daaj4GIULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2\nbu4lXapuOb7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg\nAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEA\nAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESS\nbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIK\numB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvgGrZgFCdsMneMvLJymM/NzD+5yCRC\nFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQ\npNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6J\nQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==\n-----END CERTIFICATE-----\n", - "Comodo AAA Services root": "-----BEGIN CERTIFICATE-----\nMIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UE\nCAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21v\nZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0\nMDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdy\nZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENB\nIExpbWl0ZWQxITAfBgNVBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686td\nUIoWMQuaBtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe\n3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8Ioa\nE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULi\nmAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7S\nw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYD\nVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDov\nL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0\ndHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG\n9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q\nGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLzRt0vxuBq\nw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z8VlI\nMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C\n12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==\n-----END CERTIFICATE-----\n", - "Comodo Secure Services root": "-----BEGIN CERTIFICATE-----\nMIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UE\nCAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21v\nZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4X\nDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgM\nEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2Rv\nIENBIExpbWl0ZWQxJDAiBgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6\nEfQlhfPMcm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S\nHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJA\nGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtG\nCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz6YiO/O1R65NxTq0B50SOqy3L\nqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJ\nY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeG\nNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3Js\nMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNl\ncy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0\n5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmjZ55B+glS\nzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRLDXE9\n7IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw\npCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6s\nCx1HRR3B7Hzs/Sk=\n-----END CERTIFICATE-----\n", - "Comodo Trusted Services root": "-----BEGIN CERTIFICATE-----\nMIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UE\nCAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21v\nZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAe\nFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQI\nDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9k\nbyBDQSBMaW1pdGVkMSUwIwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWa\nHiWsnOWWfnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt\nTGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgym\nBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW1O24zG71++IsWL1/\nT2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7kUlcsutT6vifR4buv5XAwAaf\n0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1UdDgQWBBTFe1i97doladL3WRaoszLA\neydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqg\nOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu\nY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2Vy\ndmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/\nHrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32pSxBvzwG\na+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDABHcT\nuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l\nR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOj\nGM9O9y5Xt5hwXsjEeLBi\n-----END CERTIFICATE-----\n", - "QuoVadis Root CA": "-----BEGIN CERTIFICATE-----\nMIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcG\nA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0\neTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYD\nVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0\naG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTR\nvM16z/Ypli4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D\nrOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtf\nfp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZ\nyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospUxbF6lR1xHkopigPcakXBpBle\nbzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4wPQYIKwYBBQUHAQEEMTAvMC0GCCsG\nAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUw\nAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCB\nxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBw\nYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy\nZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJhY3RpY2Vz\nLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEWFmh0\ndHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu\nBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJN\nMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRp\nb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0\naG9yaXR5ggQ6tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70\nmpKnGdSkfnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8\n7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe\n/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsT\nIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJD\nWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOKSnQ2+Q==\n-----END CERTIFICATE-----\n", - "QuoVadis Root CA 2": "-----BEGIN CERTIFICATE-----\nMIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNV\nBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0w\nNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBR\ndW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqG\nSIb3DQEBAQUAA4ICDwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4Gt\nMh6QRr+jhiYaHv5+HBg6XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp\n3MJGF/hd/aTa/55JWpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsR\nE8Scd3bBrrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp\n+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI\n0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2\nBlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIizPtGo/KPaHbDRsSNU30R2be1B\n2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOhD7osFRXql7PSorW+8oyWHhqPHWyk\nYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyP\nZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQAB\no4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwz\nJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL\nMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1Zh\nZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUvZ+YT\nRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3\nUIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgt\nJodmVjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q8\n0m/DShcK+JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W\n6ZM/57Es3zrWIozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQj\nrLhVoQPRTUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD\nmbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6y\nhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO\n1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAF\nZdWCEOrCMc0u\n-----END CERTIFICATE-----\n", - "QuoVadis Root CA 3": "-----BEGIN CERTIFICATE-----\nMIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNV\nBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0w\nNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBR\ndW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqG\nSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTP\nkrgEQK0CSzGrvI2RaNggDhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZ\nz3HmDyl2/7FWeUUrH556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2Objyj\nPtr7guXd8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv\nvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mta\na7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJ\nk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1\nga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEXMJPpGovgc2PZapKUSU60rUqFxKMi\nMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArl\nzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQAB\no4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMw\ngcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0\naXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0aWZpY2F0\nZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYBBQUH\nAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD\nVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1\nXNu4ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEb\nMBkGA1UEAxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62g\nLEz6wPJv92ZVqyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon\n24QRiSemd1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd\n+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hR\nOJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j5\n6hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6l\ni92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8S\nh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7\nj2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEo\nkt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7\nzTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=\n-----END CERTIFICATE-----\n", - "Security Communication Root CA": "-----BEGIN CERTIFICATE-----\nMIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UE\nChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJv\nb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEY\nMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0\naW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8\nV6UMbXaKL0u/ZPtM7orw8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzG\njGdnSj74cbAZJ6kJDKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1ae\nV+7AwFb9Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N\nQV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OV\nYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZ\naNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG\n9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g0dNq/vu+m22/xwVtWSDEHPC32oRY\nAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7K\naEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKq\nL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfci\noU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==\n-----END CERTIFICATE-----\n", - "Sonera Class 2 Root CA": "-----BEGIN CERTIFICATE-----\nMIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UE\nChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoX\nDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UE\nAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAX\nSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gX\nGM2RX/uJ4+q/Tl18GybTdXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7\nJp12W5dCsv+u8E7s3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCW\nctRUz2EjvOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu\n8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0T\nAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB\nBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zilzqsWuasvfDXLrNAPtEwr/IDv\na4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEIcbCdjdY0RzKQxmUk96BKfARzjzlv\nF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHa\nPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj\n4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M\n-----END CERTIFICATE-----\n", - "Staat der Nederlanden Root CA": "-----BEGIN CERTIFICATE-----\nMIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwG\nA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJs\nYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNV\nBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0\nIGRlciBOZWRlcmxhbmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEAmNK1URF6gaYUmHFtvsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeI\nQGv33N0iYfXCxw719tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX9\n4p2i71MOhXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U\ntFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoL\nbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGO\nMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6\nLy93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQD\nAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEA\nBYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5\nfZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0\nC5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy\n7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsRiJf2fL1L\nuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==\n-----END CERTIFICATE-----\n", - "TDC Internet Root CA": "-----BEGIN CERTIFICATE-----\nMIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMG\nA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0w\nMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxU\nREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4Nr\nXceO+YQwzho7+vvOi20jxsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUA\npy6mcca8uYGoOn0a0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3\nWiAfAzc14izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN\neGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8kt\nCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBY\noFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRU\nREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JMMTArBgNVHRAEJDAigA8yMDAxMDQw\nNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQB\nx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1Ud\nEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUA\nA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX\nwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+2ARVPp7M\nVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzbO0ES\nm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU\nCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l\n-----END CERTIFICATE-----\n", - "UTN DATACorp SGC Root CA": "-----BEGIN CERTIFICATE-----\nMIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkG\nA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UE\nChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVz\ndC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0x\nOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNh\nbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT\nGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dD\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6\nE5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0\nvpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrL\nZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c\n3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorGkVl73v67SM\nvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8E\nBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAu\nhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUE\nIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB\nAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowftGzet/Hy+\nUUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0I3Kg\nqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx\nEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jF\nVkwPDPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI\n-----END CERTIFICATE-----\n", - "UTN USERFirst Hardware Root CA": "-----BEGIN CERTIFICATE-----\nMIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkG\nA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UE\nChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVz\ndC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQy\nWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQH\nEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD\nVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt\nSGFyZHdhcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn\n0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7Ho\nxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEH\nOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1p\nLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjfPe58BEydCl5rkdbux+0ojatNh4lz\n0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8G\nA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9\nMDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3\nYXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF\nBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM//bey1Wi\nCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogWXecB\n5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2\nlzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchq\nJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnAS\nfxAynB67nfhmqA==\n-----END CERTIFICATE-----\n", - "Camerfirma Chambers of Commerce Root": "-----BEGIN CERTIFICATE-----\nMIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UE\nChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3\nLmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAe\nFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQK\nEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cu\nY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIB\nIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1\nc2VHfRtbunXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d\nBmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IU\ntdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUM\nI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyXroDclDZK9D7ONhMeU+SsTjoF\n7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0f\nBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNy\nbDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCG\nSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3Jn\nMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN\nBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJzaWduLm9y\nZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAifJ/7\nkPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD\nL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QU\nu/wNUPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34Oi\nrsrXdx/nADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuz\nPu5ifdmA6Ap1erfutGWaIZDgqtCYvDi1czyL+Nw=\n-----END CERTIFICATE-----\n", - "Camerfirma Global Chambersign Root": "-----BEGIN CERTIFICATE-----\nMIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UE\nChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3\nLmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcN\nMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe\nQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNo\nYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0G\nCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQK\nkotgVvq0Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s\nQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjq\nGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8Co\nX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oP\nX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2\nMDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3Js\nMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZI\nAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5v\ncmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE\nVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hhbWJlcnNp\nZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEAPDtw\nkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y\ngOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76Svpyk\nBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHR\nJw0lyDL4IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxK\noHflCStFREest2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==\n-----END CERTIFICATE-----\n", - "NetLock Notary (Class A) Root": "-----BEGIN CERTIFICATE-----\nMIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYD\nVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxv\nemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UE\nAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5\nMDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdI\ndW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6\ndG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0\nTG9jayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWB\nxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QV\nOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWo\nDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+\npyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii\n7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8C\nAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEg\nRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz\naSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0\nZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJp\nenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0\nZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGph\ncmFzIGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxh\ncGphbiBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRv\nIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRo\nZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg\ndG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5l\ndC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUA\nA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXH\njFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jy\nf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEV\nZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q\n5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI\n-----END CERTIFICATE-----\n", - "NetLock Business (Class B) Root": "-----BEGIN CERTIFICATE-----\nMIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNV\nBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4x\nGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAo\nQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEw\nMjJaMIGZMQswCQYDVQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExv\nY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sx\nMjAwBgNVBAMTKU5ldExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGf\nMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK\ngZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kf\npPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4IC\nnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEB\nBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFu\neSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVu\nIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFt\nYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGku\nIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0\nIGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVn\ndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8v\nd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA\nbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQg\ndGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg\nQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUt\nbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFO\nzT4JwG06sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa\nn3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgB\nazMpUIaD8QFI\n-----END CERTIFICATE-----\n", - "NetLock Express (Class C) Root": "-----BEGIN CERTIFICATE-----\nMIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNV\nBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4x\nGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6\nIChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0\nMDgxMVowgZsxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0\nTG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRv\nazE0MDIGA1UEAxMrTmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFk\nbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA\nOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH\n0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEA\nAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG\n+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJNRklHWUVMRU0hIEV6ZW4gdGFudXNp\ndHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxl\naWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZv\nbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2\nZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs\nb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBsZWlyYXNh\nIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBodHRw\nczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y\nemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2Ug\nYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRM\nb2NrIENQUyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBi\neSBlLW1haWwgYXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKA\nCtiG8XmYta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g\npO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeA\nyNDYpQcCNJgEjTME1A==\n-----END CERTIFICATE-----\n", - "XRamp Global CA Root": "-----BEGIN CERTIFICATE-----\nMIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkG\nA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJh\nbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlm\naWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjEL\nMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMb\nWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2Vy\ndGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCY\nJB69FbS638eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP\nKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5df\nT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3\nhsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSP\npuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJ\nKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O\nBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwu\neHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcN\nAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR\nvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxtqZ4Bfj8p\nzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8nnxCb\nHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz\n8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=\n-----END CERTIFICATE-----\n", - "Go Daddy Class 2 CA": "-----BEGIN CERTIFICATE-----\nMIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UE\nChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAy\nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYy\nMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjEx\nMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAw\nDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWiz\nV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HF\niH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi\nEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN\nf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44\ndMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLEsNKR1EwRcbNhyz2h/t2oatTj\nMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2oatTjoWekZTBjMQswCQYDVQQGEwJV\nUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRk\neSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJ\nKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYX\nMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P\nTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQHmyW74cN\nxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VILs9R\naRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b\nvZ8=\n-----END CERTIFICATE-----\n", - "Starfield Class 2 CA": "-----BEGIN CERTIFICATE-----\nMIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UE\nChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENs\nYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5\nMTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2ll\ncywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRo\nb3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N\n78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMe\nj2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\nX9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4Umkhyn\nArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W\n93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRb\nVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDEL\nMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAw\nBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG\nA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1ep\noXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\neruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8\nU4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtH\nCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3\nQBFGmh95DmK/D5fs4C8fF5Q=\n-----END CERTIFICATE-----\n", - "StartCom Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UE\nChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUg\nU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN\nMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN\nU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2ln\nbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0G\nCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul3\n8kMKogZkpMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf\nOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYc\ncjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d\n5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9\nbZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z6+hsTXBbKWWc3apdzK8BMewM69KN\n6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHu\nEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZP\nV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOz\nEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID\nAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE\nFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQQa7y\nMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0\ndHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93\nd3cuc3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0\nYXJ0IENvbW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0\neSwgcmVhZCB0aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENv\nbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93\nd3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG\n+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkq\nhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqn\nUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/Jx\nXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myzieb\niMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MN\nq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww\n2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK\n1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLmKhQxw4Ut\njJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuEJnHEhV5xJMqlG2zY\nYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdibD4x3TrVoivJs\n9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=\n-----END CERTIFICATE-----\n", - "Taiwan GRCA": "-----BEGIN CERTIFICATE-----\nMIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYD\nVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9y\naXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAu\nBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJ\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN8\n6aXfTEc2pBsBHH8eV4qNw8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOU\nT0b3EEk3+qhZSV1qgQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQk\nclSGxtKyyhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts\nF/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBq\nnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUq\ndULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FCVGqY8A2tl+lSXunVanLeavcb\nYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNt\nsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6O\nM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMB\nAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkG\nBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK\nUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZTulStbng\nCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6TjZwj/\n5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2\nNe//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1\nAHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0\ndDzpD6QzDxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5L\nKlwCCDTb+HbkZ6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05e\nr/ayl4WXudpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz\nssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v\n3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS\n-----END CERTIFICATE-----\n", - "Firmaprofesional Root CA": "-----BEGIN CERTIFICATE-----\nMIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNV\nBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBD\nZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3\nDQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0\nMjIwMDAwWjCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJj\nZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVz\naW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25h\nbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u\nCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ov\nFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx\n/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPayBQC6haD9HThuy1q7hryUZzM1\ngywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8NeTvtjS0pbbELaW+0MOUJEjb35bT\nALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDov\nL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQk\nMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAd\nBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n\nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wqu00vR+L4\nOQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdfwUpg\npZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm\n7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/g\ne9YGVM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA=\n-----END CERTIFICATE-----\n", - "Wells Fargo Root CA": "-----BEGIN CERTIFICATE-----\nMIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDAS\nBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9u\nIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo\nb3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMx\nFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0\naW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBB\ndXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUE\nR84A4n135zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE\nSxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9\ni86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43\nYjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQt\nnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8w\nTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3Lndl\nbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvIC\ntUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZW\nohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7\nnX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zxx32l2w8n\n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023tqcZ\nZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=\n-----END CERTIFICATE-----\n", - "Swisscom Root CA 1": "-----BEGIN CERTIFICATE-----\nMIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYD\nVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNh\ndGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2\nMjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTEl\nMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Nj\nb20gUm9vdCBDQSAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h\n+BvVM5OAFmUgdbI9m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrW\nW/oLJdihFvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/\nTilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdnt\nMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJ\nvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJn\nB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbNcA78yeNmuk6NO4HLFWR7uZToXTNS\nhXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyD\nCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0W\nR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p\n/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw\nFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0jBBgwFoAU\nAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9MA0G\nCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn\njgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzn\neAXQMbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL\n0iT43R4HVtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZ\nNuR55LU/vJtlvrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLH\nUKKwf4ipmXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH\nb6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBa\nZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7G\nh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5g\nmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6MBr1mmz0DlP5OlvRHA==\n-----END CERTIFICATE-----\n", - "DigiCert Assured ID Root CA": "-----BEGIN CERTIFICATE-----\nMIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYD\nVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu\nY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAw\nMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg\nSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1\ncmVkIElEIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOA\nXLGH87dg+XESpa7cJpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lT\nXDGEKvYPmDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+\nwRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/l\nbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcX\nxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQE\nAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF66Kv9JLLgjEtUYunpyGd823IDzAf\nBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog68\n3+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqo\nR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+\nfT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx\nH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe+o0bJW1s\nj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==\n-----END CERTIFICATE-----\n", - "DigiCert Global Root CA": "-----BEGIN CERTIFICATE-----\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYD\nVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu\nY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa\nFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx\nGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBS\nb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKP\nC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscF\ns3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6g\nSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSii\ncNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgw\nFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1E\nnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDi\nqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBA\nI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29\nC79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-----END CERTIFICATE-----\n", - "DigiCert High Assurance EV Root CA": "-----BEGIN CERTIFICATE-----\nMIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYD\nVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu\nY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2\nMTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp\nZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNl\ncnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMbM5XPm+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlB\nWTrT3JTWPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\nxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeB\nQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5\nOYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsgEsxBu24LUTi4S8sCAwEAAaNj\nMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9H\nAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3\nDQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1\nntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VH\nMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\nYzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCevEsXCS+0\nyx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K\n-----END CERTIFICATE-----\n", - "Certplus Class 2 Primary CA": "-----BEGIN CERTIFICATE-----\nMIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkG\nA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkg\nQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8G\nA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxv\nc0NXYKwzCkTsA18cgCSR5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLR\nYE2+L0ER4/YXJQyLkcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v\n0lPubNCdEgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas\nH7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC\n40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNV\nHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQw\nMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29tL0NSTC9jbGFzczIuY3JsMA0GCSqG\nSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5t\nn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabg\nlZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW\n2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB\nkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7l7+ijrRU\n-----END CERTIFICATE-----\n", - "DST Root CA X3": "-----BEGIN CERTIFICATE-----\nMIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYD\nVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENB\nIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRh\nbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJ\nKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdA\nwRgUi+DoM3ZJKuM/IUmTrE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwG\nMoOifooUMM0RoOEqOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4X\nLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkq\ntilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\nHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqGSIb3DQEBBQUAA4IBAQCjGiyb\nFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikugdB/OEIKcdBodfpga3csTS7MgROSR\n6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaL\nbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir\n/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06Xyx\nV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n-----END CERTIFICATE-----\n", - "DST ACES CA X6": "-----BEGIN CERTIFICATE-----\nMIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYD\nVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERT\nVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzEx\nMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBU\ncnVzdDERMA8GA1UECxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5\nDgO0PWGSvSMmtWPuktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+io\nkYi5Q1K7gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH\nfAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd7\n55jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEITajV8fTXpLmaRcpPV\nMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD\nAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3QuY29tMGIGA1UdIARbMFkwVwYKYIZI\nAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZp\nY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7\neI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99\nPe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/\nh40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQqnExaBqXp\nIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXsvFcj\n4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3\noKfN5XozNmr6mis=\n-----END CERTIFICATE-----\n", - "TURKTRUST Certificate Services Provider Root 1": "-----BEGIN CERTIFICATE-----\nMIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVT\nVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQG\nDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJp\nbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe\nLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RS\nVVNUIEVsZWt0cm9uaWsgU2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNV\nBAYMAlRSMQ8wDQYDVQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1Qg\nQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu\nxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFb\nazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1\ncJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35JYbOG7E6mQW6EvAPs9TscyB/C\n7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFd\nSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4\nf2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3\nDQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd\n82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh\nfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55FyB0SFHljK\nVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgYnNN9\naV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H\n-----END CERTIFICATE-----\n", - "TURKTRUST Certificate Services Provider Root 2": "-----BEGIN CERTIFICATE-----\nMIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVT\nVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQG\nEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0\nacWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2Fz\nxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2\nVMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8Sx\nMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJp\nbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe\nLiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7D\nkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9\nirWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDc\nRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52\nYItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp\n48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQW\nBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMB\nAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq\nECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4Jl3vpao6\n+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+hGIA\nF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P\n9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9R\nnuk5UrbnBEI=\n-----END CERTIFICATE-----\n", - "SwissSign Gold CA - G2": "-----BEGIN CERTIFICATE-----\nMIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNI\nMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0g\nRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMG\nA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIIC\nIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJC\nEyq8ZVeCQD5XJM1QiyUqt2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcf\nDmJlD909Vopz2q5+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpi\nkJKVyh+c6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE\nemA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT\n28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdV\nxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02yMszYF9rNt85mndT9Xv+9lz4p\nded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkOpeUDDniOJihC8AcLYiAQZzlG+qkD\nzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR7ySArqpWl2/5rX3aYT+Ydzyl\nkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+Zr\nzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\nFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn\n8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDovL3JlcG9z\naXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm5djV\n9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr\n44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8\nAYOfMke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0V\nqbe/vd6mGu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9Qkvfsywe\nxcZdylU6oJxpmo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/Eb\nMFYOkrCChdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3\n92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG\n2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/Y\nYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkk\nW8mw0FfB+j564ZfJ\n-----END CERTIFICATE-----\n", - "SwissSign Silver CA - G2": "-----BEGIN CERTIFICATE-----\nMIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gx\nFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAt\nIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTAT\nBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcy\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dO\ncbpLj6VzHVxumK4DV644N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGi\nTSf5YXu6t+WiE7brYT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi\n0R86TieFnbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH\n6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyC\nbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jM\nqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/\n+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBsROopN4WSaGa8gzj+ezku01DwH/te\nYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIj\nQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calI\nLv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV\nHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c\nwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0cDovL3Jl\ncG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P4JUw\n4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F\nkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcS\nH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkD\nlm4fS/Bx/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakM\nDHiqYMZWjwFaDGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHk\nFlt4dR2Xem1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR\ndAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29\nMC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI\n4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s\n5Aq7KkzrCWA5zspi2C5u\n-----END CERTIFICATE-----\n", - "GeoTrust Primary Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYD\nVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJp\nbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYy\nMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQD\nEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92\n/ZV+zmEwu3qDXwK9AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa\n9OBesYjAZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0\n7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0\nEME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s\n0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV\nHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZIhvcNAQEFBQADggEBAFpwfyzdtzRP\n9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z\n+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD3\n2sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJly\nc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU\nAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=\n-----END CERTIFICATE-----\n", - "thawte Primary Root CA": "-----BEGIN CERTIFICATE-----\nMIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkG\nA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlv\nbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0g\nRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3Qg\nQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTAT\nBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBE\naXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6\nZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3\n/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29\ndGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk6KHYcWUNo1F77rzSImANuVud\n37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9\nyZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+\nYf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G\nA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7OR\ntvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz\nYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAXxPcW6cTY\ncvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89jxt5\ndovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH\nz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==\n-----END CERTIFICATE-----\n", - "VeriSign Class 3 Public Primary Certification Authority - G5": "-----BEGIN CERTIFICATE-----\nMIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkG\nA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU\ncnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh\ndXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQ\ncmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcN\nMzYwNzE2MjM1OTU5WjCByjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMu\nMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBW\nZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\nU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0g\nRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8\nRRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs70PbZmIVYc9g\nDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ0\n23tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9\nr911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MU\nCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNV\nHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\nBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u\nY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqGSIb3\nDQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+\nX6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU\n7qKEKQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMt\nEMze/aiCKm0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7\nMzVIcbidJ4vEZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq\n-----END CERTIFICATE-----\n", - "SecureTrust CA": "-----BEGIN CERTIFICATE-----\nMIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYD\nVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNl\nY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UE\nBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1\ncmVUcnVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7C\nT8rU4niVWJxB4Q2ZQCQXOZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29\nvo6pQT64lO0pGtSO0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZ\nbf2IzIaowW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj\n7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xH\nCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIE\nBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE\n/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL2NybC5zZWN1cmV0cnVz\ndC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDt\nT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQ\nf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cp\nrp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS\nCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR3ItHuuG5\n1WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=\n-----END CERTIFICATE-----\n", - "Secure Global CA": "-----BEGIN CERTIFICATE-----\nMIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYD\nVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNl\nY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYD\nVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNl\nY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxV\naQZx5RNoJLNP2MwhR/jxYDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6Mpjh\nHZevj8fcyTiW89sa/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ\n/kG5VacJjnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI\nHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPi\nXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGC\nNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9E\nBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJl\ndHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IB\nAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQV\nDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895\nP4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY\niNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xcf8LDmBxr\nThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW\n-----END CERTIFICATE-----\n", - "COMODO Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkG\nA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9y\nZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZp\nY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQsw\nCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxm\nb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRp\nZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECL\ni3LjkRv3UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI\n2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7eu\nNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC\n8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQF\nZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVIrLsm9wIDAQABo4GOMIGLMB0GA1Ud\nDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw\nAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9D\nZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5\nt3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv\nIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/RxdMosIG\nlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmcIGfE\n7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN\n+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==\n-----END CERTIFICATE-----\n", - "Network Solutions Certificate Authority": "-----BEGIN CERTIFICATE-----\nMIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYD\nVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO\nZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAw\nWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1\ndGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBB\ndXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xG\nzuAnlt7e+foS0zwzc7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQ\nNJIg6nPPOCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl\nmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1\nQV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMh\nqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA\n106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MFIGA1Ud\nHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25z\nQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ot\nt3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVR\nDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH\n/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3HtvwKeI8lN3\ns2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxDydi8\nNmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey\n-----END CERTIFICATE-----\n", - "WellsSecure Public Root Certificate Authority": "-----BEGIN CERTIFICATE-----\nMIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNV\nBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5r\nIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo\nb3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMx\nIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJn\nbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0\nZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGe\nOARBJe+rWxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU\nDk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4\nS78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN\n7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFafSZtsdvqKXfcBeYF8wYNABf5x\n/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMBAAGjggE0MIIBMDAPBgNVHRMBAf8E\nBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29t\nL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+\n0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkG\nA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX\nZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBD\nZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPIK013\n4/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0\nbh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1\nNSljqHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE\n13YgY+esE2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvU\nFpULB6ouFJJJtylv2G0xffX8oRAHh84vWdw+WNs=\n-----END CERTIFICATE-----\n", - "COMODO ECC Certification Authority": "-----BEGIN CERTIFICATE-----\nMIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UE\nBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEa\nMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlm\naWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTEL\nMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2Fs\nZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0Mg\nQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmC\nFYX7deSRFtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J\ncfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZ\nSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq\nhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDmfQjGGoe9GKhzvSbKYAydzpmf\nz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeAU/7dIOA1mjbRxwG55tzd8/8dLDoW\nV9mSOdY=\n-----END CERTIFICATE-----\n", - "IGC/A": "-----BEGIN CERTIFICATE-----\nMIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8w\nDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYD\nVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5w\nbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYT\nAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0RO\nMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FA\nc2dkbi5wbS5nb3V2LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLF\nMzvABIaIs9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2\nxtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfR\nNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUz\naJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAxVs5wKpayMLh35nnAvSk7/ZR3\nTL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQtQIDAQABo3cwdTAPBgNVHRMBAf8E\nBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSj\nBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjAN\nBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2\nFLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY\nYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsgCrpa/Jos\nPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNIlQgR\nHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF\n0mBWWg==\n-----END CERTIFICATE-----\n", - "Security Communication EV RootCA1": "-----BEGIN CERTIFICATE-----\nMIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UE\nChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29t\nbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlow\nYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4x\nKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1\nOXj/l3X3L+SqawSERMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1\nV4qe70gOzXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5\nbmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5\nkd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+z\nyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eCOKyrcWUXdYydVZPmMA4GA1Ud\nDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBn\nXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRG\nef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXk\ngKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF7\n5x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O\nVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490\n-----END CERTIFICATE-----\n", - "OISTE WISeKey Global Root GA CA": "-----BEGIN CERTIFICATE-----\nMIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkG\nA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAw\nNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUg\nV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5\nNTFaMIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJp\nZ2h0IChjKSAyMDA1MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYD\nVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEF\nAAOCAQ8AMIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR\nVVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSL\ntZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dy\noJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg4E8HsChWjBgbl0SOid3gF27n\nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3RLoGbw9ho972WG6xwsRYUC9tguSYB\nBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+\nrja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEB\nAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VF\nvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8\nvPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXahNVQA7bi\nhKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEYokxS\ndsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=\n-----END CERTIFICATE-----\n", - "Microsec e-Szigno Root CA": "-----BEGIN CERTIFICATE-----\nMIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkG\nA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQw\nEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBD\nQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYD\nVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temln\nbm8gQ0ExIjAgBgNVBAMTGU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICb\nPHiN1I2uuO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+\nLMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOS\nJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw\n7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx62z69Rrkav17fVVA71hu5tnV\nvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBz\nOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemln\nbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFi\nBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1\nL1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5\nACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBnAGEAZADh\nAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA4QBs\nAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg\nAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAt\nAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSG\nIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3pp\nZ25vLmh1L0NOPU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8l\nMjBDQSxPPU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv\nY2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9A\nZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEW\nMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UE\nBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3\nQJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoT\nDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3Nl\nYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZh\nhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds\nZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl7tnlJNUb\n3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a86g4nzUGCM4ilb7N\n1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehKyVZs15KrnfVJ\nONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQBS6kRnSlq\nLtBdgcDPsiBDxwPgN05dCtxZICU=\n-----END CERTIFICATE-----\n", - "Certigna": "-----BEGIN CERTIFICATE-----\nMIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZS\nMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMw\nNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczER\nMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ\n1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lI\nzw7sebYs5zRLcAglozyHGxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxr\nyIRWijOp5yIVUxbwzBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJb\nzg4ij02Q130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2\nJsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0T\nAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AU\nGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlt\neW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEG\nCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl\n1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxA\nGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9q\ncEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w\nt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/QwWyH8EZE0\nvkHve52Xdf+XlcCWWC/qu0bXu+TZLg==\n-----END CERTIFICATE-----\n", - "AC Raíz Certicámara S.A.": "-----BEGIN CERTIFICATE-----\nMIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV\nBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERp\nZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6Ft\nYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJD\nTzFHMEUGA1UECgw+U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFs\nIC0gQ2VydGljw6FtYXJhIFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBT\nLkEuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgI\nem08kBeGqentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL\nfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cS\nsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLY\nvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ54v5aHxwD6Mq0Do43zeX4lve\ngGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIu\nmGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeR\nyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVT\nP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBk\nAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ\npxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd\nBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0gADCB\niTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF\nBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8g\nc2UgcHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4\nRZFNjmEfAygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz\n75uny3XlesuXEpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i\n4z0ldma/Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp\nezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI\n8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIP\nPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44b\nb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6\n/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X\n94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ\n7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ==\n-----END CERTIFICATE-----\n", - "TC TrustCenter Class 2 CA II": "-----BEGIN CERTIFICATE-----\nMIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UE\nBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0\nQ2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0Eg\nSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoG\nA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xh\nc3MgMiBDQTElMCMGA1UEAxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJ\nKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/R\nKrLqk2jftMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg\nuNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqki\nRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9\nH7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+995OKdy1u2bv/jzVrndIIFuoAl\nOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD\nAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHc\noIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJ\nLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUy\nMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290\nY2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9i\nYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4GdXpo\nUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ\nKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1\nKdsjTYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbq\nNZn1l7kPJOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcX\njFq32nQozZfkvQ==\n-----END CERTIFICATE-----\n", - "TC TrustCenter Class 3 CA II": "-----BEGIN CERTIFICATE-----\nMIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UE\nBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0\nQ2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0Eg\nSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoG\nA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xh\nc3MgMyBDQTElMCMGA1UEAxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJ\nKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJ\nDRoeIMJWHt4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q\nVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogk\nAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdz\ns5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5\nSpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD\nAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHc\noIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJ\nLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUy\nMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290\nY2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9i\nYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzEO2ea\ntN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8\nyRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL\n2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+Gzj\nBgnyXlal092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v\n+5ZWgOI2F9Hc5A==\n-----END CERTIFICATE-----\n", - "TC TrustCenter Universal CA I": "-----BEGIN CERTIFICATE-----\nMIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UE\nBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0\nQ2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2Fs\nIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEc\nMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIg\nVW5pdmVyc2FsIENBMSYwJAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCC\nASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B\n6DGtxnSRJJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T\nfCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPi\nUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+\nF1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQfezmlwQek8wiSdeXhrYTCjxD\nI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0jBBgwFoAUkqR1LKSevoFE63n8isWV\npesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyk\nnr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8R\nMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNer\nNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs\nydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPTujdEWBF6\nAmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a7CIM\nHOCkoj3w6DnPgcB77V0fb8XQC9eY\n-----END CERTIFICATE-----\n", - "Deutsche Telekom Root CA 2": "-----BEGIN CERTIFICATE-----\nMIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UE\nChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRl\ncjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAw\nWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVs\nZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1\ndHNjaGUgVGVsZWtvbSBSb290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQCrC6M14IspFLEUha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1c\nOs7TuKhCQN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr\nrFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1\nUdrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFh\nmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0G\nA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB\n/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f7\n6Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSY\nSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juw\nzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+\nxbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mUCm26OWMo\nhpLzGITY+9HPBVZkVw==\n-----END CERTIFICATE-----\n", - "ComSign Secured CA": "-----BEGIN CERTIFICATE-----\nMIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkG\nA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJ\nTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24g\nU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjW\naueP1H5XJLkGieQcPOqs49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqY\nHU4Gk/v1iDurX8sWv+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20\nIZFKF3ueMv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr\n9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z\n1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRw\nOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNlY3VyZWRDQS5jcmwwDgYDVR0P\nAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTB\nS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq\n1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tM\nM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAm\nlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL\nhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQzOjRXUDpv\ngV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==\n-----END CERTIFICATE-----\n", - "Cybertrust Global Root": "-----BEGIN CERTIFICATE-----\nMIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMP\nQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2\nMTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5j\nMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO2\n1O1fWLE3TdVJDm71aofW0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2O\nlTEQXO2iLb3VOm2yHLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeW\nP032a7iPt3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz\nFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQID\nAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2\nCHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJs\naWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8GA1UdIwQYMBaAFLYIew16zKwgTIZW\nMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ej\nhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24C\nJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+z\nv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc\nA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jWWL1WMRJO\nEcgh4LMRkWXbtKaIOM5V\n-----END CERTIFICATE-----\n", - "ePKI Root Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYD\nVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsM\nIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0z\nNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29t\nIENvLiwgTHRkLjEqMCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U\n82N0ywEhajfqhFAHSyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrB\np0xtInAhijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X\nDZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZr\nxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ad\no4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffAsgRFelQArr5T9rXn4fg8ozHS\nqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ETOxQvdibBjWzwloPn9s9h6PYq2l\nY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUa\ndCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+Xk\nwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3\npyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF\nMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLHClZ87lt4\nDJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B01GqZ\nNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq\nKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnV\nvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltab\nrNMdjmEPNXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc\n7b3jajWvY9+rGNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8\nGrBQAuUBo2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS\n/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C\n6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yI\nVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4\nEZw=\n-----END CERTIFICATE-----\n", - "TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3": "-----BEGIN CERTIFICATE-----\nMIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYD\nVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRl\na25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVz\nYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0g\nVUVLQUUxIzAhBgNVBAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFU\nw5xCxLBUQUsgVUVLQUUgS8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAt\nIFPDvHLDvG0gMzAeFw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UE\nBhMCVFIxGDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls\naW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBG\nBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5z\ndGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkx\nSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xh\necSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\nim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6V\nQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+81\n8qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw\nlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oLhmUZEdPp\nCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAdBgNV\nHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF\nMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTf\nvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpN\neBLWrcLTy9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceE\nxh/VS4ESshYhLBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0\na+IDRM5noN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs\nyZyQ2uypQjyttgI=\n-----END CERTIFICATE-----\n", - "Buypass Class 2 CA 1": "-----BEGIN CERTIFICATE-----\nMIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UE\nCgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAx\nMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNV\nBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0Eg\nMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE4\n25KEHK8T1A9vNkYgxC7McXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2l\nFYxuyHyXA8vmIPLXl18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTX\njAePzdVBHfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B\n5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9E\ndrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\nFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUA\nA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdl\nyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaa\nkZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZS\nr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+o\nRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho\n-----END CERTIFICATE-----\n", - "Buypass Class 3 CA 1": "-----BEGIN CERTIFICATE-----\nMIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UE\nCgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAx\nMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNV\nBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0Eg\nMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZE\nC4DVC69TB4sSveZn8AKxifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhj\nP5JW3SROjvi6K//zNIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IX\nF4Rs4HyI+MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R\nhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3\nlRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\nFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUA\nA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6\nOyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT\n+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs\n5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4ok\noyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915\n-----END CERTIFICATE-----\n", - "EBG Elektronik Sertifika Hizmet Sağlayıcısı": "-----BEGIN CERTIFICATE-----\nMIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VC\nRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQK\nDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYD\nVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9F\nQkcgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UE\nCgwuRUJHIEJpbGnFn2ltIFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkG\nA1UEBhMCVFIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4\nf6en5f2h4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk\ntiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggD\ng3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3M\nenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4c0JqwmZ2sQomFd2TkuzbqV9U\nIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGyY5lhcucqZJnSuOl14nypqZoaqsNW\n2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBV\nFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5H\nd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8\nowrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2\nl9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB\nBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wWZ5b6\nSqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t\nFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVG\noGgmzJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswno\nT4cCB64kXPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7\ns9QJ/XvCgKqTbCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKf\nAB5UVUJnxk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q\nDgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN\n4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP\n14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3\nx0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIU\npgqT\n-----END CERTIFICATE-----\n", - "certSIGN ROOT CA": "-----BEGIN CERTIFICATE-----\nMIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREw\nDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQx\nNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lH\nTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBALczuX7IJUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oq\nrl0Hj0rDKH/v+yv6efHHrfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsA\nfsT8AzNXDe3i+s5dRdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUo\nSe1b16kQOA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv\nJoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNC\nMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPx\nfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJLjX8+HXd5n9liPRyTMks1zJO\n890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6\nIJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KT\nafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI\n0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5V\naZVDADlN9u6wWk5JRFRYX0KD\n-----END CERTIFICATE-----\n", - "CNNIC ROOT": "-----BEGIN CERTIFICATE-----\nMIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwG\nA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcw\nNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNO\nTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LR\nb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx\n3zkBwRP9SFIhxFXf2tizVHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJ\nMfAw28Mbdim7aXZOV/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPih\nNIaj3XrCGHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN\nv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIA\nBzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsG\nA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO76bVOxEwDQYJKoZIhvcNAQEF\nBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMX\nYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23\nxzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftO\nhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8\nyGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=\n-----END CERTIFICATE-----\n", - "ApplicationCA - Japanese Government": "-----BEGIN CERTIFICATE-----\nMIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UE\nChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEy\nMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBh\nbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdh\njYq+xpqcBrSGUeQ3DnR4fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7\nNCPbXCbkcXmP1G55IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH\n/OlQR9cwFO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht\nQWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW\n8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8B\nAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzl\nm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseODvOOCt+ODp+ODs0NBMA8GA1UdEwEB\n/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJ\nfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsv\ncJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc\n/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj\nB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdLrosot4LK\nGAfmt1t06SAZf7IbiVQ=\n-----END CERTIFICATE-----\n", - "GeoTrust Primary Certification Authority - G3": "-----BEGIN CERTIFICATE-----\nMIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkG\nA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdl\nb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1\nc3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAw\nMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJ\nbmMuMTkwNwYDVQQLEzAoYykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQg\ndXNlIG9ubHkxNjA0BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRo\nb3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz\n+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD6\n14SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeD\nXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/WJmxsYAQlTlV+fe+/lEjetx3d\ncI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ\n6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB\n/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqG\nSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTT\nOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN\nkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGDAWh9jUGh\nlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33st/3L\njWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt\n-----END CERTIFICATE-----\n", - "thawte Primary Root CA - G2": "-----BEGIN CERTIFICATE-----\nMIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UE\nBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3Rl\nLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmlt\nYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQsw\nCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0\naGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3Rl\nIFByaW1hcnkgUm9vdCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFS\neIf+iha/BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6\npapu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/\nMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZI\nzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3KMqh9HneteY4sPBlcIx/AlTC\nv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3Krr0TKUQNJ1uo52icEvdYPy5yAlej\nj6EULg==\n-----END CERTIFICATE-----\n", - "thawte Primary Root CA - G3": "-----BEGIN CERTIFICATE-----\nMIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkG\nA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlv\nbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0g\nRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg\nQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJV\nUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZp\nY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0\naG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu\n86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/E\nth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3To\nO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY7CFJXJv2eul/VTV+lmuNk5Mny5K7\n6qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiY\nnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB\n/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQAD\nggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW\noCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1but8jLZ8HJ\nnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC8rZc\nJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm\ner/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=\n-----END CERTIFICATE-----\n", - "GeoTrust Primary Certification Authority - G2": "-----BEGIN CERTIFICATE-----\nMIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UE\nBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1Ry\ndXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3Qg\nUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoX\nDTM4MDExODIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMu\nMTkwNwYDVQQLEzAoYykgMjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl\nIG9ubHkxNjA0BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp\ndHkgLSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL\nSo17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf\n691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSW\nWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7mndwxHLKgpxgceeHHNgIwOlavmnRs\n9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2npaqBA+K\n-----END CERTIFICATE-----\n", - "VeriSign Universal Root Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkG\nA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU\ncnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBh\ndXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBD\nZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTla\nMIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl\ncmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMu\nIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh\nbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbna\nzU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWHH26MfF8WIFFE0XBPV+rjHOPM\nee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL729fdC4uW/h2KJXwBL38Xd5HVEMkE6\nHnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ\n79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQAB\no4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEw\nX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs\nexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1UdDgQWBBS2\nd/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3Y8xu\nTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx\nY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahf\nYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tew\nXDpPaj+PwGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WI\ng0vvBZIGcfK4mJO37M2CYfE45k+XmCpajQ==\n-----END CERTIFICATE-----\n", - "VeriSign Class 3 Public Primary Certification Authority - G4": "-----BEGIN CERTIFICATE-----\nMIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UE\nBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz\ndCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo\nb3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt\nYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgw\nMTE4MjM1OTU5WjCByjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8w\nHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJp\nU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln\nbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQw\ndjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmD\niWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3vefLK+ymVhAIau2o970ImtTR1Z\nmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYI\nKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoas\njY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYw\nHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgm\nYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga\nFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==\n-----END CERTIFICATE-----\n", - "NetLock Arany (Class Gold) Főtanúsítvány": "-----BEGIN CERTIFICATE-----\nMIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTER\nMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFu\nw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwws\nTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjEx\nMTUwODIxWhcNMjgxMjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFw\nZXN0MRUwEwYDVQQKDAxOZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lh\nZMOzayAoQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkg\nKENsYXNzIEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFtt\nvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn\n7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5VA1lddkVQZQBr17s9o3x/61k\n/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7\nGRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiL\no0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpn\nk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ\n5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C\n+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzCbLBQWV2Q\nWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5KfnaNwUA\nSZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu\ndZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=\n-----END CERTIFICATE-----\n", - "Staat der Nederlanden Root CA - G2": "-----BEGIN CERTIFICATE-----\nMIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwG\nA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJs\nYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjEL\nMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwi\nU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD\nggIPADCCAgoCggIBAMVZ5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZ\nqhQlEq0i6ABtQ8SpuOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU2\n54DBtvPUZ5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE\npMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV\n3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9\nwhUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2U\nuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V6548r6f1CGPqI0GAwJaCgRHOThuVw+\nR7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/\nPlemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymY\nNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov\nL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNVHQ8BAf8E\nBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUAA4IC\nAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz\n+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUX\nvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sU\nOlWDuYaNkqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fM\ndWVSSt7wsKfkCpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2t\nUKRXCnxLvJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm\nbEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8s\nV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXq\nZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOL\nnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ==\n-----END CERTIFICATE-----\n", - "CA Disig": "-----BEGIN CERTIFICATE-----\nMIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UE\nBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcw\nHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UE\nBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6\nUShGhJd4NLxs/LxFWYgmGErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhq\nFQ4/61HhVKndBpnXmjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaS\nfQUMbEYDXcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW\nS8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJd\nKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\nFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nh\nb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAt\noCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZo\ndHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuB\nHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA\n/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq\nEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/CBUz91BK\nez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6Kezfq\nwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA\n4Z7CRneC9VkGjCFMhwnN5ag=\n-----END CERTIFICATE-----\n", - "Juur-SK": "-----BEGIN CERTIFICATE-----\nMIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglw\na2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vz\na3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVow\nXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMg\nU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B8\n41oiqBB4M8yIsdOBSvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/\nmX8MCgkzABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH\nLCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGz\nlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQ\nn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8wggEWBgNVHSAEggENMIIBCTCC\nAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHDHoHAAFMAZQBlACAAcwBlAHIAdABp\nAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBz\nACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABh\nAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABh\nAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f\nBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYEFASqekej\n5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4GA1Ud\nDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo\nERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbR\nxZyLabVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+\nNe6ML678IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/\nZEuOyoqysOkhMp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aW\nAuVrua0ZTbvGRNs2yyqcjg==\n-----END CERTIFICATE-----\n", - "Hongkong Post Root CA 1": "-----BEGIN CERTIFICATE-----\nMIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNV\nBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4X\nDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT\nDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSS\nHSL22oVyaf7XPwnU3ZG1ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8g\nPW2iNr4joLFutbEnPzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7j\nEAaPIpjhZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9\nnnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208\no1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQE\nAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsCmEEIjEy82tvuJxuC52pF7BaL\nT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37piol7Yutmcn1KZJ/RyTZXaeQi/cImya\nT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgC\nIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES\n7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4Jx\nHYB0yvbiAmvZWg==\n-----END CERTIFICATE-----\n", - "SecureSign RootCA11": "-----BEGIN CERTIFICATE-----\nMIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UE\nChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJl\nU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNV\nBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRww\nGgYDVQQDExNTZWN1cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA/XeqpRyQBTvLTJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1y\nfIw/XwFndBWW4wI8h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyK\nyiyhFTOVMdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9\nUK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V\n1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsCh8U+iQIDAQABo0Iw\nQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud\nEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKChOBZmLqdWHyGcBvod7bkixTgm2E5P\n7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI\n6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAY\nga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR\n7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN\nQSdJQO7e5iNEOdyhIta6A/I=\n-----END CERTIFICATE-----\n", - "ACEDICOM Root": "-----BEGIN CERTIFICATE-----\nMIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNF\nRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVT\nMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00g\nUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjAN\nBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7\nw2rbYgIB8hiGtXxaOLHkWLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auOD\nAKgrLlUTY4HKRxx7XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW1\n0W2ZEi5PGrjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK\nt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ\n1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQA\ntwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQUfecyuB+81fFOvW8XAjnXDpVC\nOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTu\ntYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27\nk5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MC\nAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB\n53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw\nRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNvbS5lZGlj\nb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqgaHtP\nkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP\neGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH\n1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf\n8seACQl1ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7\ntq3PgbUhh8oIKiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtP\nF2Y9fwsZo5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6\nzqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQY\nXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyl\neW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+\nKzgHVZhepA==\n-----END CERTIFICATE-----\n", - "Microsec e-Szigno Root CA 2009": "-----BEGIN CERTIFICATE-----\nMIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJI\nVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMM\nHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0Bl\nLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQG\nEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNV\nBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5m\nb0BlLXN6aWduby5odTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG\n2KfgQvvPkd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc\ncbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDH\nQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqp\nGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV\n87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQF\nMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAf\nBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3pp\nZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5Dw\npL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk\nddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775tyERzAMB\nVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02yULy\nMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi\nLXpUq3DDfSJlgnCW\n-----END CERTIFICATE-----\n", - "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi": "-----BEGIN CERTIFICATE-----\nMIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYD\nVQQGEwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoG\nA1UEAxMzZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWlj\naXNpMB4XDTA3MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAm\nBgNVBAoTH0VsZWt0cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2\nZW4gS29rIEVsZWt0cm9uaWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJ\nKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDB\nS75+PNdUMZTe1RK6UxYC6lhj71vY8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlT\nL/jDj/6z/P2douNffb7tC+Bg62nsM+3YjfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy\n2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAIJjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+T\nzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+t\niEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w\nHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqGSIb3DQEBBQUAA4IBAQB/X7lT\nW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5dF4dvaAXBlGzZXd/aslnL\npRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwqD2fK/A+JYZ1lpTzl\nvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4Vwpm+Vganf2X\nKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtqfJ7lddK2\nl4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX\n-----END CERTIFICATE-----\n", - "GlobalSign Root CA - R3": "-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMX\nR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMT\nCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQL\nExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UE\nAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5Bngi\nFvXAg7aEyiie/QV2EcWtiHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0M\nK66X17YUhhB5uzsTgHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL\n0gRgykmmKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613\nt2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQD\nAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0G\nCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7lgAJQayzE4aGKAczymvmdLm6AC2u\npArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdW\nPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0\n095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJr\nlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----\n", - "TC TrustCenter Universal CA III": "-----BEGIN CERTIFICATE-----\nMIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UE\nBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0\nQ2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2Fs\nIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRF\nMRwwGgYDVQQKExNUQyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRl\nciBVbml2ZXJzYWwgQ0ExKDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJ\nSUkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmz\nNEubkKLF5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv\nDIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f\n/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkht\nWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yjdipFtK+/fz6HP3bFzSreIMUW\nWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozh\ncbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW\n5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22J\nLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhn\nYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G\nDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZVCIgJwcyR\nGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIqwoII\nlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==\n-----END CERTIFICATE-----\n", - "Autoridad de Certificacion Firmaprofesional CIF A62634068": "-----BEGIN CERTIFICATE-----\nMIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMx\nQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwg\nQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNV\nBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zl\nc2lvbmFsIENJRiBBNjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDK\nlmuO6vj78aI14H9M2uDDUtd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOS\nL/UR5GLXMnE42QQMcas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9\nqFD0sefGL9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i\nNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2\nf3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44\nI8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCyZ/QYFpM6/EfY0XiWMR+6Kwxf\nXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy\n9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF\n8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mV\nBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8C\nAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD\nVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZpcm1hcHJv\nZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAAbABh\nACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx\nADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+\nxDLx51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5x\nhOW1//qkR71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5\neTSSPi5E6PaPT481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5Fl\nClrD2VQS3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k\nSeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2\ngHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYD\nNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhr\nJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIyS\nxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V\n-----END CERTIFICATE-----\n", - "Izenpe.com": "-----BEGIN CERTIFICATE-----\nMIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYD\nVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcN\nMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwL\nSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC\nDwAwggIKAoICAQDJ03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5Tz\ncqQsRNiekpsUOqHnJJAKClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpz\nbm3benhB6QiIEn6HLmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJ\nGjMxCrFXuaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD\nyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8\nhBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG7\n0t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyNBjNaooXlkDWgYlwWTvDjovoD\nGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+0rnq49qlw0dpEuDb8PYZi+17cNcC\n1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQD\nfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNV\nHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4g\nLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB\nBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAxMCBWaXRv\ncmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE\nFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l\nFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9\nfbgakEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJO\nubv5vr8qhT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m\n5hzkQiCeR7Csg1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Py\ne6kfLqCTVyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk\nLhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqt\nujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZ\npR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6i\nSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE4\n1V4tC5h9Pmzb/CaIxw==\n-----END CERTIFICATE-----\n", - "Chambers of Commerce Root - 2008": "-----BEGIN CERTIFICATE-----\nMIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJF\nVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZp\ncm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1l\ncmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4\nMB4XDTA4MDgwMTEyMjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYD\nVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t\nL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEg\nUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G\nCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+\nJrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCG\nhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072QDuKZoRuGDtqaCrsLYVAGUvGe\nf3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL\n+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9\nZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esH\nnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2w\nsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5\nWk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhjya6BXBg1\n4JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2EQID\nAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI\nG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4x\nCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQg\nd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNV\nBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2Ug\nUm9vdCAtIDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV\nHSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI\nhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I\n6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0\n/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk1\n8pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rc\nf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+K\nMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb\n0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq\njktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1DefhiYtUU7\n9nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRgOGcEMeyP84LG3rlV\n8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ\n-----END CERTIFICATE-----\n", - "Global Chambersign Root - 2008": "-----BEGIN CERTIFICATE-----\nMIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJF\nVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZp\ncm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1l\ncmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAe\nFw0wODA4MDExMjMxNDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UE\nBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9h\nZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu\nQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI\nhvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwG\nMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7G706tcuto8xEpw2u\nIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBA\nspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/\nLMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkB\nfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9\nkGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al\n/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r\n6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9JhwZG7SMA0\nj0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMBAAGj\nggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT\nBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkG\nA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cu\nY2FtZXJmaXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMS\nQUMgQ2FtZXJmaXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAt\nIDIwMDiCCQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow\nKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEF\nBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv\n4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWC\nkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIa\ndJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJ\njUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uY\nlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3L\nm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso\nM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4gev8CSlDQb\n4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z09gwzxMNTxXJhLyn\nSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B\n-----END CERTIFICATE-----\n", - "Go Daddy Root Certificate Authority - G2": "-----BEGIN CERTIFICATE-----\nMIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNV\nBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29t\nLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAt\nIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAw\nDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5\nLmNvbSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp\ndHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3\ngElY6SKDE6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH\n/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLI\njWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6\ngZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGRtDtwKj9useiciAF9n9T521Nt\nYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\nBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3\nDQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC\n2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95\nkTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo\n2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPOLPAvTK33\nsefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1\n-----END CERTIFICATE-----\n", - "Starfield Root Certificate Authority - G2": "-----BEGIN CERTIFICATE-----\nMIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNV\nBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBU\nZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRl\nIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJ\nBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYD\nVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQg\nUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\nnLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSu\nS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhh\ndM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dNdloedl40wOiWVpmKs/B/pM29\n3DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbUJtQIBFnQmA4O5t78w+wfkPECAwEA\nAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n\n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWU\nXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox\n9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/KpL/QlwVK\nvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZc2T5\nNnReJaH1ZgUufzkVqSr7UIuOhWn0\n-----END CERTIFICATE-----\n", - "Starfield Services Root Certificate Authority - G2": "-----BEGIN CERTIFICATE-----\nMIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNV\nBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBU\nZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENl\ncnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1\nOVowgZgxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNk\nYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJT\ndGFyZmllbGQgU2VydmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p\nOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2\ndBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS\n7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufehRhJfGZOozptqbXuNC66DQO4\nM99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFBrMnUVN+HL8cisibMn1lUaJ/8viov\nxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBL\nNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynV\nv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z\nqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkdiEDPfUYd\n/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jzaYyWf\n/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6\n-----END CERTIFICATE-----\n", - "AffirmTrust Commercial": "-----BEGIN CERTIFICATE-----\nMIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMx\nFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFs\nMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNV\nBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTW\nzsO3qyxPxkEylFf6EqdbDuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U\n6Mje+SJIZMblq8Yrba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNA\nFxHUdPALMeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1\nyHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1J\ndX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8w\nDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFis\n9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M\n06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1Ua\nADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjip\nM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclN\nmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=\n-----END CERTIFICATE-----\n", - "AffirmTrust Networking": "-----BEGIN CERTIFICATE-----\nMIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMx\nFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5n\nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNV\nBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWRE\nZY9nZOIG41w3SfYvm4SEHi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ\n/Ls6rnla1fTWcbuakCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXL\nviRmVSRLQESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp\n6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKB\nNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0w\nDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAIlX\nshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t\n3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA\n3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzek\nujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfx\nojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=\n-----END CERTIFICATE-----\n", - "AffirmTrust Premium": "-----BEGIN CERTIFICATE-----\nMIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMx\nFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4X\nDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoM\nC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64t\nb+eT2TZwamjPjlGjhVtnBKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/\n0qRY7iZNyaqoe5rZ+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/\nK+k8rNrSs8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5\nHMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua\n2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/\n9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+SqHZGnEJlPqQewQcDWkYtuJfz\nt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m\n6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKP\nKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNC\nMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYD\nVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2\nKI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMgNt58D2kT\niKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC6C1Y\n91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S\nL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQ\nwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFo\noC8k4gmVBtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5Yw\nH2AG7hsj/oFgIxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/\nqzWaVYa8GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO\nRtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAlo\nGRwYQw==\n-----END CERTIFICATE-----\n", - "AffirmTrust Premium ECC": "-----BEGIN CERTIFICATE-----\nMIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDAS\nBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAe\nFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQK\nDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcq\nhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQU\nX+iOGasvLkjmrBhDeKzQN8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR\n4ptlKymjQjBAMB0GA1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTAD\nAQH/MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs\naobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9C\na/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==\n-----END CERTIFICATE-----\n", - "Certum Trusted Network CA": "-----BEGIN CERTIFICATE-----\nMIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYD\nVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlm\naWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0Ew\nHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UE\nChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmlj\nYXRpb24gQXV0aG9yaXR5MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/\n91sts1rHUV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM\nTXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmt\nVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM\n+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8xAcPs3hEtF10fuFDRXhmnad4H\nMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQI\nds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEB\nAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsi\nsrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv\n94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY\nVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI03YnnZot\nBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=\n-----END CERTIFICATE-----\n", - "Certinomis - Autorité Racine": "-----BEGIN CERTIFICATE-----\nMIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UE\nChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRp\nbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1\nOVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIg\nNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIw\nDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2\nDpdUzZlMGvE5x4jYF1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOr\nJ3NqDi5N8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe\nrP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0\nK0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb\n4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6\nDwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTClrLooyPCXQP8w9PlfMl1I9f09bze\n5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGo\nOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75\nmxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29Ynf\nAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN\njLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJKoZIhvcN\nAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/xWqnd\nIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva\nR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCX\nwH40nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQR\nE7rWhh1BCxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPb\nVFsDbVRfsbjvJL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJ\nOqxp9YDG5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq\npdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XS\nAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ\n8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5\n-----END CERTIFICATE-----\n", - "Root CA Generalitat Valenciana": "-----BEGIN CERTIFICATE-----\nMIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0G\nA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQD\nEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEw\nNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5j\naWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZh\nbGVuY2lhbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qd\nyu0togu8M1JAJke+WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9pt\nI6GJXiKjSgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl\nu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt5\n5cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxkHl6AovWDfgzWyoxV\njr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7MIIDNzAyBggrBgEFBQcBAQQm\nMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB\n/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcC\nAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA\nYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQA\nIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA\nbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA\nYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBtAGkA\nZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA\nYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUA\nZQBuAHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgA\ndAB0AHAAOgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYB\nBQUHAgEWGWh0dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90\nECjcPk+yeAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw\nCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMG\nUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5Wgw\nDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQ\nqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHP\njCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+\neLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3R\nr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYx\nn7fofMM=\n-----END CERTIFICATE-----\n", - "A-Trust-nQual-03": "-----BEGIN CERTIFICATE-----\nMIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYG\nA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERh\ndGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBB\nLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJ\nBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1l\nIGltIGVsZWt0ci4gRGF0ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwt\nMDMxGTAXBgNVBAMMEEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\nggEKAoIBAQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj\nlUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuK\nqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXl\nyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9\nj4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGj\nNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIB\nBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvU\nB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdC\noLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R\nFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GSmYHovjrH\nF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6ahq9\n7BvIxYSazQ==\n-----END CERTIFICATE-----\n", - "TWCA Root Certification Authority": "-----BEGIN CERTIFICATE-----\nMIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UE\nCgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2Vy\ndGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBf\nMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSow\nKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bi\nhSX0NXIP+FPQQeFEAcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQ\nsIBct+HHK3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX\nRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJb\nKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxY\nA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud\nDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG9w0BAQUFAAOCAQEAPNV3PdrfibqH\nDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqG\nfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4g\numlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKu\nD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ\nYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==\n-----END CERTIFICATE-----\n", - "Security Communication RootCA2": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UE\nChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29t\nbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTEL\nMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAl\nBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz3\n35c9S672XewhtUGrzbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonC\nv/Q4EpVMVAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ\nhNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhw\nHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCca\ndfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQE\nAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBMOqNErLlFsceTfsgL\nCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8\nAynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g6\n9ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR\n50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/\nSjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03\n-----END CERTIFICATE-----\n", - "EC-ACC": "-----BEGIN CERTIFICATE-----\nMIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkG\nA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChO\nSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNh\nY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAo\nYykwMzE1MDMGA1UECxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRh\nbGFuZXMxDzANBgNVBAMTBkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTla\nMIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZp\nY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD\nZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3Zl\ncmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNh\nY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfC\nQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6\nPttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST\n2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n\n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB\no4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8EBTADAQH/\nMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYDVR0g\nBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0\nLm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0\nLm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/\nsXE7zDkJlF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPp\nqojlNcAZQmNaAl6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7Awa\nboMMPOhyRp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS\nAgu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6\nUn/10asIbvPuW/mIPX64b24D5EI=\n-----END CERTIFICATE-----\n", - "Hellenic Academic and Research Institutions RootCA 2011": "-----BEGIN CERTIFICATE-----\nMIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNV\nBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4g\nQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5z\ndGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1Mlow\ngZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFy\nY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNh\nZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz\ndYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0a\ne50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsm\nLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD75O6aRXxYp2fmTmCobd0LovU\nxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH3N6sQWRstBmbAmNtJGSPRLIl6s5d\ndAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNV\nHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUw\nBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3\nDQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p\n6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8TqBTnbI6\nnOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD/md9\nzU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N\n7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4\n-----END CERTIFICATE-----\n", - "Actalis Authentication Root CA": "-----BEGIN CERTIFICATE-----\nMIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQx\nDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEn\nMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIw\nMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYD\nVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRo\nZW50aWNhdGlvbiBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bE\npSmkLO/lGMWwUKNvUTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW\n1V8IbInX4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9\nKK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63\nigxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8\noJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RH\nILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8lEfKXGkJh90qX6IuxEAf6ZYGyojnP\n9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4\nRCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U\n5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/j\nVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz\nezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbtifN7OHCU\nyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyIWOYd\niPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0\nJZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjR\nlwKxK3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2ryk\nOLpn7VU+Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2T\nlf05fbsq4/aC4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst\n842/6+OkfcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R\nK4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VL\nkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDz\nzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7y\nFIrM6bV8+2ydDKXhlg==\n-----END CERTIFICATE-----\n", - "Trustis FPS Root CA": "-----BEGIN CERTIFICATE-----\nMIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYD\nVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQ\nUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMC\nR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9v\ndCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2\nmfRC6qc+gIMPpqdZh8mQRUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkc\nhU59j9WvezX2fihHiTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE\n2gfmHhjjvSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA\n0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L6\n8MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV\nHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuy\nZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2cGE+esCu8jowU/yyg2kdbw++BLa8F\n6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5B\nuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWh\nPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/\nrGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN\nZetX2fNXlrtIzYE=\n-----END CERTIFICATE-----\n", - "StartCom Certification Authority G2": "-----BEGIN CERTIFICATE-----\nMIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UE\nChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRo\nb3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJ\nTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNh\ndGlvbiBBdXRob3JpdHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZb\nB7cgNr2Cu+EWIAOVeq8Oo1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe\n3ikj1AENoBB5uNsDvfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSC\nb0AgJnooD/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/\nQ0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr\n7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq\n42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxNnw3h3Kq74W4a7I/htkxNeXJd\nFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ\n85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0s\nAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPI\nN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud\nDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL\nBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K2s06Ctg6\nWgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbkJ4kd\n+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+\nJYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w\n6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9\nmk47EDTcnIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1\ndZxAF7L+/XldblhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6M\nanY5Ka5lIxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo\nhdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjR\nkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI\n-----END CERTIFICATE-----\n", - "Buypass Class 2 Root CA": "-----BEGIN CERTIFICATE-----\nMIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UE\nCgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290\nIENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAb\nBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIg\nUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1\naeTuMgHbo4Yf5FkNuud1g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXl\nzwx87vFKu3MwZfPVL4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FV\nM5I+GC911K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx\nMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfg\nolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkBarcNuAeBfos4Gzjm\nCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T\n3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1L\nPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIH\nZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVe\ne7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+Bi\nkoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h\n9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462sA20ucS6v\nxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EIosHs\nHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S\naq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlq\nYLYdDnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6\nOBE1/yWDLfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6w\npJ9qzo6ysmD0oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYK\nbeaP4NK75t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h\n3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv\n4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=\n-----END CERTIFICATE-----\n", - "Buypass Class 3 Root CA": "-----BEGIN CERTIFICATE-----\nMIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UE\nCgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290\nIENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAb\nBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMg\nUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEG\nMnqb8RB2uACatVI2zSRHsJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fk\noF0LXOBXByow9c3EN3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOo\nTyrvYLs9tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX\n0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux\n9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6a\nny2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5\nGQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon\n74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3i\niZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFM\nOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/l\nb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj\nQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdVcSQy9sgL\n8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+GuIAe\nqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG\nQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshA\npqr8ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjEN\nSoYc6+I2KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr1\n8okmAWiDSKIz6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2X\ncEQNtg413OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD\nu79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN\n12TyUb7mqqta6THuBrxzvxNiCp/HuZc=\n-----END CERTIFICATE-----\n", - "T-TeleSec GlobalRoot Class 3": "-----BEGIN CERTIFICATE-----\nMIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNV\nBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lz\ndGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNz\nIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzAp\nBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQt\nU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENs\nYXNzIDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3Z\nJNW4t/zN8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/\nRLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys5\n2qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HM\nVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6\ntsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0B\nAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ\n85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/\nvBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT\n91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuImle9eiPZaG\nzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==\n-----END CERTIFICATE-----\n", - "EE Certification Centre Root CA": "-----BEGIN CERTIFICATE-----\nMIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYD\nVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwf\nRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNr\nLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVF\nMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0\naWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEi\nMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLq\nI9iroWUyeuuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO\nbntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajm\nofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAd\nTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE1CV2yreN1x5KZmTNXMWcg+HC\nCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\nBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUF\nBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkw\nDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQi\nZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG\nE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5uuSlNDUmJ\nEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU3j2L\nrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM\ndcGWxZ0=\n-----END CERTIFICATE-----\n" -} \ No newline at end of file diff --git a/package.json b/package.json index 0bad982..60baac5 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "request": "browser-request" }, "dependencies": { - "asn1.js": "=0.4.1", "bn.js": "=0.16.1", "browser-request": "^0.3.3", "bs58": "=2.0.0", @@ -82,9 +81,7 @@ "elliptic": "=0.16.0", "hash.js": "=0.3.2", "inherits": "=2.0.1", - "jsrsasign": "=0.0.3", "lodash": "=2.4.1", - "protobufjs": "=3.0.0", "request": "^2.51.0", "sha512": "=0.0.1", "socks5-client": "^0.3.6" diff --git a/test/paymentprotocol/index.js b/test/paymentprotocol/index.js deleted file mode 100644 index 4ba58ca..0000000 --- a/test/paymentprotocol/index.js +++ /dev/null @@ -1,985 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var should = chai.should(); -var expect = chai.expect; -var bitcore = require('../../'); -var PrivateKey = bitcore.PrivateKey; -var PublicKey = bitcore.PublicKey; - -var is_browser = typeof process === 'undefined' || typeof process.versions === 'undefined'; - -var PaymentProtocol = bitcore.PaymentProtocol; -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'); - -// A test PaymentRequest (with a full cert chain) from test.bitpay.com: - -var bitpayRequest = new Buffer('' - + '0801120b783530392b7368613235361a89250aa40a3082052030820408a0' - + '03020102020727a49d05046d62300d06092a864886f70d01010b05003081' - + 'b4310b30090603550406130255533110300e060355040813074172697a6f' - + '6e61311330110603550407130a53636f74747364616c65311a3018060355' - + '040a1311476f44616464792e636f6d2c20496e632e312d302b060355040b' - + '1324687474703a2f2f63657274732e676f64616464792e636f6d2f726570' - + '6f7369746f72792f313330310603550403132a476f204461646479205365' - + '6375726520436572746966696361746520417574686f72697479202d2047' - + '32301e170d3134303432363132333532365a170d31363034323631323335' - + '32365a303a3121301f060355040b1318446f6d61696e20436f6e74726f6c' - + '2056616c6964617465643115301306035504030c0c2a2e6269747061792e' - + '636f6d30820122300d06092a864886f70d01010105000382010f00308201' - + '0a0282010100e2a5dd4aea959c1d0fb016e6e05bb7011e741cdc61918c61' - + 'f9625a2f682f485f0e862ea63db61cc9161753127504de800604df36b10f' - + '46cb17ab6cb99dba8aa45a36adfb901a2fc380c89e234bce18de6639b883' - + 'e9339801673efaee1f2df77eeb82f7c39c96a2f8ef4572b634c203d9be8f' - + 'd1e0036d32fb38b6b9b5ecd5a0684345c7e9ffc5d26bc6fd69aa6619f77b' - + 'adaa4bfb989478fb2f41aa92782e40b34ba9ac4549a4e6fda76b5fc4a581' - + '853bd0de5fb5a2c6dfdc12cdfadb54e9636a6d1223705924b8be566b81ac' - + '7921078cf590a146ae397a84908ef4fc83ff5715a44ab59e9258674d9011' - + '3bb607b8d81eb268e4c6ce849497c76521795b0873950203010001a38201' - + 'ae308201aa300f0603551d130101ff04053003010100301d0603551d2504' - + '16301406082b0601050507030106082b06010505070302300e0603551d0f' - + '0101ff0404030205a030360603551d1f042f302d302ba029a02786256874' - + '74703a2f2f63726c2e676f64616464792e636f6d2f676469673273312d34' - + '392e63726c30530603551d20044c304a3048060b6086480186fd6d010717' - + '013039303706082b06010505070201162b687474703a2f2f636572746966' - + '6963617465732e676f64616464792e636f6d2f7265706f7369746f72792f' - + '307606082b06010505070101046a3068302406082b060105050730018618' - + '687474703a2f2f6f6373702e676f64616464792e636f6d2f304006082b06' - + '0105050730028634687474703a2f2f6365727469666963617465732e676f' - + '64616464792e636f6d2f7265706f7369746f72792f67646967322e637274' - + '301f0603551d2304183016801440c2bd278ecc348330a233d7fb6cb3f0b4' - + '2c80ce30230603551d11041c301a820c2a2e6269747061792e636f6d820a' - + '6269747061792e636f6d301d0603551d0e0416041485454e3b4072e2f58e' - + '377438988b5229387e967a300d06092a864886f70d01010b050003820101' - + '002d0a7ef97f988905ebbbad4e9ffb690352535211d6792516119838b55f' - + '24ff9fa4e93b6187b8517cbb0477457d3378078ef66057abe41bcafeb142' - + 'ec52443a94b88114fa069f725c6198581d97af16352727f4f35e7f2110fa' - + 'a41a0511bcfdf8e3f4a3a310278c150b10f32a962c81e8f3d5374d9cb56d' - + '893027ff4fa4e3c3e6384c1f1557ceea6fca9cbc0c110748c08b82d8f0ed' - + '9a579637ee43a2d8fec3b5b04d1f3c8f1a3e2088da2274b6bc60948bbe74' - + '4a7f8b942b41f0ae9b4afaeefbb7e0f04a0587b52efb6ebfa2d970b9de56' - + 'a068575e4bf0cf824618dc17bbeaa2cdd25d65970a9f1a06fc9fffb466a1' - + '0c9568cd651795bc2c7996975027bdbaba0ad409308204d0308203b8a003' - + '020102020107300d06092a864886f70d01010b0500308183310b30090603' - + '550406130255533110300e060355040813074172697a6f6e613113301106' - + '03550407130a53636f74747364616c65311a3018060355040a1311476f44' - + '616464792e636f6d2c20496e632e3131302f06035504031328476f204461' - + '64647920526f6f7420436572746966696361746520417574686f72697479' - + '202d204732301e170d3131303530333037303030305a170d333130353033' - + '3037303030305a3081b4310b30090603550406130255533110300e060355' - + '040813074172697a6f6e61311330110603550407130a53636f7474736461' - + '6c65311a3018060355040a1311476f44616464792e636f6d2c20496e632e' - + '312d302b060355040b1324687474703a2f2f63657274732e676f64616464' - + '792e636f6d2f7265706f7369746f72792f313330310603550403132a476f' - + '204461646479205365637572652043657274696669636174652041757468' - + '6f72697479202d20473230820122300d06092a864886f70d010101050003' - + '82010f003082010a0282010100b9e0cb10d4af76bdd49362eb3064b88108' - + '6cc304d962178e2fff3e65cf8fce62e63c521cda16454b55ab786b638362' - + '90ce0f696c99c81a148b4ccc4533ea88dc9ea3af2bfe80619d7957c4cf2e' - + 'f43f303c5d47fc9a16bcc3379641518e114b54f828bed08cbef030381ef3' - + 'b026f86647636dde7126478f384753d1461db4e3dc00ea45acbdbc71d9aa' - + '6f00dbdbcd303a794f5f4c47f81def5bc2c49d603bb1b24391d8a4334eea' - + 'b3d6274fad258aa5c6f4d5d0a6ae7405645788b54455d42d2a3a3ef8b8bd' - + 'e9320a029464c4163a50f14aaee77933af0c20077fe8df0439c269026c63' - + '52fa77c11bc87487c8b993185054354b694ebc3bd3492e1fdcc1d252fb02' - + '03010001a382011a30820116300f0603551d130101ff040530030101ff30' - + '0e0603551d0f0101ff040403020106301d0603551d0e0416041440c2bd27' - + '8ecc348330a233d7fb6cb3f0b42c80ce301f0603551d230418301680143a' - + '9a8507106728b6eff6bd05416e20c194da0fde303406082b060105050701' - + '0104283026302406082b060105050730018618687474703a2f2f6f637370' - + '2e676f64616464792e636f6d2f30350603551d1f042e302c302aa028a026' - + '8624687474703a2f2f63726c2e676f64616464792e636f6d2f6764726f6f' - + '742d67322e63726c30460603551d20043f303d303b0604551d2000303330' - + '3106082b06010505070201162568747470733a2f2f63657274732e676f64' - + '616464792e636f6d2f7265706f7369746f72792f300d06092a864886f70d' - + '01010b05000382010100087e6c9310c838b896a9904bffa15f4f04ef6c3e' - + '9c8806c9508fa673f757311bbebce42fdbf8bad35be0b4e7e679620e0ca2' - + 'd76a637331b5f5a848a43b082da25d90d7b47c254f115630c4b6449d7b2c' - + '9de55ee6ef0c61aabfe42a1bee849eb8837dc143ce44a713700d911ff4c8' - + '13ad8360d9d872a873241eb5ac220eca17896258441bab892501000fcdc4' - + '1b62db51b4d30f512a9bf4bc73fc76ce36a4cdd9d82ceaae9bf52ab290d1' - + '4d75188a3f8a4190237d5b4bfea403589b46b2c3606083f87d5041cec2a1' - + '90c3bbef022fd21554ee4415d90aaea78a33edb12d763626dc04eb9ff761' - + '1f15dc876fee469628ada1267d0a09a72e04a38dbcf8bc0430010a810930' - + '82047d30820365a00302010202031be715300d06092a864886f70d01010b' - + '05003063310b30090603550406130255533121301f060355040a13185468' - + '6520476f2044616464792047726f75702c20496e632e3131302f06035504' - + '0b1328476f20446164647920436c61737320322043657274696669636174' - + '696f6e20417574686f72697479301e170d3134303130313037303030305a' - + '170d3331303533303037303030305a308183310b30090603550406130255' - + '533110300e060355040813074172697a6f6e61311330110603550407130a' - + '53636f74747364616c65311a3018060355040a1311476f44616464792e63' - + '6f6d2c20496e632e3131302f06035504031328476f20446164647920526f' - + '6f7420436572746966696361746520417574686f72697479202d20473230' - + '820122300d06092a864886f70d01010105000382010f003082010a028201' - + '0100bf716208f1fa5934f71bc918a3f7804958e9228313a6c52043013b84' - + 'f1e685499f27eaf6841b4ea0b4db7098c73201b1053e074eeef4fa4f2f59' - + '3022e7ab19566be28007fcf316758039517be5f935b6744ea98d8213e4b6' - + '3fa90383faa2be8a156a7fde0bc3b6191405caeac3a804943b467c320df3' - + '006622c88d696d368c1118b7d3b21c60b438fa028cced3dd4607de0a3eeb' - + '5d7cc87cfbb02b53a4926269512505611a44818c2ca9439623dfac3a819a' - + '0e29c51ca9e95d1eb69e9e300a39cef18880fb4b5dcc32ec856243253402' - + '56270191b43b702a3f6eb1e89c88017d9fd4f9db536d609dbf2ce758abb8' - + '5f46fccec41b033c09eb49315c6946b3e0470203010001a3820117308201' - + '13300f0603551d130101ff040530030101ff300e0603551d0f0101ff0404' - + '03020106301d0603551d0e041604143a9a8507106728b6eff6bd05416e20' - + 'c194da0fde301f0603551d23041830168014d2c4b0d291d44c1171b361cb' - + '3da1fedda86ad4e3303406082b0601050507010104283026302406082b06' - + '0105050730018618687474703a2f2f6f6373702e676f64616464792e636f' - + '6d2f30320603551d1f042b30293027a025a0238621687474703a2f2f6372' - + '6c2e676f64616464792e636f6d2f6764726f6f742e63726c30460603551d' - + '20043f303d303b0604551d20003033303106082b06010505070201162568' - + '747470733a2f2f63657274732e676f64616464792e636f6d2f7265706f73' - + '69746f72792f300d06092a864886f70d01010b05000382010100590b53bd' - + '928611a7247bed5b31cf1d1f6c70c5b86ebe4ebbf6be9750e1307fba285c' - + '6294c2e37e33f7fb427685db951c8c225875090c886567390a1609c5a038' - + '97a4c523933fb418a601064491e3a76927b45a257f3ab732cddd84ff2a38' - + '2933a4dd67b285fea188201c5089c8dc2af64203374ce688dfd5af24f2b1' - + 'c3dfccb5ece0995eb74954203c94180cc71c521849a46de1b3580bc9d8ec' - + 'd9ae1c328e28700de2fea6179e840fbd5770b35ae91fa08653bbef7cff69' - + '0be048c3b7930bc80a54c4ac5d1467376ccaa52f310837aa6e6f8cbc9be2' - + '575d2481af97979c84ad6cac374c66f361911120e4be309f7aa42909b0e1' - + '345f6477184051df8c30a6af0a840830820400308202e8a0030201020201' - + '00300d06092a864886f70d01010505003063310b30090603550406130255' - + '533121301f060355040a131854686520476f2044616464792047726f7570' - + '2c20496e632e3131302f060355040b1328476f20446164647920436c6173' - + '7320322043657274696669636174696f6e20417574686f72697479301e17' - + '0d3034303632393137303632305a170d3334303632393137303632305a30' - + '63310b30090603550406130255533121301f060355040a13185468652047' - + '6f2044616464792047726f75702c20496e632e3131302f060355040b1328' - + '476f20446164647920436c61737320322043657274696669636174696f6e' - + '20417574686f7269747930820120300d06092a864886f70d010101050003' - + '82010d00308201080282010100de9dd7ea571849a15bebd75f4886eabedd' - + 'ffe4ef671cf46568b35771a05e77bbed9b49e970803d561863086fdaf2cc' - + 'd03f7f0254225410d8b281d4c0753d4b7fc777c33e78ab1a03b5206b2f6a' - + '2bb1c5887ec4bb1eb0c1d845276faa3758f78726d7d82df6a917b71f7236' - + '4ea6173f659892db2a6e5da2fe88e00bde7fe58d15e1ebcb3ad5e212a213' - + '2dd88eaf5f123da0080508b65ca565380445991ea3606074c541a572621b' - + '62c51f6f5f1a42be025165a8ae23186afc7803a94d7f80c3faab5afca140' - + 'a4ca1916feb2c8ef5e730dee77bd9af67998bcb10767a2150ddda058c644' - + '7b0a3e62285fba41075358cf117e3874c5f8ffb569908f8474ea971baf02' - + '0103a381c03081bd301d0603551d0e04160414d2c4b0d291d44c1171b361' - + 'cb3da1fedda86ad4e330818d0603551d230481853081828014d2c4b0d291' - + 'd44c1171b361cb3da1fedda86ad4e3a167a4653063310b30090603550406' - + '130255533121301f060355040a131854686520476f204461646479204772' - + '6f75702c20496e632e3131302f060355040b1328476f2044616464792043' - + '6c61737320322043657274696669636174696f6e20417574686f72697479' - + '820100300c0603551d13040530030101ff300d06092a864886f70d010105' - + '05000382010100324bf3b2ca3e91fc12c6a1078c8e77a03306145c901e18' - + 'f708a63d0a19f98780116e69e4961730ff3491637238eecc1c01a31d9428' - + 'a431f67ac454d7f6e5315803a2ccce62db944573b5bf45c924b5d58202ad' - + '2379698db8b64dcecf4cca3323e81c88aa9d8b416e16c920e5899ecd3bda' - + '70f77e992620145425ab6e7385e69b219d0a6c820ea8f8c20cfa101e6c96' - + 'ef870dc40f618badee832b95f88e92847239eb20ea83ed83cd976e08bceb' - + '4e26b6732be4d3f64cfe2671e26111744aff571a870f75482ecf516917a0' - + '02126195d5d140b2104ceec4ac1043a6a59e0ad595629a0dcf8882c5320c' - + 'e42b9f45e60d9f289cb1b92a5a57ad370faf1d7fdbbd9f22a1010a047465' - + '7374122008c0c9e714121976a914176d7c5d60da6f8c82de86671a1fb776' - + '028538ca88ac18c6f5d89f0520cafcd89f052a395061796d656e74207265' - + '717565737420666f722042697450617920696e766f69636520434d577075' - + '46736a676d51325a4c6979476663463157323068747470733a2f2f746573' - + '742e6269747061792e636f6d2f692f434d57707546736a676d51325a4c69' - + '794766634631572a80021566366ab78842a514c056ca7ecb76481262cac7' - + '4cc4c4ccdc82c4980bc3300de67836d61d3e06dc8c90798a7774c21c7ad4' - + 'fe634b85faa8719d6402411bb720396ae03cbb4e14f06f7894a66b208b99' - + 'f727fab35d32f4f2148294d24bea1b3f240c159d0fd3ee4a32e5f926bf7c' - + '05eb7a3f75e01d9af81254cfbb61606467750ea7e0a1536728358e0898d0' - + '6f57235e4096d2caf647ae58dff645be80c9b3555fa96c81efa07d421977' - + 'd26214ad4f1ff642a93d0925656aeab454fa0b60fcbb6c1bc570eb6e43e7' - + '613392f37900748635ae381534bfaa558792bc46028b9efce391423a9c12' - + '01f76292614b30a14272e837f3813045b035f3d42f4f76f48acd', - 'hex'); - -describe('PaymentProtocol', function() { - - this.timeout(15000); - - it('should be able to create class', function() { - should.exist(PaymentProtocol); - }); - - describe('#Output', function() { - - it('should not fail', function() { - var obj = {}; - var output = new PaymentProtocol.Output(); - output.$set('amount', 20); - }); - - it('should be able to set the amount of an output', function() { - var output = new PaymentProtocol.Output(); - output.set('amount', 20); - output.get('amount').toInt().should.equal(20); - }); - - it('should be able to make output using "makeOutput"', function() { - var output = new PaymentProtocol().makeOutput(); - output.message.set('amount', 20); - output.message.get('amount').toInt().should.equal(20); - }); - - }); - - describe('#PaymentDetails', function() { - - it('should not fail', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentDetails(); - }); - - it('should set the memo', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('memo', 'test memo'); - pd.get('memo').should.equal('test memo'); - }); - - it('should serialize', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - pd.set('memo', 'test memo'); - var hex = pd.toHex(); - hex.length.should.be.greaterThan(0); - }); - - }); - - describe('#PaymentRequest', function() { - - it('should not fail', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentRequest(); - }); - - it('should serialize', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var pr = new PaymentProtocol.PaymentRequest(); - pr.set('serialized_payment_details', pdbuf); - var prhex = pr.toHex(); - prhex.length.should.be.greaterThan(0); - }); - - }); - - describe('#Payment', function() { - - it('should not fail', function() { - var obj = {}; - var pd = new PaymentProtocol.Payment(); - }); - - it('should serialize', function() { - var obj = {}; - var p = new PaymentProtocol.Payment(); - p.set('memo', 'this is a memo'); - p.get('memo').should.equal('this is a memo'); - var phex = p.toHex(); - phex.length.should.be.greaterThan(0); - }); - - }); - - describe('#PaymentACK', function() { - - it('should not fail', function() { - var obj = {}; - var pd = new PaymentProtocol.PaymentACK(); - }); - - it('should serialize', function() { - var obj = {}; - var p = new PaymentProtocol.Payment(); - var pa = new PaymentProtocol.PaymentACK(); - pa.set('payment', p); - pa.set('memo', 'this is a memo'); - pa.get('memo').should.equal('this is a memo'); - var pahex = pa.toHex(); - pahex.length.should.be.greaterThan(0); - }); - - it('makePaymentACK', function() { - var payment = new PaymentProtocol.Payment(); - var ack = new PaymentProtocol().makePaymentACK(); - ack.set('payment', payment); - ack.set('memo', 'this is a memo'); - ack.get('memo').should.equal('this is a memo'); - var valid = ack.isValidSize(); - valid.should.equal(true); - var contentType = ack.getContentType(); - contentType.should.equal(PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE); - var serialized = ack.serialize(); - serialized.length.should.be.greaterThan(0); - var ack2 = new PaymentProtocol().makePaymentACK(); - ack2.deserialize(serialized, 'PaymentACK'); - var serialized2 = ack2.serialize(); - serialized.should.deep.equal(serialized2); - }); - - }); - - describe('#X509Certificates', function() { - - it('should not fail', function() { - var obj = {}; - var pd = new PaymentProtocol.X509Certificates(); - }); - - it('should serialize', function() { - var obj = {}; - var x = new PaymentProtocol.X509Certificates(); - var fakecertificate = new Buffer([0, 0, 0, 0]); - x.set('certificate', [fakecertificate]); - var xhex = x.toHex(); - xhex.length.should.be.greaterThan(0); - }); - - }); - - describe('#isValidSize', function() { - - it('should return true for validly sized payment', function() { - var paypro = new PaymentProtocol(); - paypro.makePayment(); - paypro.set('memo', 'test memo'); - paypro.isValidSize().should.equal(true); - }); - - }); - - describe('#getContentType', function() { - - it('should error without a known message type', function() { - var paypro = new PaymentProtocol(); - paypro.messageType = 'unknown'; - expect(function(){ - paypro.getContentType(); - }).to.throw(Error); - }); - - it('should get a content type for payment', function() { - var paypro = new PaymentProtocol(); - paypro.makePayment(); - paypro.set('memo', 'test memo'); - paypro.getContentType().should.equal('application/bitcoin-payment'); - }); - - }); - - describe('#set', function() { - - it('should set a field', function() { - var obj = {}; - var paypro = new PaymentProtocol(); - paypro.makePaymentDetails(); - paypro.set('memo', 'test memo'); - paypro.get('memo').should.equal('test memo'); - }); - - }); - - describe('#get', function() { - - it('should get a field', function() { - var obj = {}; - var paypro = new PaymentProtocol(); - paypro.makePaymentDetails(); - paypro.set('memo', 'test memo'); - paypro.get('memo').should.equal('test memo'); - }); - - }); - - describe('#setObj', function() { - - it('should set properties of paymentdetails', function() { - var pd = new PaymentProtocol.PaymentDetails(); - var paypro = new PaymentProtocol(); - paypro.messageType = "PaymentDetails"; - paypro.message = pd; - paypro.setObj({ - time: 0 - }); - paypro.get('time').should.equal(0); - }); - - }); - - describe('#serializeForSig', function() { - - it('should error when not a payment request', function() { - var paypro = new PaymentProtocol(); - paypro.messageType = 'unknown'; - expect(function(){ - paypro.serializeForSig(); - }).to.throw(Error); - }); - - it('should serialize a PaymentRequest and not fail', function() { - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - var buf = paypro.serializeForSig(); - var valid = paypro.isValidSize(); - var contentType = paypro.getContentType(); - contentType.should.equal(PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE); - valid.should.equal(true); - buf.length.should.be.greaterThan(0); - }); - - }); - - describe('#serialize', function() { - - it('should serialize', function() { - var obj = {}; - var paypro = new PaymentProtocol(); - paypro.makePaymentDetails(); - paypro.set('memo', 'test memo'); - paypro.set('time', 0); - var buf = paypro.serialize(); - buf.length.should.be.greaterThan(0); - Buffer.isBuffer(buf).should.equal(true); - }); - - }); - - describe('#deserialize', function() { - - it('should error without a message type', function() { - var paypro = new PaymentProtocol(); - expect(function(){ - paypro.deserialize(new Buffer({size: 12})); - }).to.throw(Error); - }); - - it('should deserialize a serialized message', function() { - var obj = {}; - var paypro = new PaymentProtocol(); - paypro.makePaymentDetails(); - paypro.set('memo', 'test memo'); - paypro.set('time', 0); - var buf = paypro.serialize(); - var paypro2 = new PaymentProtocol(); - paypro2.deserialize(buf, 'PaymentDetails'); - paypro2.get('memo').should.equal('test memo'); - paypro2.get('time').should.equal(0); - }); - - }); - - describe('#sign', function() { - - it('should error when not a payment request', function() { - var paypro = new PaymentProtocol(); - expect(function(){ - paypro.sign(); - }).to.throw(Error); - }); - - it('should not sign if the pki_type is "none"', function() { - var paypro = new PaymentProtocol().makePaymentRequest(); - paypro.set('pki_type', 'none'); - var a = paypro.sign(); - var signature = a.get('signature'); - should.not.exist(signature); - }); - - it('should error if unkown pki_type', function() { - var paypro = new PaymentProtocol().makePaymentRequest(); - paypro.set('pki_type', 'x508'); //typo - expect(function(){ - paypro.sign(); - }).to.throw(Error); - }); - - it('should sign a payment request', function() { - // SIN - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'SIN'); - var key = new PrivateKey(); - paypro.sign(key); - var sig = paypro.get('signature'); - sig.length.should.be.greaterThan(0); - - // X509 - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha256'); - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - paypro.sign(x509.priv); - x509.sig1 = paypro.get('signature'); - x509.sig1.length.should.be.greaterThan(0); - }); - - }); - - describe('#verify', function() { - - it('should error if not a payment request', function() { - var paypro = new PaymentProtocol(); - expect(function(){ - paypro.verify(); - }).to.throw(Error); - }); - - it('should return true if pki_type is set to "none"', function() { - var paypro = new PaymentProtocol().makePaymentRequest(); - paypro.set('pki_type', 'none'); - var valid = paypro.verify(); - valid.should.equal(true); - }); - - it('should error if unsupported pki_type', function() { - var paypro = new PaymentProtocol().makePaymentRequest(); - paypro.set('pki_type', 'x508'); // typo - expect(function(){ - paypro.verify(); - }).to.throw(Error); - }); - - it('should verify a signed payment request', function() { - // SIN - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'SIN'); - var key = new PrivateKey(); - paypro.sign(key); - var verify = paypro.verify(); - verify.should.equal(true); - - // X509 - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha256'); - paypro.set('signature', x509.sig1); // sig buffer - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - var verify = paypro.verify(); - verify.should.equal(true); - - var trust = paypro.verify(true); - trust.selfSigned.should.equal(1); - trust.isChain.should.equal(false); - trust.verified.should.equal(true); - trust.caTrusted.should.equal(false); - should.equal(null, trust.caName); - trust.chainVerified.should.equal(false); - }); - - }); - - describe('#sinSign', function() { - - it('should error if not sent an instance of PrivateKey', function() { - var paypro = new PaymentProtocol(); - expect(function(){ - paypro.sinSign(Number(7)); // not a private key - }).to.throw(TypeError); - }); - - it('should sign assuming pki_type is SIN', function() { - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'SIN'); - var key = new PrivateKey(); - var sig = paypro.sinSign(key); - sig.length.should.be.greaterThan(0); - }); - - }); - - describe('#sinVerify', function() { - - it('should verify assuming pki_type is SIN', function() { - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - var pdbuf = pd.toBuffer(); - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'SIN'); - var key = new PrivateKey(); - paypro.sign(key); - var verify = paypro.sinVerify(); - verify.should.equal(true); - }); - - }); - - describe('#x509+sha256Sign', function() { - it('should sign assuming pki_type is x509+sha256', function() { - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - - var pdbuf = pd.toBuffer(); - - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha256'); - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - 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 PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - - var pdbuf = pd.toBuffer(); - - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha256'); - - paypro.set('signature', x509.sig2); // sig buffer - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - var verify = paypro.x509Verify(); - verify.should.equal(true); - - var trust = paypro.x509Verify(true); - trust.selfSigned.should.equal(1); - trust.isChain.should.equal(false); - trust.verified.should.equal(true); - trust.caTrusted.should.equal(false); - should.equal(null, trust.caName); - trust.chainVerified.should.equal(false); - }); - }); - - describe('#x509+sha1Sign', function() { - it('should sign assuming pki_type is x509+sha1', function() { - var pd = new PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - - var pdbuf = pd.toBuffer(); - - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha1'); - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - var sigTrust = paypro.x509Sign(x509.priv, true); - sigTrust.selfSigned.should.equal(1); - sigTrust.isChain.should.equal(false); - sigTrust.signature.length.should.be.greaterThan(0); - sigTrust.caTrusted.should.equal(false); - should.not.exist(sigTrust.caName); - - var sig = paypro.x509Sign(x509.priv); - 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 PaymentProtocol.PaymentDetails(); - pd.set('time', 0); - - var pdbuf = pd.toBuffer(); - - var paypro = new PaymentProtocol(); - paypro.makePaymentRequest(); - - paypro.set('serialized_payment_details', pdbuf); - paypro.set('pki_type', 'x509+sha1'); - - paypro.set('signature', x509.sig3); // sig buffer - - var cr = new PaymentProtocol(); - cr = cr.makeX509Certificates(); - cr.set('certificate', [x509.der]); - - paypro.set('pki_data', cr.serialize()); // contains one or more x509 certs - - var verify = paypro.x509Verify(); - verify.should.equal(true); - - var trust = paypro.x509Verify(true); - trust.selfSigned.should.equal(1); - trust.isChain.should.equal(false); - trust.verified.should.equal(true); - trust.caTrusted.should.equal(false); - should.equal(null, trust.caName); - trust.chainVerified.should.equal(false); - }); - }); - - describe('#x509+sha256Verify ', function() { - it('should verify a real PaymentRequest', function() { - var data = PaymentProtocol.PaymentRequest.decode(bitpayRequest); - var pr = new PaymentProtocol(); - pr = pr.makePaymentRequest(data); - - // PaymentRequest - var ver = pr.get('payment_details_version'); - var pki_type = pr.get('pki_type'); - var pki_data = pr.get('pki_data'); - var details = pr.get('serialized_payment_details'); - var sig = pr.get('signature'); - - pki_data = PaymentProtocol.X509Certificates.decode(pki_data); - pki_data = pki_data.certificate; - - ver.should.equal(1); - pki_type.should.equal('x509+sha256'); - pki_data.length.should.equal(4); - sig.toString('hex').should.equal('' - + '1566366ab78842a514c056ca7ecb76481262cac74cc4c4ccdc' - + '82c4980bc3300de67836d61d3e06dc8c90798a7774c21c7ad4' - + 'fe634b85faa8719d6402411bb720396ae03cbb4e14f06f7894' - + 'a66b208b99f727fab35d32f4f2148294d24bea1b3f240c159d' - + '0fd3ee4a32e5f926bf7c05eb7a3f75e01d9af81254cfbb6160' - + '6467750ea7e0a1536728358e0898d06f57235e4096d2caf647' - + 'ae58dff645be80c9b3555fa96c81efa07d421977d26214ad4f' - + '1ff642a93d0925656aeab454fa0b60fcbb6c1bc570eb6e43e7' - + '613392f37900748635ae381534bfaa558792bc46028b9efce3' - + '91423a9c1201f76292614b30a14272e837f3813045b035f3d4' - + '2f4f76f48acd'); - - if (is_browser) { - var type = 'SHA256'; - var pem = PaymentProtocol.prototype._DERtoPEM(pki_data[0], 'CERTIFICATE'); - var buf = pr.serializeForSig(); - var jsrsaSig = new KJUR.crypto.Signature({ - alg: type + 'withRSA', - prov: 'cryptojs/jsrsa' - }); - var signedCert = pki_data[0]; - var der = signedCert.toString('hex'); - // var pem = PaymentProtocol.DERtoPEM(der, 'CERTIFICATE'); - var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(der, 'CERTIFICATE'); - jsrsaSig.initVerifyByCertificatePEM(pem); - jsrsaSig.updateHex(buf.toString('hex')); - jsrsaSig.verify(sig.toString('hex')).should.equal(true); - } else { - var crypto = require('crypto'); - var type = 'SHA256'; - var pem = PaymentProtocol.DERtoPEM(pki_data[0], 'CERTIFICATE'); - var buf = pr.serializeForSig(); - var verifier = crypto.createVerify('RSA-' + type); - verifier.update(buf); - verifier.verify(pem, sig).should.equal(true); - } - - // Verify Signature - var verified = pr.x509Verify(); - verified.should.equal(true); - - // Verify Signature with trust properties - var trust = pr.x509Verify(true); - trust.selfSigned.should.equal(0); - trust.isChain.should.equal(true); - trust.verified.should.equal(true); - trust.caTrusted.should.equal(true); - trust.caName.should.equal('Go Daddy Class 2 CA'); - trust.chainVerified.should.equal(true); - - // PaymentDetails - details = PaymentProtocol.PaymentDetails.decode(details); - var pd = new PaymentProtocol(); - pd = pd.makePaymentDetails(details); - var network = pd.get('network'); - var outputs = pd.get('outputs'); - var time = pd.get('time'); - var expires = pd.get('expires'); - var memo = pd.get('memo'); - var payment_url = pd.get('payment_url'); - var merchant_data = pd.get('merchant_data'); - - network.should.equal('test'); - outputs.length.should.equal(1); - outputs[0].amount.should.not.equal(undefined); - outputs[0].script.should.not.equal(undefined); - time.should.equal(1408645830); - expires.should.equal(1408646730); - memo.should.equal('Payment request for BitPay invoice CMWpuFsjgmQ2ZLiyGfcF1W'); - payment_url.should.equal('https://test.bitpay.com/i/CMWpuFsjgmQ2ZLiyGfcF1W'); - should.equal(null, merchant_data); - }); - }); - - describe('#PEMtoDER', function() { - it('should convert a PEM cert to DER', function() { - var paypro = new PaymentProtocol(); - 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 PaymentProtocol(); - 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); - }); - }); - -}); From 41191a285fad812aa0305ef93e715011552e507c Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Sat, 10 Jan 2015 13:33:52 -0300 Subject: [PATCH 28/68] Add alternative to create an Address * When by error one has two instances of an address, an address can't be instantiated from the other --- lib/address.js | 11 ++++++----- test/address.js | 11 +++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/address.js b/lib/address.js index 0f80a20..be9fc8a 100644 --- a/lib/address.js +++ b/lib/address.js @@ -143,12 +143,13 @@ Address._transformHash = function(hash){ * @return {Address} */ Address._transformObject = function(data) { - $.checkArgument(data.hash, 'Must provide a `hash` property'); + $.checkArgument(data.hash || data.hashBuffer, 'Must provide a `hash` or `hashBuffer` property'); $.checkArgument(data.type, 'Must provide a `type` property'); - data.hashBuffer = new Buffer(data.hash, 'hex'); - data.network = Networks.get(data.network) || Networks.defaultNetwork; - - return data; + return { + hashBuffer: data.hash ? new Buffer(data.hash, 'hex') : data.hashBuffer, + network: Networks.get(data.network) || Networks.defaultNetwork, + type: data.type + }; }; /** diff --git a/test/address.js b/test/address.js index 17218b8..85c7fc3 100644 --- a/test/address.js +++ b/test/address.js @@ -210,7 +210,18 @@ describe('Address', function() { should.not.exist(error); } }); + }); + describe('instantiation', function() { + it('can be instantiated from another address', function() { + var address = Address.fromBuffer(buf); + var address2 = new Address({ + hashBuffer: address.hashBuffer, + network: address.network, + type: address.type + }); + address.toString().should.equal(address2.toString()); + }); }); describe('encodings', function() { From b827e36e137e7cc64f4add2c6aac7765769a2534 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Sun, 11 Jan 2015 13:35:44 +0200 Subject: [PATCH 29/68] Added mempool request I added `GetMempool` function that sends an 'mempool' request. the answer will come in 'inv' message. --- lib/transport/messages.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/transport/messages.js b/lib/transport/messages.js index 8817463..ffe82c7 100644 --- a/lib/transport/messages.js +++ b/lib/transport/messages.js @@ -584,6 +584,17 @@ function GetHeaders(starts, stop) { util.inherits(GetHeaders, GetBlocks); module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders; +/** + * GetMempool Message + * + * @name Transport.Message.GetMempool + */ +function GetMempool() { + this.command = 'mempool'; +} + +util.inherits(GetMempool, Message); +module.exports.GetMempool = Message.COMMANDS.mempool = GetMempool; // TODO: Remove this PATCH (yemel) Buffers.prototype.skip = function (i) { From f3663e26d64c565b98b69b86d2be755ec6724039 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 12 Jan 2015 10:56:27 -0300 Subject: [PATCH 30/68] Don't add the same input twice --- lib/transaction/transaction.js | 7 ++++ test/transaction/transaction.js | 58 +++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index accd86e..a22114f 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -337,6 +337,13 @@ Transaction.prototype.from = function(utxo, pubkeys, threshold) { }); return this; } + var exists = _.any(this.inputs, function(input) { + // TODO: Maybe prevTxId should be a string? Or defined as read only property? + return input.prevTxId.toString('hex') === utxo.txId && input.outputIndex === utxo.outputIndex; + }); + if (exists) { + return; + } if (pubkeys && threshold) { this._fromMultisigUtxo(utxo, pubkeys, threshold); } else { diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 0892a2f..2f53350 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -120,6 +120,40 @@ describe('Transaction', function() { var changeAddressP2SH = '2N7T3TAetJrSCruQ39aNrJvYLhG1LJosujf'; var privateKey = 'cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY'; + var simpleUtxoWith1BTC = { + address: fromAddress, + txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458', + outputIndex: 0, + script: Script.buildPublicKeyHashOut(fromAddress).toString(), + satoshis: 1e8 + }; + + describe('adding inputs', function() { + + it('it only adds once one utxo', function() { + var tx = new Transaction(); + tx.from(simpleUtxoWith1BTC); + tx.from(simpleUtxoWith1BTC); + tx.inputs.length.should.equal(1); + }); + + describe('not enough information errors', function() { + it('fails when Inputs are not subclassed and isFullySigned is called', function() { + var tx = new Transaction(tx_1_hex); + expect(function() { + return tx.isFullySigned(); + }).to.throw(errors.Transaction.UnableToVerifySignature); + }); + + it('fails when Inputs are not subclassed and verifySignature is called', function() { + var tx = new Transaction(tx_1_hex); + expect(function() { + return tx.isValidSignature({inputIndex: 0}); + }).to.throw(errors.Transaction.UnableToVerifySignature); + }); + }); + }); + describe('change address', function() { it('can calculate simply the output amount', function() { var transaction = new Transaction() @@ -190,30 +224,6 @@ describe('Transaction', function() { }); }); - var simpleUtxoWith1BTC = { - address: fromAddress, - txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458', - outputIndex: 0, - script: Script.buildPublicKeyHashOut(fromAddress).toString(), - satoshis: 1e8 - }; - - describe('not enough information errors', function() { - it('fails when Inputs are not subclassed and isFullySigned is called', function() { - var tx = new Transaction(tx_1_hex); - expect(function() { - return tx.isFullySigned(); - }).to.throw(errors.Transaction.UnableToVerifySignature); - }); - - it('fails when Inputs are not subclassed and verifySignature is called', function() { - var tx = new Transaction(tx_1_hex); - expect(function() { - return tx.isValidSignature({inputIndex: 0}); - }).to.throw(errors.Transaction.UnableToVerifySignature); - }); - }); - describe('serialization', function() { it('stores the change address correctly', function() { var serialized = new Transaction() From eaa07363a97941636aa26cb1d5471fac01b599ea Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 12 Jan 2015 16:06:22 -0300 Subject: [PATCH 31/68] Drop code for the p2p module --- lib/transport/index.js | 5 +- lib/transport/messages.js | 613 -------------------------------------- lib/transport/peer.js | 194 ------------ lib/transport/pool.js | 275 ----------------- 4 files changed, 1 insertion(+), 1086 deletions(-) delete mode 100644 lib/transport/messages.js delete mode 100644 lib/transport/peer.js delete mode 100644 lib/transport/pool.js diff --git a/lib/transport/index.js b/lib/transport/index.js index 7d25662..6e49efa 100644 --- a/lib/transport/index.js +++ b/lib/transport/index.js @@ -2,8 +2,5 @@ * @namespace Transport */ module.exports = { - explorers: require('./explorers'), - Messages: require('./messages'), - Peer: require('./peer'), - Pool: require('./pool') + explorers: require('./explorers') }; diff --git a/lib/transport/messages.js b/lib/transport/messages.js deleted file mode 100644 index ffe82c7..0000000 --- a/lib/transport/messages.js +++ /dev/null @@ -1,613 +0,0 @@ -'use strict'; -/** - * @namespace Transport.Message - */ -/* jshint curly: false */ - -var Buffers = require('buffers'); -var Put = require('bufferput'); -var util = require('util'); - -var BlockHeaderModel = require('../blockheader'); -var BlockModel = require('../block'); -var BufferReader = require('../encoding/bufferreader'); -var BufferUtil = require('../util/buffer'); -var Hash = require('../crypto/hash'); -var Random = require('../crypto/random'); -var TransactionModel = require('../transaction'); - -var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8); -var PROTOCOL_VERSION = 70000; - -/** - * Static helper for consuming a data buffer until the next message. - * - * @name Transport.Message#parseMessage - * @param{Network} network - the network object - * @param{Buffer} dataBuffer - the buffer to read from - * @returns{Message|undefined} A message or undefined if there is nothing to read. - */ -var parseMessage = function(network, dataBuffer) { - if (dataBuffer.length < 20) return; - - // Search the next magic number - if (!discardUntilNextMessage(network, dataBuffer)) return; - - var PAYLOAD_START = 16; - var payloadLen = (dataBuffer.get(PAYLOAD_START)) + - (dataBuffer.get(PAYLOAD_START + 1) << 8) + - (dataBuffer.get(PAYLOAD_START + 2) << 16) + - (dataBuffer.get(PAYLOAD_START + 3) << 24); - - var messageLength = 24 + payloadLen; - if (dataBuffer.length < messageLength) return; - - var command = dataBuffer.slice(4, 16).toString('ascii').replace(/\0+$/, ''); - var payload = dataBuffer.slice(24, messageLength); - var checksum = dataBuffer.slice(20, 24); - - var checksumConfirm = Hash.sha256sha256(payload).slice(0, 4); - if (!BufferUtil.equals(checksumConfirm, checksum)) { - dataBuffer.skip(messageLength); - return; - } - - dataBuffer.skip(messageLength); - return Message.buildMessage(command, payload); -}; - -module.exports.parseMessage = parseMessage; - -/** - * @desc Internal function that discards data until founds the next message. - * @name Transport.Message#discardUntilNextMessage - */ -function discardUntilNextMessage(network, dataBuffer) { - var magicNumber = network.networkMagic; - - var i = 0; - for (;;) { - // check if it's the beginning of a new message - var packageNumber = dataBuffer.slice(0, 4); - if (BufferUtil.equals(packageNumber, magicNumber)) { - dataBuffer.skip(i); - return true; - } - - // did we reach the end of the buffer? - if (i > (dataBuffer.length - 4)) { - dataBuffer.skip(i); - return false; - } - - i++; // continue scanning - } -} - -/** - * Abstract Message that knows how to parse and serialize itself. - * Concret subclases should implement {fromBuffer} and {getPayload} methods. - * @name Transport.Message - */ -function Message() {} - -/** - * @value - * @name Transport.Message.COMMANDS - */ -Message.COMMANDS = {}; - -/** - * Look up a message type by command name and instantiate the correct Message - * @name Transport.Message#buildMessage - */ -Message.buildMessage = function(command, payload) { - try { - var CommandClass = Message.COMMANDS[command]; - return new CommandClass().fromBuffer(payload); - } catch (err) { - console.log('Error while parsing message', err); - } -}; - -/** - * Parse instance state from buffer. - * - * @param{Buffer} payload - the buffer to read from - * @returns{Message} The same message instance - */ -Message.prototype.fromBuffer = function(payload) { - /* jshint unused: false */ - return this; -}; - -/** - * Serialize the payload into a buffer. - * - * @returns{Buffer} the serialized payload - */ -Message.prototype.getPayload = function() { - return BufferUtil.EMPTY_BUFFER; -}; - -/** - * Serialize the message into a buffer. - * - * @returns{Buffer} the serialized message - */ -Message.prototype.serialize = function(network) { - var magic = network.networkMagic; - var commandBuf = new Buffer(this.command, 'ascii'); - if (commandBuf.length > 12) throw 'Command name too long'; - - var payload = this.getPayload(); - var checksum = Hash.sha256sha256(payload).slice(0, 4); - - // -- HEADER -- - var message = new Put(); - message.put(magic); - message.put(commandBuf); - message.pad(12 - commandBuf.length); // zero-padded - message.word32le(payload.length); - message.put(checksum); - - // -- BODY -- - message.put(payload); - - return message.buffer(); -}; - -module.exports.Message = Message; - -/** - * Version Message - * - * @name Transport.Message.Version - * @param{string} subversion - version of the client - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Version(subversion, nonce) { - this.command = 'version'; - this.version = PROTOCOL_VERSION; - this.subversion = subversion || '/BitcoinX:0.1/'; - this.nonce = nonce || CONNECTION_NONCE; -} -util.inherits(Version, Message); - -Version.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.version = parser.readUInt32LE(); - this.services = parser.readUInt64LEBN(); - this.timestamp = parser.readUInt64LEBN(); - this.addr_me = parser.read(26); - this.addr_you = parser.read(26); - this.nonce = parser.read(8); - this.subversion = parser.readVarintBuf().toString(); - this.start_height = parser.readUInt32LE(); - - return this; -}; - -Version.prototype.getPayload = function() { - var put = new Put(); - put.word32le(this.version); // version - put.word64le(1); // services - put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp - put.pad(26); // addr_me - put.pad(26); // addr_you - put.put(this.nonce); - put.varint(this.subversion.length); - put.put(new Buffer(this.subversion, 'ascii')); - put.word32le(0); - - return put.buffer(); -}; - -module.exports.Version = Message.COMMANDS.version = Version; - -/** - * Inv Message - * - * @name Transport.Message.Inventory - * @param{Array} inventory - reported elements - */ -function Inventory(inventory) { - this.command = 'inv'; - this.inventory = inventory || []; -} -util.inherits(Inventory, Message); - -Inventory.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var count = parser.readVarintNum(); - for (var i = 0; i < count; i++) { - this.inventory.push({ - type: parser.readUInt32LE(), - hash: parser.read(32) - }); - } - - return this; -}; - -Inventory.prototype.getPayload = function() { - var put = new Put(); - - put.varint(this.inventory.length); - this.inventory.forEach(function(value) { - put.word32le(value.type); - put.put(value.hash); - }); - - return put.buffer(); -}; - -module.exports.Inventory = Message.COMMANDS.inv = Inventory; - -/** - * Getdata Message - * - * @name Transport.Message.GetData - * @param{Array} inventory - requested elements - */ -function GetData(inventory) { - this.command = 'getdata'; - this.inventory = inventory || []; -} - -util.inherits(GetData, Inventory); -module.exports.GetData = GetData; - -/** - * Ping Message - * - * @name Transport.Message.Ping - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Ping(nonce) { - this.command = 'ping'; - this.nonce = nonce || CONNECTION_NONCE; -} -util.inherits(Ping, Message); - -Ping.prototype.fromBuffer = function(payload) { - this.nonce = new BufferReader(payload).read(8); - return this; -}; - -Ping.prototype.getPayload = function() { - return this.nonce; -}; - -module.exports.Ping = Message.COMMANDS.ping = Ping; - -/** - * Pong Message - * - * @name Transport.Message.Pong - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Pong(nonce) { - this.command = 'pong'; - this.nonce = nonce || CONNECTION_NONCE; -} - -util.inherits(Pong, Ping); -module.exports.Pong = Message.COMMANDS.pong = Pong; - -/** - * Addr Message - * - * @name Transport.Message.Addressess - * @param{Array} addresses - array of know addresses - */ -function Addresses(addresses) { - this.command = 'addr'; - this.addresses = addresses || []; -} -util.inherits(Addresses, Message); - -Addresses.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var addrCount = Math.min(parser.readVarintNum(), 1000); - - this.addresses = []; - for (var i = 0; i < addrCount; i++) { - // TODO: Time actually depends on the version of the other peer (>=31402) - - var time = parser.readUInt32LE(); - var services = parser.readUInt64LEBN(); - - // parse the ipv6 to a string - var ipv6 = []; - for (var a = 0; a < 6; a++) { - ipv6.push(parser.read(2).toString('hex')); - } - ipv6 = ipv6.join(':'); - - // parse the ipv4 to a string - var ipv4 = []; - for (var b = 0; b < 4; b++) { - ipv4.push(parser.read(1)[0]); - } - ipv4 = ipv4.join('.'); - - var port = parser.readUInt16BE(); - - this.addresses.push({ - time: time, - services: services, - ip: { v6: ipv6, v4: ipv4 }, - port: port - }); - } - - return this; -}; - -Addresses.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.addresses.length); - - for (var i = 0; i < this.addresses.length; i++) { - put.word32le(this.addresses[i].time); - put.word64le(this.addresses[i].services); - put.put(this.addresses[i].ip); - put.word16be(this.addresses[i].port); - } - - return put.buffer(); -}; - -module.exports.Addresses = Message.COMMANDS.addr = Addresses; - -/** - * GetAddr Message - * - * @name Transport.Message.GetAddresses - */ -function GetAddresses() { - this.command = 'getaddr'; -} - -util.inherits(GetAddresses, Message); -module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses; - -/** - * Verack Message - * - * @name Transport.Message.VerAck - */ -function VerAck() { - this.command = 'verack'; -} - -util.inherits(VerAck, Message); -module.exports.VerAck = Message.COMMANDS.verack = VerAck; - -/** - * Reject Message - * - * @name Transport.Message.Reject - */ -function Reject() { - this.command = 'reject'; -} -util.inherits(Reject, Message); - -// TODO: Parse REJECT message - -module.exports.Reject = Message.COMMANDS.reject = Reject; - -/** - * Alert Message - * - * @name Transport.Message.Alert - */ -function Alert(payload, signature) { - this.command = 'alert'; - this.payload = payload || new Buffer(32); - this.signature = signature || new Buffer(32); -} -util.inherits(Alert, Message); - -Alert.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.payload = parser.readVarintBuf(); // TODO: Use current format - this.signature = parser.readVarintBuf(); - return this; -}; - -Alert.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.payload.length); - put.put(this.payload); - - put.varint(this.signature.length); - put.put(this.signature); - - return put.buffer(); -}; - -module.exports.Alert = Message.COMMANDS.alert = Alert; - -/** - * Headers Message - * - * @name Transport.Message.Headers - * @param{Array} blockheaders - array of block headers - */ -function Headers(blockheaders) { - this.command = 'headers'; - this.headers = blockheaders || []; -} -util.inherits(Headers, Message); - -Headers.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var count = parser.readVarintNum(); - - this.headers = []; - for (var i = 0; i < count; i++) { - var header = BlockHeaderModel._fromBufferReader(parser); - this.headers.push(header); - } - - return this; -}; - -Headers.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.headers.length); - - for (var i = 0; i < this.headers.length; i++) { - var buffer = this.headers[i].toBuffer(); - put.put(buffer); - } - - return put.buffer(); -}; - -module.exports.Headers = Message.COMMANDS.headers = Headers; - -/** - * Block Message - * - * @name Transport.Message.Block - * @param{Block} block - */ -function Block(block) { - this.command = 'block'; - this.block = block; -} -util.inherits(Block, Message); - -Block.prototype.fromBuffer = function(payload) { - this.block = BlockModel(payload); - return this; -}; - -Block.prototype.getPayload = function() { - return this.block.toBuffer(); -}; - -module.exports.Block = Message.COMMANDS.block = Block; - -/** - * Tx Message - * - * @name Transport.Message.Transaction - * @param{Transaction} transaction - */ -function Transaction(transaction) { - this.command = 'tx'; - this.transaction = transaction; -} -util.inherits(Transaction, Message); - -Transaction.prototype.fromBuffer = function(payload) { - this.transaction = TransactionModel(payload); - return this; -}; - -Transaction.prototype.getPayload = function() { - return this.transaction.toBuffer(); -}; - -module.exports.Transaction = Message.COMMANDS.tx = Transaction; - -/** - * Getblocks Message - * - * @name Transport.Message.GetBlocks - * @param{Array} starts - array of buffers with the starting block hashes - * @param{Buffer} [stop] - hash of the last block - */ -function GetBlocks(starts, stop) { - this.command = 'getblocks'; - this.version = PROTOCOL_VERSION; - this.starts = starts || []; - this.stop = stop || BufferUtil.NULL_HASH; -} -util.inherits(GetBlocks, Message); - -GetBlocks.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.version = parser.readUInt32LE(); - - var startCount = Math.min(parser.readVarintNum(), 500); - this.starts = []; - for (var i = 0; i < startCount; i++) { - this.starts.push(parser.read(32)); - } - this.stop = parser.read(32); - - return this; -}; - -GetBlocks.prototype.getPayload = function() { - var put = new Put(); - put.word32le(this.version); - put.varint(this.starts.length); - - for (var i = 0; i < this.starts.length; i++) { - if (this.starts[i].length !== 32) { - throw new Error('Invalid hash length'); - } - put.put(this.starts[i]); - } - - if (this.stop.length !== 32) { - throw new Error('Invalid hash length'); - } - put.put(this.stop); - - return put.buffer(); -}; - -module.exports.GetBlocks = Message.COMMANDS.getblocks = GetBlocks; - -/** - * Getheaders Message - * - * @name Transport.Message.GetHeaders - * @param{Array} starts - array of buffers with the starting block hashes - * @param{Buffer} [stop] - hash of the last block - */ -function GetHeaders(starts, stop) { - this.command = 'getheaders'; - this.version = PROTOCOL_VERSION; - this.starts = starts || []; - this.stop = stop || BufferUtil.NULL_HASH; -} - -util.inherits(GetHeaders, GetBlocks); -module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders; - -/** - * GetMempool Message - * - * @name Transport.Message.GetMempool - */ -function GetMempool() { - this.command = 'mempool'; -} - -util.inherits(GetMempool, Message); -module.exports.GetMempool = Message.COMMANDS.mempool = GetMempool; - -// TODO: Remove this PATCH (yemel) -Buffers.prototype.skip = function (i) { - if (i === 0) return; - - if (i === this.length) { - this.buffers = []; - this.length = 0; - return; - } - - var pos = this.pos(i); - this.buffers = this.buffers.slice(pos.buf); - this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset)); - this.length -= i; -}; diff --git a/lib/transport/peer.js b/lib/transport/peer.js deleted file mode 100644 index 1c10f1b..0000000 --- a/lib/transport/peer.js +++ /dev/null @@ -1,194 +0,0 @@ -'use strict'; - -var Buffers = require('buffers'); -var EventEmitter = require('events').EventEmitter; -var Net = require('net'); -var Socks5Client = require('socks5-client'); -var util = require('util'); - -var Networks = require('../networks'); -var Messages = require('./messages'); - -var MAX_RECEIVE_BUFFER = 10000000; - -/** - * A Peer instance represents a remote bitcoin node and allows to communicate - * with it using the standar messages of the bitcoin p2p protocol. - * - * @example - * ```javascript - * - * var peer = new Peer('127.0.0.1').setProxy('127.0.0.1', 9050); - * peer.on('tx', function(tx) { - * console.log('New transaction: ', tx.id); - * }); - * peer.connect(); - * ``` - * - * @param {String} host - IP address of the remote host - * @param {Number} [port] - Port number of the remote host - * @param {Network} [network] - The context for this communication - * @returns {Peer} A new instance of Peer. - * @constructor - */ -function Peer(host, port, network) { - if (!(this instanceof Peer)) { - return new Peer(host, port, network); - } - - // overloading stuff - if (port instanceof Object && !network) { - network = port; - port = undefined; - } - - this.host = host; - this.status = Peer.STATUS.DISCONNECTED; - this.network = network || Networks.livenet; - this.port = port || this.network.port; - - this.dataBuffer = new Buffers(); - - this.version = 0; - this.bestHeight = 0; - this.subversion = null; - - // set message handlers - var self = this; - this.on('verack', function() { - self.status = Peer.STATUS.READY; - self.emit('ready'); - }); - - this.on('version', function(message) { - self.version = message.version; - self.subversion = message.subversion; - self.bestHeight = message.start_height - }); - - this.on('ping', function(message) { - self._sendPong(message.nonce); - }); - -} -util.inherits(Peer, EventEmitter); - -Peer.STATUS = { - DISCONNECTED: 'disconnected', - CONNECTING: 'connecting', - CONNECTED: 'connected', - READY: 'ready' -}; - -/** - * Set a socks5 proxy for the connection. Enables the use of the TOR network. - * - * @param {String} host - IP address of the proxy - * @param {Number} port - Port number of the proxy - * @returns {Peer} The same Peer instance. - */ -Peer.prototype.setProxy = function(host, port) { - if (this.status != Peer.STATUS.DISCONNECTED) { - throw Error('Invalid State'); - } - - this.proxy = { - host: host, - port: port - }; - return this; -}; - -/** - * Init the connection with the remote peer. - * - * @returns {Socket} The same peer instance. - */ -Peer.prototype.connect = function() { - this.socket = this._getSocket(); - this.status = Peer.STATUS.CONNECTING; - - var self = this; - this.socket.on('connect', function(ev) { - self.status = Peer.STATUS.CONNECTED; - self.emit('connect'); - self._sendVersion(); - }); - - this.socket.on('error', self.disconnect.bind(this)); - this.socket.on('end', self.disconnect.bind(this)); - - this.socket.on('data', function(data) { - self.dataBuffer.push(data); - - if (self.dataBuffer.length > MAX_RECEIVE_BUFFER) return self.disconnect(); - self._readMessage(); - }); - - this.socket.connect(this.port, this.host); - return this; -}; - -/** - * Disconnects the remote connection. - * - * @returns {Socket} The same peer instance. - */ -Peer.prototype.disconnect = function() { - this.status = Peer.STATUS.DISCONNECTED; - this.socket.destroy(); - this.emit('disconnect'); - return this; -}; - -/** - * Send a Message to the remote peer. - * - * @param {Message} message - A message instance - */ -Peer.prototype.sendMessage = function(message) { - this.socket.write(message.serialize(this.network)); -}; - -/** - * Internal function that sends VERSION message to the remote peer. - */ -Peer.prototype._sendVersion = function() { - var message = new Messages.Version(); - this.sendMessage(message); -}; - -/** - * Send a PONG message to the remote peer. - */ -Peer.prototype._sendPong = function(nonce) { - var message = new Messages.Pong(nonce); - this.sendMessage(message); -}; - -/** - * Internal function that tries to read a message from the data buffer - */ -Peer.prototype._readMessage = function() { - var message = Messages.parseMessage(this.network, this.dataBuffer); - - if (message) { - this.emit(message.command, message); - this._readMessage(); - } -}; - -/** - * Internal function that creates a socket using a proxy if neccesary. - * - * @returns {Socket} A Socket instance not yet connected. - */ -Peer.prototype._getSocket = function() { - if (this.proxy) { - return new Socks5Client(this.proxy.host, this.proxy.port); - } - - return new Net.Socket(); -}; - -module.exports = Peer; diff --git a/lib/transport/pool.js b/lib/transport/pool.js deleted file mode 100644 index ec2b64c..0000000 --- a/lib/transport/pool.js +++ /dev/null @@ -1,275 +0,0 @@ -'use strict'; - -var dns = require('dns'); -var EventEmitter = require('events').EventEmitter; -var Networks = require('../networks'); -var sha256 = require('../crypto/hash').sha256; -var Peer = require('./peer'); -var util = require('util'); - -function now() { - return Math.floor(new Date().getTime() / 1000); -} - -/** - * A pool is a collection of Peers. A pool will discover peers from DNS seeds, and - * collect information about new peers in the network. When a peer disconnects the pool - * will connect to others that are available to maintain a max number of - * ongoing peer connections. Peer events are relayed to the pool. - * - * @example - * ```javascript - * - * var pool = new Pool(Networks.livenet); - * pool.on('peerinv', function(peer, message) { - * // do something with the inventory announcement - * }); - * pool.connect(); - * ``` - * - * @param {Network|String} network - The network to connect - * @returns {Pool} - * @constructor - */ -function Pool(network) { - - var self = this; - - this.network = Networks.get(network) || Networks.defaultNetwork; - this.keepalive = false; - this._connectedPeers = {}; - this._addrs = []; - - this.on('peeraddr', function peerAddrEvent(peer, message) { - var addrs = message.addresses; - var length = addrs.length; - for (var i = 0; i < length; i++) { - var addr = addrs[i]; - // In case of an invalid time, assume "5 days ago" - if (addr.time <= 100000000 || addr.time > (now() + 10 * 60)) { - addr.time = now() - 5 * 24 * 60 * 60; - } - this._addAddr(addr); - } - }); - - this.on('seed', function seedEvent(ips) { - ips.forEach(function(ip) { - self._addAddr({ - ip: { - v4: ip - } - }); - }); - if (self.keepalive) { - self._fillConnections(); - } - }); - - this.on('peerdisconnect', function peerDisconnectEvent(peer, addr) { - self._deprioritizeAddr(addr); - self._removeConnectedPeer(addr); - if (self.keepalive) { - self._fillConnections(); - } - }); - - return this; - -} - -util.inherits(Pool, EventEmitter); - -Pool.MaxConnectedPeers = 8; -Pool.RetrySeconds = 30; -Pool.PeerEvents = ['version', 'inv', 'getdata', 'ping', 'ping', 'addr', - 'getaddr', 'verack', 'reject', 'alert', 'headers', 'block', - 'tx', 'getblocks', 'getheaders' -]; - - -/** - * Will initiatiate connection to peers, if available peers have been added to - * the pool, it will connect to those, otherwise will use DNS seeds to find - * peers to connect. When a peer disconnects it will add another. - */ -Pool.prototype.connect = function connect() { - this.keepalive = true; - var self = this; - if (self._addrs.length === 0) { - self._addAddrsFromSeeds(); - } else { - self._fillConnections(); - } - return this; -}; - - -/** - * Will disconnect all peers that are connected. - */ -Pool.prototype.disconnect = function disconnect() { - this.keepalive = false; - for (var i in this._connectedPeers) { - this._connectedPeers[i].disconnect(); - } - return this; -}; - -/** - * @returns {Number} The number of peers currently connected. - */ -Pool.prototype.numberConnected = function numberConnected() { - return Object.keys(this._connectedPeers).length; -}; - -/** - * Will fill the conneted peers to the maximum amount. - */ -Pool.prototype._fillConnections = function _fillConnections() { - var length = this._addrs.length; - for (var i = 0; i < length; i++) { - if (this.numberConnected() >= Pool.MaxConnectedPeers) { - break; - } - var addr = this._addrs[i]; - if (!addr.retryTime || now() > addr.retryTime) { - this._connectPeer(addr); - } - } - return this; -}; - -/** - * Will remove a peer from the list of connected peers. - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._removeConnectedPeer = function _removeConnectedPeer(addr) { - if (this._connectedPeers[addr.hash].status !== Peer.STATUS.DISCONNECTED) { - this._connectedPeers[addr.hash].disconnect(); - } else { - delete this._connectedPeers[addr.hash]; - } - return this; -}; - -/** - * Will connect a peer and add to the list of connected peers. - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._connectPeer = function _connectPeer(addr) { - var self = this; - - function addConnectedPeer(addr) { - var port = addr.port || self.network.port; - var ip = addr.ip.v4 || addr.ip.v6; - var peer = new Peer(ip, port, self.network); - peer.on('disconnect', function peerDisconnect() { - self.emit('peerdisconnect', peer, addr); - }); - peer.on('ready', function peerReady() { - self.emit('peerready', peer, addr); - }); - Pool.PeerEvents.forEach(function addPeerEvents(event) { - peer.on(event, function peerEvent(message) { - self.emit('peer' + event, peer, message); - }); - }); - peer.connect(); - self._connectedPeers[addr.hash] = peer; - } - - if (!this._connectedPeers[addr.hash]) { - addConnectedPeer(addr); - } - - return this; -}; - -/** - * Will deprioritize an addr in the list of addrs by moving it to the end - * of the array, and setting a retryTime - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._deprioritizeAddr = function _deprioritizeAddr(addr) { - for (var i = 0; i < this._addrs.length; i++) { - if (this._addrs[i].hash === addr.hash) { - var middle = this._addrs[i]; - middle.retryTime = now() + Pool.RetrySeconds; - var beginning = this._addrs.splice(0, i); - var end = this._addrs.splice(i + 1, this._addrs.length); - var combined = beginning.concat(end); - this._addrs = combined.concat([middle]); - } - } - return this; -}; - -/** - * Will add an addr to the beginning of the addrs array - * @param {Object} - */ -Pool.prototype._addAddr = function _addAddr(addr) { - - // make a unique key - addr.hash = sha256(new Buffer(addr.ip.v6 + addr.ip.v4 + addr.port)).toString('hex'); - - var length = this._addrs.length; - var exists = false; - for (var i = 0; i < length; i++) { - if (this._addrs[i].hash === addr.hash) { - exists = true; - } - } - if (!exists) { - this._addrs.unshift(addr); - } - return this; -}; - -/** - * Will add addrs to the list of addrs from a DNS seed - * @param {String} seed - A domain name to resolve known peers - * @param {Function} done - */ -Pool.prototype._addAddrsFromSeed = function _addAddrsFromSeed(seed) { - var self = this; - dns.resolve(seed, function(err, ips) { - if (err) { - self.emit('seederror', err); - return; - } - if (!ips || !ips.length) { - self.emit('seederror', new Error('No IPs found from seed lookup.')); - return; - } - // announce to pool - self.emit('seed', ips); - }); - return this; -}; - -/** - * Will add addrs to the list of addrs from network DNS seeds - * @param {Function} done - */ -Pool.prototype._addAddrsFromSeeds = function _addAddrsFromSeeds() { - var self = this; - var seeds = this.network.dnsSeeds; - seeds.forEach(function(seed) { - self._addAddrsFromSeed(seed); - }); - return this; -}; - -/** - * @returns {String} A string formatted for the console - */ -Pool.prototype.inspect = function inspect() { - return ''; -}; - -module.exports = Pool; From 456b4345f022e4d27b0574bb361f74bbd7c86132 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 12 Jan 2015 16:06:46 -0300 Subject: [PATCH 32/68] Drop tests for p2p --- test/transport/messages.js | 353 ------------------------------------- test/transport/peer.js | 75 -------- test/transport/pool.js | 104 ----------- 3 files changed, 532 deletions(-) delete mode 100644 test/transport/messages.js delete mode 100644 test/transport/peer.js delete mode 100644 test/transport/pool.js diff --git a/test/transport/messages.js b/test/transport/messages.js deleted file mode 100644 index 15325b3..0000000 --- a/test/transport/messages.js +++ /dev/null @@ -1,353 +0,0 @@ -'use strict'; - -var chai = require('chai'); - -var should = chai.should(); - -var bitcore = require('../..'); -var Data = require('../data/messages'); -var Messages = bitcore.transport.Messages; -var Networks = bitcore.Networks; - -describe('Messages', function() { - - describe('Version', function() { - it('should be able to create instance', function() { - var message = new Messages.Version(); - message.command.should.equal('version'); - message.version.should.equal(70000); - message.subversion.should.equal('/BitcoinX:0.1/'); - should.exist(message.nonce); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Version(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Version(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.VERSION.payload, 'hex'); - new Messages.Version().fromBuffer(payload); - }); - }); - - describe('VerAck', function() { - it('should be able to create instance', function() { - var message = new Messages.VerAck(); - message.command.should.equal('verack'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.VerAck(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.VerAck(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.VERACK.payload, 'hex'); - new Messages.VerAck().fromBuffer(payload); - }); - }); - - describe('Inventory', function() { - it('should be able to create instance', function() { - var message = new Messages.Inventory(); - message.command.should.equal('inv'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Inventory(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Inventory(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.INV.payload, 'hex'); - new Messages.Inventory().fromBuffer(payload); - }); - }); - - describe('Addresses', function() { - it('should be able to create instance', function() { - var message = new Messages.Addresses(); - message.command.should.equal('addr'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Addresses(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Addresses(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.ADDR.payload, 'hex'); - new Messages.Addresses().fromBuffer(payload); - }); - }); - - describe('Ping', function() { - it('should be able to create instance', function() { - var message = new Messages.Ping(); - message.command.should.equal('ping'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Ping(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Ping(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.PING.payload, 'hex'); - new Messages.Ping().fromBuffer(payload); - }); - }); - - describe('Pong', function() { - it('should be able to create instance', function() { - var message = new Messages.Pong(); - message.command.should.equal('pong'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Pong(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Pong(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - - it('should be able to parse payload', function() { - var payload = new Buffer(Data.PING.payload, 'hex'); - new Messages.Pong().fromBuffer(payload); - }); - }); - - describe('Alert', function() { - it('should be able to create instance', function() { - var message = new Messages.Alert(); - message.command.should.equal('alert'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Alert(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Alert(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('Reject', function() { - it('should be able to create instance', function() { - var message = new Messages.Reject(); - message.command.should.equal('reject'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Reject(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Reject(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('Block', function() { - var blockHex = 'f9beb4d91d0100000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; - var block = new bitcore.Block(new Buffer(blockHex, 'hex')); - - it('should be able to create instance', function() { - var message = new Messages.Block(block); - message.command.should.equal('block'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Block(block); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Block(block); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('GetBlocks', function() { - it('should be able to create instance', function() { - var message = new Messages.GetBlocks(); - message.command.should.equal('getblocks'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.GetBlocks(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.GetBlocks(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('GetHeaders', function() { - it('should be able to create instance', function() { - var message = new Messages.GetHeaders(); - message.command.should.equal('getheaders'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.GetHeaders(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.GetHeaders(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('GetData', function() { - it('should be able to create instance', function() { - var message = new Messages.GetData(); - message.command.should.equal('getdata'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.GetData(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.GetData(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('GetData', function() { - it('should be able to create instance', function() { - var message = new Messages.GetData(); - message.command.should.equal('getdata'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.GetData(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.GetData(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('GetAddresses', function() { - it('should be able to create instance', function() { - var message = new Messages.GetAddresses(); - message.command.should.equal('getaddr'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.GetAddresses(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.GetAddresses(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('Headers', function() { - it('should be able to create instance', function() { - var message = new Messages.Headers(); - message.command.should.equal('headers'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Headers(); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Headers(); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); - - describe('Transaction', function() { - it('should be able to create instance', function() { - var message = new Messages.Transaction(new bitcore.Transaction()); - message.command.should.equal('tx'); - }); - - it('should be able to serialize the payload', function() { - var message = new Messages.Transaction(new bitcore.Transaction()); - var payload = message.getPayload(); - should.exist(payload); - }); - - it('should be able to serialize the message', function() { - var message = new Messages.Transaction(new bitcore.Transaction()); - var buffer = message.serialize(Networks.livenet); - should.exist(buffer); - }); - }); -}); diff --git a/test/transport/peer.js b/test/transport/peer.js deleted file mode 100644 index 066ee7a..0000000 --- a/test/transport/peer.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var Net = require('net'); -var Socks5Client = require('socks5-client'); - -/* jshint unused: false */ -var should = chai.should(); -var expect = chai.expect; - -var bitcore = require('../..'); -var Peer = bitcore.transport.Peer; -var Networks = bitcore.Networks; - -describe('Peer', function() { - - it('should be able to create instance', function() { - var peer = new Peer('localhost'); - peer.host.should.equal('localhost'); - peer.network.should.equal(Networks.livenet); - peer.port.should.equal(Networks.livenet.port); - }); - - it('should be able to create instance setting a port', function() { - var peer = new Peer('localhost', 8111); - peer.host.should.equal('localhost'); - peer.network.should.equal(Networks.livenet); - peer.port.should.equal(8111); - }); - - it('should be able to create instance setting a network', function() { - var peer = new Peer('localhost', Networks.testnet); - peer.host.should.equal('localhost'); - peer.network.should.equal(Networks.testnet); - peer.port.should.equal(Networks.testnet.port); - }); - - it('should be able to create instance setting port and network', function() { - var peer = new Peer('localhost', 8111, Networks.testnet); - peer.host.should.equal('localhost'); - peer.network.should.equal(Networks.testnet); - peer.port.should.equal(8111); - }); - - it('should support creating instance without new', function() { - var peer = Peer('localhost', 8111, Networks.testnet); - peer.host.should.equal('localhost'); - peer.network.should.equal(Networks.testnet); - peer.port.should.equal(8111); - }); - - if (typeof(window) === 'undefined'){ - - // Node.js Tests - - it('should be able to set a proxy', function() { - var peer, peer2, socket; - - peer = new Peer('localhost'); - expect(peer.proxy).to.be.undefined(); - socket = peer._getSocket(); - socket.should.be.instanceof(Net.Socket); - - peer2 = peer.setProxy('127.0.0.1', 9050); - peer2.proxy.host.should.equal('127.0.0.1'); - peer2.proxy.port.should.equal(9050); - socket = peer2._getSocket(); - socket.should.be.instanceof(Socks5Client); - - peer.should.equal(peer2); - }); - - } - -}); diff --git a/test/transport/pool.js b/test/transport/pool.js deleted file mode 100644 index ced95f1..0000000 --- a/test/transport/pool.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -if (typeof(window) === 'undefined'){ - - // Node.js Tests - - var chai = require('chai'); - - /* jshint unused: false */ - var should = chai.should(); - var expect = chai.expect; - - var dns = require('dns'); - var sinon = require('sinon'); - - var bitcore = require('../..'); - var Peer = bitcore.transport.Peer; - var MessagesData = require('../data/messages'); - var Messages = bitcore.transport.Messages; - var Pool = bitcore.transport.Pool; - var Networks = bitcore.Networks; - - describe('Pool', function() { - - it('should be able to create instance', function() { - var pool = new Pool(); - should.exist(pool.network); - expect(pool.network).to.satisfy(function(network){ - if (network === Networks.testnet || network === Networks.livenet) { - return true; - } - return false; - }); - }); - - it('should be able to create instance setting the network', function() { - var pool = new Peer(Networks.testnet); - pool.network.should.equal(Networks.livenet); - }); - - it('should discover peers via dns', function() { - var stub = sinon.stub(dns, 'resolve', function(seed, callback){ - callback(null, ['10.10.10.1', '10.10.10.2', '10.10.10.3']); - }); - var pool = new Pool(Networks.livenet); - pool.connect(); - pool.disconnect(); - pool._addrs.length.should.equal(3); - stub.restore(); - }); - - it('should not discover peers via dns', function() { - var pool = new Pool(); - pool._addAddr({ip: {v4: '10.10.10.1'}}); - pool.connect(); - pool.disconnect(); - pool._addrs.length.should.equal(1); - }); - - it('should add new addrs as they are announced over the network', function(done) { - - // only emit an event, no need to connect - var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function(){ - this._readMessage(); - this.emit('ready'); - }); - - // mock a addr peer event - var peerMessageStub = sinon.stub(Peer.prototype, '_readMessage', function(){ - var payload = new Buffer(MessagesData.ADDR.payload, 'hex'); - var message = new Messages.Addresses().fromBuffer(payload); - this.emit(message.command, message); - }); - - var pool = new Pool(); - - pool._addAddr({ip: {v4: 'localhost'}}); - - // listen for the event - pool.on('peeraddr', function(peer, message) { - pool._addrs.length.should.equal(502); - - // restore stubs - peerConnectStub.restore(); - peerMessageStub.restore(); - - for (var i = 0; i < pool._addrs.length; i++) { - should.exist(pool._addrs[i].hash); - should.exist(pool._addrs[i].ip); - should.exist(pool._addrs[i].ip.v4); - } - - // done - done(); - }); - - pool.connect(); - - }); - - - }); - -} From fce088758f7922b48539fb11fd0fc84eb17117ec Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 12 Jan 2015 16:05:23 -0300 Subject: [PATCH 33/68] Drop documentation for p2p --- docs/guide/peer.md | 105 --------------------------------------------- docs/guide/pool.md | 31 ------------- 2 files changed, 136 deletions(-) delete mode 100644 docs/guide/peer.md delete mode 100644 docs/guide/pool.md diff --git a/docs/guide/peer.md b/docs/guide/peer.md deleted file mode 100644 index ccd73a2..0000000 --- a/docs/guide/peer.md +++ /dev/null @@ -1,105 +0,0 @@ -title: Peer -description: The Peer class provides a simple interface for connecting to a node in the bitcoin network. ---- -# Peer - -## Description - -Represents a node from the p2p bitcoin network. The Peer class supports connecting directly to other nodes or through a socks5 proxy like Tor. - -## Creating a peer - -The code to create a new peer looks like this: - -```javascript -var bitcore = require('bitcore'); -var Peer = bitcore.transport.Peer; - -// default port -var livenetPeer = new Peer('5.9.85.34'); -var testnetPeer = new Peer('5.9.85.34', bitcore.testnet); - -// custom port -var livenetPeer = new Peer('5.9.85.34', 8334); -var testnetPeer = new Peer('5.9.85.34', 18334, bitcore.testnet); - -// use sock5 proxy (Tor) -var peer = new Peer('5.9.85.34').setProxy('localhost', 9050); -``` - -## States - -A peer instance is always in one of the following states: - -* `disconnected`: No connection with the remote node. -* `connecting`: While establishing the connection. -* `connected`: Exchanging version packages. -* `ready`: Connection ready for sending and receiving messages. - -You can subscribe to the change of those states as follows: - -```javascript -var bitcore = require('bitcore'); -var Peer = bitcore.transport.Peer; - -var peer = new Peer('5.9.85.34'); - -peer.on('ready', function() { - // peer info - console.log(peer.version, peer.subversion, peer.bestHeight); -}); - -peer.on('disconnect', function() { - console.log('connection closed'); -}); - -peer.connect(); -``` - -## Handle messages - -Once connected, a peer instance can send and receive messages. Every time a message arrives it's emitted as a new event. Let's see an example of this: - -```javascript -var bitcore = require('bitcore'); -var peer = new bitcore.transport.Peer('5.9.85.34'); - -// handle events -peer.on('inv', function(message) { - // message.inventory[] -}); - -peer.on('tx', function(message) { - // message.transaction -}); - -peer.on('addr', function(message) { - // message.addresses[] -}); - -peer.connect(); -``` - -## Sending messages - -In order to send messages the Peer class offers the `sendMessage(message)` method, which receives an instance of a message. All supported messages can be found on the `bitcore.transport.Messages` module. For more information about messages refer to the [protocol specification](https://en.bitcoin.it/wiki/Protocol_specification). - -An example for requesting other connected nodes to a peers looks like this: - -```javascript -var bitcore = require('bitcore'); -var peer = new bitcore.transport.Peer('5.9.85.34'); - -peer.on('ready', function() { - var message = new bitcore.transport.Messages.GetAddresses(); - peer.sendMessage(message); -}); - -peer.on('addr', function(message) { - message.addresses.forEach(function(address) { - // do something - }); -}); - -peer.connect(); -``` diff --git a/docs/guide/pool.md b/docs/guide/pool.md deleted file mode 100644 index cbcb4df..0000000 --- a/docs/guide/pool.md +++ /dev/null @@ -1,31 +0,0 @@ -title: Pool -description: A simple interface to create and maintain a set of connections to bitcoin nodes. ---- -# Pool - -A pool maintains a connection of [Peers](peer.md). A pool will discover peers via DNS seeds, as well as when peer addresses are announced through the network. - -The quickest way to get connected is to run the following: - -```javascript - -var bitcore = require('bitcore'); -var Pool = bitcore.transport.Pool; -var Networks = bitcore.Networks; - -var pool = new Pool(Networks.livenet); - -// connect to the network -pool.connect(); - -// attach peer events -pool.on('peerinv', function(peer, message) { - // a new peer message has arrived -}); - -// will disconnect all peers -pool.disconnect() - -``` - -For more information about Peer events please read the [Peer](peer.md) documentation. Peer events are relayed to the pool, a peer event `inv` in the pool would be `peerinv`. When a peer is disconnected the pool will try to connect to the list of known addresses to maintain connection. From 0f85e4ff1495b55d0dc1e12ffdb9938d7fa2cc61 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Mon, 12 Jan 2015 16:07:56 -0300 Subject: [PATCH 34/68] Drop unused dependencies --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 60baac5..a20d8a9 100644 --- a/package.json +++ b/package.json @@ -76,8 +76,6 @@ "bn.js": "=0.16.1", "browser-request": "^0.3.3", "bs58": "=2.0.0", - "bufferput": "^0.1.2", - "buffers": "^0.1.1", "elliptic": "=0.16.0", "hash.js": "=0.3.2", "inherits": "=2.0.1", From 149b7fafed79f9ea7f6dc7e8e2e6ac4030e4c574 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 12 Jan 2015 21:01:17 -0300 Subject: [PATCH 35/68] new error system with no code generation --- .gitignore | 2 - gulpfile.js | 12 +-- lib/errors/build.js | 49 --------- lib/errors/index.js | 60 +++++++++++ lib/errors/spec.js | 248 +++++++++++++++++++++----------------------- 5 files changed, 184 insertions(+), 187 deletions(-) delete mode 100644 lib/errors/build.js create mode 100644 lib/errors/index.js diff --git a/.gitignore b/.gitignore index 2be4b24..375322f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,6 @@ node_modules browser/tests.js docs/api -lib/errors/index.js - CONTRIBUTING.html LICENSE.html README.html diff --git a/gulpfile.js b/gulpfile.js index ed80a78..012a2b8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -21,7 +21,6 @@ *
  • `browser:compressed` - build `browser/bitcore.min.js` *
  • `browser:maketests` - build `browser/tests.js`, needed for testing without karma * ` - *
  • `errors` - autogenerate the `./lib/errors/index.js` file with error definitions *
  • `lint` - run `jshint` *
  • `coverage` - run `istanbul` with mocha to generate a report of test coverage *
  • `jsdoc` - run `jsdoc` to generate the API reference @@ -73,9 +72,9 @@ var testKarma = shell.task([ * Testing */ -gulp.task('test:node', ['errors'], testMocha); +gulp.task('test:node', testMocha); -gulp.task('test:node:nofail', ['errors'], function() { +gulp.task('test:node:nofail', function() { return testMocha().on('error', ignoreError); }); @@ -93,7 +92,7 @@ gulp.task('browser:makefolder', shell.task([ 'if [ ! -d "browser" ]; then mkdir browser; fi' ])); -gulp.task('browser:uncompressed', ['browser:makefolder', 'errors'], shell.task([ +gulp.task('browser:uncompressed', ['browser:makefolder'], shell.task([ './node_modules/.bin/browserify index.js --insert-global-vars=true --standalone=bitcore -o browser/bitcore.js' ])); @@ -116,11 +115,6 @@ gulp.task('browser', function(callback) { runSequence(['browser:compressed'], ['browser:maketests'], callback); }); -gulp.task('errors', shell.task([ - 'node ./lib/errors/build.js' -])); - - /** * Code quality and documentation */ diff --git a/lib/errors/build.js b/lib/errors/build.js deleted file mode 100644 index 723e1e4..0000000 --- a/lib/errors/build.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -var _ = require('lodash'); -var fs = require('fs'); - -var defineElement = function(fullName, baseClass, message) { - return fullName + ' = function() {\n' + - ' this.message = ' + message + ';\n' + - ' this.stack = this.message + \'\\n\' + (new Error()).stack;\n' + - '};\n' + - fullName + '.prototype = Object.create(' + baseClass + '.prototype);\n' + - fullName + '.prototype.name = "' + fullName + '";\n\n'; -}; - -var traverseNode = function(baseClass, errorDefinition) { - var className = baseClass + '.' + errorDefinition.name; - var generated = defineElement(className, baseClass, errorDefinition.message); - if (errorDefinition.errors) { - generated += childDefinitions(className, errorDefinition.errors); - } - return generated; -}; - -/* jshint latedef: false */ -var childDefinitions = function(parent, childDefinitions) { - var generated = ''; - _.each(childDefinitions, function(childDefinition) { - generated += traverseNode(parent, childDefinition); - }); - return generated; -}; -/* jshint latedef: true */ - -var traverseRoot = function(errorsDefinition) { - var fullName = 'bitcore.Error'; - var path = 'Error'; - var generated = '\'use strict\';\n\n'; - generated += '/* jshint maxlen: 300 */\n'; - generated += '/* jshint quotmark: false */\n'; - generated += '/* AUTOGENERATED FILE. DON\'T EDIT, MODIFY "lib/errors/spec.js" INSTEAD */\n\n'; - generated += 'var bitcore = {};\n\n'; - generated += defineElement(fullName, path, '\'Internal error\''); - generated += childDefinitions(fullName, errorsDefinition); - generated += 'module.exports = bitcore.Error;\n'; - return generated; -}; - -var data = require('./spec'); -fs.writeFileSync(__dirname + '/index.js', traverseRoot(data)); diff --git a/lib/errors/index.js b/lib/errors/index.js new file mode 100644 index 0000000..921b2ff --- /dev/null +++ b/lib/errors/index.js @@ -0,0 +1,60 @@ +'use strict'; + +var _ = require('lodash'); + +function format(message, args) { + return message + .replace('{0}', args[0]) + .replace('{1}', args[1]) + .replace('{2}', args[2]); +} +var traverseNode = function(parent, errorDefinition) { + var NodeError = function() { + if (_.isString(errorDefinition.message)) { + this.message = format(errorDefinition.message, arguments); + } else if (_.isFunction(errorDefinition.message)) { + this.message = errorDefinition.message.apply(null, arguments); + } else { + throw new Error('Invalid error definition for ' + errorDefinition.name); + } + this.stack = this.message + '\n' + (new Error()).stack; + }; + NodeError.prototype = Object.create(parent.prototype); + NodeError.prototype.name = parent.prototype.name + errorDefinition.name; + parent[errorDefinition.name] = NodeError; + if (errorDefinition.errors) { + childDefinitions(NodeError, errorDefinition.errors); + } +}; + +/* jshint latedef: false */ +var childDefinitions = function(parent, childDefinitions) { + _.each(childDefinitions, function(childDefinition) { + traverseNode(parent, childDefinition); + }); +}; +/* jshint latedef: true */ + +var traverseRoot = function(parent, errorsDefinition) { + childDefinitions(parent, errorsDefinition); + return parent; +}; + + +var bitcore = {}; +bitcore.Error = function() { + this.message = 'Internal error'; + this.stack = this.message + '\n' + (new Error()).stack; +}; +bitcore.Error.prototype = Object.create(Error.prototype); +bitcore.Error.prototype.name = 'bitcore.Error'; + + +var data = require('./spec'); +traverseRoot(bitcore.Error, data); + +module.exports = bitcore.Error; + +module.exports.extend = function(spec) { + traverseRoot(bitcore.Error, spec); +}; diff --git a/lib/errors/spec.js b/lib/errors/spec.js index 70fbeac..c68150f 100644 --- a/lib/errors/spec.js +++ b/lib/errors/spec.js @@ -1,131 +1,125 @@ 'use strict'; -function format(arg) { - return '\'' + arg - .replace('{0}', '\' + arguments[0] + \'') - .replace('{1}', '\' + arguments[1] + \'') - .replace('{2}', '\' + arguments[2] + \'') + '\''; -} - module.exports = [{ - name: 'InvalidB58Char', - message: format('Invalid Base58 character: {0} in {1}') - }, { - name: 'InvalidB58Checksum', - message: format('Invalid Base58 checksum for {0}') - }, { - name: 'InvalidNetwork', - message: format('Invalid version for network: got {0}') - }, { - name: 'InvalidState', - message: format('Invalid state: {0}') - }, { - name: 'NotImplemented', - message: format('Function {0} was not implemented yet') - }, { - name: 'InvalidNetworkArgument', - message: format('Invalid network: must be "livenet" or "testnet", got {0}') - }, { - name: 'InvalidArgument', - message: format('Invalid Argument' + '\' + (arguments[0] ? \': {0}\' : \'\') + \'') - }, { - name: 'AbstractMethodInvoked', - message: format('Abstract Method Invokation: {0}') - }, { - name: 'InvalidArgumentType', - message: format('Invalid Argument for {2}, expected {1} but got ') + '+ typeof arguments[0]', - }, { - name: 'Unit', - message: format('Internal Error on Unit {0}'), - errors: [{ - 'name': 'UnknownCode', - 'message': format('Unrecognized unit code: {0}') - },{ - 'name': 'InvalidRate', - 'message': format('Invalid exchange rate: {0}') - }] - }, { - name: 'Transaction', - message: format('Internal Error on Transaction {0}'), - errors: [ - { - name: 'Input', - message: format('Internal Error on Input {0}'), - errors: [{ - name: 'MissingScript', - message: format('Need a script to create an input') - }] - }, { - name: 'NeedMoreInfo', - message: format('{0}') - }, { - name: 'UnableToVerifySignature', - message: format('Unable to verify signature: {0}') - }, { - name: 'DustOutputs', - message: format('Dust amount detected in one output') - }, { - name: 'FeeError', - message: format('Fees are not correctly set {0}'), - }, { - name: 'ChangeAddressMissing', - message: format('Change address is missing') - } - ] - }, { - name: 'Script', - message: format('Internal Error on Script {0}'), - errors: [{ - name: 'UnrecognizedAddress', - message: format('Expected argument {0} to be an address') - }] - }, { - name: 'HDPrivateKey', - message: format('Internal Error on HDPrivateKey {0}'), - errors: [{ - name: 'InvalidDerivationArgument', - message: format('Invalid derivation argument {0}, expected string, or number and boolean') - }, { - name: 'InvalidEntropyArgument', - message: format('Invalid entropy: must be an hexa string or binary buffer, got {0}'), - errors: [{ - name: 'TooMuchEntropy', - message: format('Invalid entropy: more than 512 bits is non standard, got "{0}"') - }, { - name: 'NotEnoughEntropy', - message: format('Invalid entropy: at least 128 bits needed, got "{0}"') - }] - }, { - name: 'InvalidLength', - message: format('Invalid length for xprivkey string in {0}') - }, { - name: 'InvalidPath', - message: format('Invalid derivation path: {0}') - }, { - name: 'UnrecognizedArgument', - message: format('Invalid argument: creating a HDPrivateKey requires a string, buffer, json or object, got "{0}"') - }] - }, { - name: 'HDPublicKey', - message: format('Internal Error on HDPublicKey {0}'), - errors: [{ - name: 'ArgumentIsPrivateExtended', - message: format('Argument is an extended private key: {0}') - }, { - name: 'InvalidDerivationArgument', - message: format('Invalid derivation argument: got {0}') - }, { - name: 'InvalidLength', - message: format('Invalid length for xpubkey: got "{0}"') - }, { - name: 'InvalidPath', - message: format('Invalid derivation path, it should look like: "m/1/100", got "{0}"') - }, { - name: 'MustSupplyArgument', - message: format('Must supply an argument to create a HDPublicKey') - }, { - name: 'UnrecognizedArgument', - message: format('Invalid argument for creation, must be string, json, buffer, or object') - }] + name: 'InvalidB58Char', + message: 'Invalid Base58 character: {0} in {1}' +}, { + name: 'InvalidB58Checksum', + message: 'Invalid Base58 checksum for {0}' +}, { + name: 'InvalidNetwork', + message: 'Invalid version for network: got {0}' +}, { + name: 'InvalidState', + message: 'Invalid state: {0}' +}, { + name: 'NotImplemented', + message: 'Function {0} was not implemented yet' +}, { + name: 'InvalidNetworkArgument', + message: 'Invalid network: must be "livenet" or "testnet", got {0}' +}, { + name: 'InvalidArgument', + message: function() { + return 'Invalid Argument' + (arguments[0] ? (': ' + arguments[0]) : ''); } -]; +}, { + name: 'AbstractMethodInvoked', + message: 'Abstract Method Invokation: {0}' +}, { + name: 'InvalidArgumentType', + message: function() { + return 'Invalid Argument for ' + arguments[2] + ', expected ' + arguments[1] + ' but got ' + typeof arguments[0]; + } +}, { + name: 'Unit', + message: 'Internal Error on Unit {0}', + errors: [{ + 'name': 'UnknownCode', + 'message': 'Unrecognized unit code: {0}' + }, { + 'name': 'InvalidRate', + 'message': 'Invalid exchange rate: {0}' + }] +}, { + name: 'Transaction', + message: 'Internal Error on Transaction {0}', + errors: [{ + name: 'Input', + message: 'Internal Error on Input {0}', + errors: [{ + name: 'MissingScript', + message: 'Need a script to create an input' + }] + }, { + name: 'NeedMoreInfo', + message: '{0}' + }, { + name: 'UnableToVerifySignature', + message: 'Unable to verify signature: {0}' + }, { + name: 'DustOutputs', + message: 'Dust amount detected in one output' + }, { + name: 'FeeError', + message: 'Fees are not correctly set {0}', + }, { + name: 'ChangeAddressMissing', + message: 'Change address is missing' + }] +}, { + name: 'Script', + message: 'Internal Error on Script {0}', + errors: [{ + name: 'UnrecognizedAddress', + message: 'Expected argument {0} to be an address' + }] +}, { + name: 'HDPrivateKey', + message: 'Internal Error on HDPrivateKey {0}', + errors: [{ + name: 'InvalidDerivationArgument', + message: 'Invalid derivation argument {0}, expected string, or number and boolean' + }, { + name: 'InvalidEntropyArgument', + message: 'Invalid entropy: must be an hexa string or binary buffer, got {0}', + errors: [{ + name: 'TooMuchEntropy', + message: 'Invalid entropy: more than 512 bits is non standard, got "{0}"' + }, { + name: 'NotEnoughEntropy', + message: 'Invalid entropy: at least 128 bits needed, got "{0}"' + }] + }, { + name: 'InvalidLength', + message: 'Invalid length for xprivkey string in {0}' + }, { + name: 'InvalidPath', + message: 'Invalid derivation path: {0}' + }, { + name: 'UnrecognizedArgument', + message: 'Invalid argument: creating a HDPrivateKey requires a string, buffer, json or object, got "{0}"' + }] +}, { + name: 'HDPublicKey', + message: 'Internal Error on HDPublicKey {0}', + errors: [{ + name: 'ArgumentIsPrivateExtended', + message: 'Argument is an extended private key: {0}' + }, { + name: 'InvalidDerivationArgument', + message: 'Invalid derivation argument: got {0}' + }, { + name: 'InvalidLength', + message: 'Invalid length for xpubkey: got "{0}"' + }, { + name: 'InvalidPath', + message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"' + }, { + name: 'MustSupplyArgument', + message: 'Must supply an argument to create a HDPublicKey' + }, { + name: 'UnrecognizedArgument', + message: 'Invalid argument for creation, must be string, json, buffer, or object' + }] +}]; From 6434d6ca87942f2664695770e836824c3b539387 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 19:01:23 -0300 Subject: [PATCH 36/68] use gulp-bitcore for gulp --- .gitignore | 6 +- bower.json | 2 +- gulpfile.js | 329 +------------------------------------------------- karma.conf.js | 2 +- package.json | 4 +- 5 files changed, 11 insertions(+), 332 deletions(-) diff --git a/.gitignore b/.gitignore index 375322f..9cf6a6a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,8 @@ apiref bower_components report .DS_Store -browser + + +bitcore.js +bitcore.min.js +tests.js diff --git a/bower.json b/bower.json index ac4c444..8ec416b 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "bitcore", - "main": "browser/bitcore.min.js", + "main": "./bitcore.min.js", "version": "0.8.6", "homepage": "http://bitcore.io", "authors": [ diff --git a/gulpfile.js b/gulpfile.js index 012a2b8..53191d2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,330 +1,5 @@ -/** - * @file gulpfile.js - * - * Defines tasks that can be run on gulp. - * - * Summary:
      - *
    • `test` - runs all the tests on node and the browser (mocha and karma) - *
        - *
      • `test:node` - *
      • `test:node:nofail` - internally used for watching (due to bug on gulp-mocha) - *
      • `test:browser` - *
      ` - *
    • `watch:test` - watch for file changes and run tests - *
        - *
      • `watch:test:node` - *
      • `watch:test:browser` - *
      ` - *
    • `browser` - generate files needed for browser (browserify) - *
        - *
      • `browser:uncompressed` - build `browser/bitcore.js` - *
      • `browser:compressed` - build `browser/bitcore.min.js` - *
      • `browser:maketests` - build `browser/tests.js`, needed for testing without karma - *
      ` - *
    • `lint` - run `jshint` - *
    • `coverage` - run `istanbul` with mocha to generate a report of test coverage - *
    • `jsdoc` - run `jsdoc` to generate the API reference - *
    • `coveralls` - updates coveralls info - *
    • `release` - automates release process (only for bitcore maintainers) - *
    - */ -'use strict'; - -var gulp = require('gulp'); - -var bump = require('gulp-bump'); -var coveralls = require('gulp-coveralls'); -var git = require('gulp-git'); -var gutil = require('gulp-util'); -var jsdoc2md = require('jsdoc-to-markdown'); -var jshint = require('gulp-jshint'); -var mfs = require('more-fs'); -var mocha = require('gulp-mocha'); -var rename = require('gulp-rename'); -var runSequence = require('run-sequence'); -var shell = require('gulp-shell'); -var through = require('through2'); -var uglify = require('gulp-uglify'); -var files = ['lib/**/*.js']; -var tests = ['test/**/*.js']; -var alljs = files.concat(tests); +var gulp_bitcore = require('gulp-bitcore'); - -function ignoreError() { - /* jshint ignore:start */ // using `this` in this context is weird - this.emit('end'); - /* jshint ignore:end */ -} - -var testMocha = function() { - return gulp.src(tests).pipe(new mocha({ - reporter: 'spec' - })); -}; - -var testKarma = shell.task([ - './node_modules/karma/bin/karma start' -]); - -/** - * Testing - */ - -gulp.task('test:node', testMocha); - -gulp.task('test:node:nofail', function() { - return testMocha().on('error', ignoreError); -}); - -gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testKarma); - -gulp.task('test', function(callback) { - runSequence(['test:node'], ['test:browser'], callback); -}); - -/** - * File generation - */ - -gulp.task('browser:makefolder', shell.task([ - 'if [ ! -d "browser" ]; then mkdir browser; fi' -])); - -gulp.task('browser:uncompressed', ['browser:makefolder'], shell.task([ - './node_modules/.bin/browserify index.js --insert-global-vars=true --standalone=bitcore -o browser/bitcore.js' -])); - -gulp.task('browser:compressed', ['browser:uncompressed'], function() { - return gulp.src('browser/bitcore.js') - .pipe(uglify({ - mangle: true, - compress: true - })) - .pipe(rename('bitcore.min.js')) - .pipe(gulp.dest('browser')) - .on('error', gutil.log); -}); - -gulp.task('browser:maketests', ['browser:makefolder'], shell.task([ - 'find test/ -type f -name "*.js" | xargs ./node_modules/.bin/browserify -t brfs -o browser/tests.js' -])); - -gulp.task('browser', function(callback) { - runSequence(['browser:compressed'], ['browser:maketests'], callback); -}); - -/** - * Code quality and documentation - */ - -gulp.task('lint', function() { - return gulp.src(alljs) - .pipe(jshint()) - .pipe(jshint.reporter('default')); -}); - -gulp.task('plato', shell.task(['plato -d report -r -l .jshintrc -t bitcore lib'])); - -gulp.task('jsdoc', function() { - - function jsdoc() { - return through.obj(function(file, enc, cb) { - - if (file.isNull()) { - cb(null, file); - return; - } - if (file.isStream()) { - cb(new gutil.PluginError('gulp-jsdoc2md', 'Streaming not supported')); - return; - } - var destination = 'docs/api/' + file.path.replace(file.base, '').replace(/\.js$/, '.md'); - jsdoc2md.render(file.path, {}) - .on('error', function(err) { - gutil.log(gutil.colors.red('jsdoc2md failed', err.message)); - }) - .pipe(mfs.writeStream(destination)); - cb(null, file); - }); - } - - return gulp.src(files).pipe(jsdoc()); - -}); - -gulp.task('coverage', shell.task(['node_modules/.bin/./istanbul cover node_modules/.bin/_mocha -- --recursive'])); - -gulp.task('coveralls', ['coverage'], function() { - gulp.src('coverage/lcov.info').pipe(coveralls()); -}); - -/** - * Watch tasks - */ - -gulp.task('watch:test', function() { - // TODO: Only run tests that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['test']); -}); - -gulp.task('watch:test:node', function() { - // TODO: Only run tests that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['test:node']); -}); - -gulp.task('watch:test:browser', function() { - // TODO: Only run tests that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['test:browser']); -}); - -gulp.task('watch:jsdoc', function() { - // TODO: Only run tests that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['jsdoc']); -}); - -gulp.task('watch:coverage', function() { - // TODO: Only run tests that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['coverage']); -}); - -gulp.task('watch:lint', function() { - // TODO: Only lint files that are linked to file changes by doing - // something smart like reading through the require statements - return gulp.watch(alljs, ['lint']); -}); - -gulp.task('watch:browser', function() { - return gulp.watch(alljs, ['browser']); -}); - -/** - * Release automation - */ - -gulp.task('release:install', function() { - return shell.task([ - 'npm install', - ]); -}); - -gulp.task('release:bump', function() { - return gulp.src(['./bower.json', './package.json']) - .pipe(bump({ - type: 'patch' - })) - .pipe(gulp.dest('./')); -}); - -gulp.task('release:checkout-releases', function(cb) { - git.checkout('releases', { - args: '' - }, cb); -}); - -gulp.task('release:merge-master', function(cb) { - git.merge('master', { - args: '' - }, cb); -}); - -gulp.task('release:checkout-master', function(cb) { - git.checkout('master', { - args: '' - }, cb); -}); - -gulp.task('release:add-built-files', function() { - return gulp.src(['./browser/bitcore.js', './browser/bitcore.min.js', './package.json', './bower.json']) - .pipe(git.add({ - args: '-f' - })); -}); - -gulp.task('release:build-commit', ['release:add-built-files'], function() { - var pjson = require('./package.json'); - return gulp.src(['./browser/bitcore.js', './browser/bitcore.min.js', './package.json', './bower.json']) - .pipe(git.commit('Build: ' + pjson.version, { - args: '' - })); -}); - -gulp.task('release:version-commit', function() { - var pjson = require('./package.json'); - var files = ['./package.json', './bower.json']; - return gulp.src(files) - .pipe(git.commit('Bump package version to ' + pjson.version, { - args: '' - })); -}); - -gulp.task('release:push-releases', function(cb) { - git.push('bitpay', 'releases', { - args: '' - }, cb); -}); - -gulp.task('release:push', function(cb) { - git.push('bitpay', 'master', { - args: '' - }, cb); -}); - -gulp.task('release:push-tag', function(cb) { - var pjson = require('./package.json'); - var name = 'v' + pjson.version; - git.tag(name, 'Release ' + name, function() { - git.push('bitpay', name, cb); - }); -}); - -gulp.task('release:publish', shell.task([ - 'npm publish' -])); - -// requires https://hub.github.com/ -gulp.task('release', function(cb) { - runSequence( - // Checkout the `releases` branch - ['release:checkout-releases'], - // Merge the master branch - ['release:merge-master'], - // Run npm install - ['release:install'], - // Build browser bundle - ['browser:compressed'], - // Run tests with gulp test - ['test'], - // Update package.json and bower.json - ['release:bump'], - // Commit - ['release:build-commit'], - // Run git push bitpay $VERSION - ['release:push-tag'], - // Push to releases branch - ['release:push-releases'], - // Run npm publish - ['release:publish'], - // Checkout the `master` branch - ['release:checkout-master'], - // Bump package.json and bower.json, again - ['release:bump'], - // Version commit with no binary files to master - ['release:version-commit'], - // Push to master - ['release:push'], - cb); -}); - - -/* Default task */ -gulp.task('default', function(callback) { - return runSequence(['lint', 'jsdoc'], ['browser:uncompressed', 'test'], ['coverage', 'browser:compressed'], - callback); -}); +gulp_bitcore(); diff --git a/karma.conf.js b/karma.conf.js index acc9eac..dc5d597 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -23,7 +23,7 @@ module.exports = function(config) { }, singleRun: true, files: [ - 'browser/tests.js' + 'tests.js' ], plugins: [ 'karma-mocha', diff --git a/package.json b/package.json index 60baac5..7a451cc 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "lint": "gulp lint", "test": "gulp test", "coverage": "gulp coverage", - "build": "gulp", - "postinstall": "node ./lib/errors/build.js" + "build": "gulp" }, "contributors": [ { @@ -92,6 +91,7 @@ "chai": "~1.10.0", "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", "gulp": "^3.8.10", + "gulp-bitcore": "git://github.com/maraoz/gulp-bitcore.git", "gulp-bump": "^0.1.11", "gulp-closure-compiler": "^0.2.9", "gulp-coveralls": "^0.1.3", From c53e00f3076292397ecd3acfe4af392f6b0eda35 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 19:04:43 -0300 Subject: [PATCH 37/68] revert dep change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a451cc..deb8048 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "chai": "~1.10.0", "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", "gulp": "^3.8.10", - "gulp-bitcore": "git://github.com/maraoz/gulp-bitcore.git", + "gulp-bitcore": "^0.2.2", "gulp-bump": "^0.1.11", "gulp-closure-compiler": "^0.2.9", "gulp-coveralls": "^0.1.3", From 4fba778a2ab2b863e352de16399d282423035e54 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 19:19:59 -0300 Subject: [PATCH 38/68] remove gulp submodules --- package.json | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/package.json b/package.json index deb8048..fbaa1ee 100644 --- a/package.json +++ b/package.json @@ -92,16 +92,6 @@ "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", "gulp": "^3.8.10", "gulp-bitcore": "^0.2.2", - "gulp-bump": "^0.1.11", - "gulp-closure-compiler": "^0.2.9", - "gulp-coveralls": "^0.1.3", - "gulp-git": "^0.5.5", - "gulp-jshint": "^1.9.0", - "gulp-mocha": "^2.0.0", - "gulp-rename": "^1.2.0", - "gulp-shell": "^0.2.10", - "gulp-uglify": "^1.0.2", - "gulp-util": "=3.0.1", "istanbul": "^0.3.5", "jsdoc": "^3.3.0-alpha11", "jsdoc-to-markdown": "=0.5.9", From 1e27d533188a6a7139b3334ca09d3d3ea99c7e2d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 19:47:09 -0300 Subject: [PATCH 39/68] use gulp-bitcore 0.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbaa1ee..f37733b 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "chai": "~1.10.0", "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", "gulp": "^3.8.10", - "gulp-bitcore": "^0.2.2", + "gulp-bitcore": "^0.3.0", "istanbul": "^0.3.5", "jsdoc": "^3.3.0-alpha11", "jsdoc-to-markdown": "=0.5.9", From f2eeb7664e70b7c162a3b4852d4c1310bcaba248 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 20:11:40 -0300 Subject: [PATCH 40/68] fix extend --- lib/errors/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/errors/index.js b/lib/errors/index.js index 921b2ff..425e995 100644 --- a/lib/errors/index.js +++ b/lib/errors/index.js @@ -56,5 +56,6 @@ traverseRoot(bitcore.Error, data); module.exports = bitcore.Error; module.exports.extend = function(spec) { - traverseRoot(bitcore.Error, spec); + traverseNode(bitcore.Error, spec); + return bitcore.Error; }; From b37a8d2f326db17768406175773605433e4c15e6 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 13 Jan 2015 20:18:28 -0300 Subject: [PATCH 41/68] new version of extend --- lib/errors/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/errors/index.js b/lib/errors/index.js index 425e995..de6f731 100644 --- a/lib/errors/index.js +++ b/lib/errors/index.js @@ -25,6 +25,7 @@ var traverseNode = function(parent, errorDefinition) { if (errorDefinition.errors) { childDefinitions(NodeError, errorDefinition.errors); } + return NodeError; }; /* jshint latedef: false */ @@ -56,6 +57,5 @@ traverseRoot(bitcore.Error, data); module.exports = bitcore.Error; module.exports.extend = function(spec) { - traverseNode(bitcore.Error, spec); - return bitcore.Error; + return traverseNode(bitcore.Error, spec); }; From 6923b9bed970f93866a2a383ac100626d6b60900 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Wed, 14 Jan 2015 11:43:57 -0300 Subject: [PATCH 42/68] Drop explorers --- docs/guide/insight.md | 36 --------- lib/transport/explorers/index.js | 3 - lib/transport/explorers/insight.js | 115 ----------------------------- lib/transport/index.js | 6 -- 4 files changed, 160 deletions(-) delete mode 100644 docs/guide/insight.md delete mode 100644 lib/transport/explorers/index.js delete mode 100644 lib/transport/explorers/insight.js delete mode 100644 lib/transport/index.js diff --git a/docs/guide/insight.md b/docs/guide/insight.md deleted file mode 100644 index 9892846..0000000 --- a/docs/guide/insight.md +++ /dev/null @@ -1,36 +0,0 @@ -title: Insight Explorer -description: Provides an interface to fetch information about the state of the blockchain from a trusted Insight server. ---- -# Insight - -## Description - -`bitcore.transport.explorers.Insight` is a simple agent to perform queries to an Insight blockchain explorer. The default servers are `https://insight.bitpay.com` and `https://test-insight.bitpay.com`, hosted by BitPay Inc. You can (and we strongly suggest you do) run your own insight server. For more information, head to https://github.com/bitpay/insight-api - -There are currently two methods implemented (the API will grow as features are requested): `getUnspentUtxos` and `broadcast`. - -### Retrieving Unspent UTXOs for an Address (or set of) - -```javascript -var insight = new Insight(); -insight.getUnspentUtxos('1Bitcoin...', function(err, utxos) { - if (err) { - // Handle errors... - } else { - // Maybe use the UTXOs to create a transaction - } -}); -``` - -### Broadcasting a Transaction - -```javascript -var insight = new Insight(); -insight.broadcast(tx, function(err, returnedTxId) { - if (err) { - // Handle errors... - } else { - // Mark the transaction as broadcasted - } -}); -``` diff --git a/lib/transport/explorers/index.js b/lib/transport/explorers/index.js deleted file mode 100644 index 2483955..0000000 --- a/lib/transport/explorers/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - Insight: require('./insight') -}; diff --git a/lib/transport/explorers/insight.js b/lib/transport/explorers/insight.js deleted file mode 100644 index 71a41c5..0000000 --- a/lib/transport/explorers/insight.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; - -var $ = require('../../util/preconditions'); -var _ = require('lodash'); - -var Address = require('../../address'); -var JSUtil = require('../../util/js'); -var Networks = require('../../networks'); -var Transaction = require('../../transaction'); -var UnspentOutput = Transaction.UnspentOutput; - -var request = require('request'); - -/** - * Allows the retrieval of information regarding the state of the blockchain - * (and broadcasting of transactions) from/to a trusted Insight server. - * @param {string=} url the url of the Insight server - * @param {Network=} network whether to use livenet or testnet - * @constructor - */ -function Insight(url, network) { - if (!url && !network) { - return new Insight(Networks.defaultNetwork); - } - if (Networks.get(url)) { - network = Networks.get(url); - if (network === Networks.livenet) { - url = 'https://insight.bitpay.com'; - } else { - url = 'https://test-insight.bitpay.com'; - } - } - JSUtil.defineImmutable(this, { - url: url, - network: Networks.get(network) || Networks.defaultNetwork - }); - return this; -} - -/** - * @callback Insight.GetUnspentUtxosCallback - * @param {Error} err - * @param {Array.UnspentOutput} utxos - */ - -/** - * Retrieve a list of unspent outputs associated with an address or set of addresses - * @param {Address|string|Array.Address|Array.string} addresses - * @param {GetUnspentUtxosCallback} callback - */ -Insight.prototype.getUnspentUtxos = function(addresses, callback) { - $.checkArgument(_.isFunction(callback)); - if (!_.isArray(addresses)) { - addresses = [addresses]; - } - addresses = _.map(addresses, function(address) { return new Address(address); }); - - this.requestPost('/api/addrs/utxo', { - addrs: _.map(addresses, function(address) { return address.toString(); }).join(',') - }, function(err, res, unspent) { - if (err || res.statusCode !== 200) { - return callback(err || res); - } - unspent = _.map(unspent, UnspentOutput); - - return callback(null, unspent); - }); -}; - -/** - * @callback Insight.BroadcastCallback - * @param {Error} err - * @param {string} txid - */ - -/** - * Broadcast a transaction to the bitcoin network - * @param {transaction|string} transaction - * @param {BroadcastCallback} callback - */ -Insight.prototype.broadcast = function(transaction, callback) { - $.checkArgument(JSUtil.isHexa(transaction) || transaction instanceof Transaction); - $.checkArgument(_.isFunction(callback)); - if (transaction instanceof Transaction) { - transaction = transaction.serialize(); - } - - this.requestPost('/api/tx/send', { - rawtx: transaction - }, function(err, res, body) { - if (err || res.statusCode !== 200) { - return callback(err || body); - } - return callback(null, body ? body.txid : null); - }); -}; - -/** - * Internal function to make a post request to the server - * @param {string} path - * @param {?} data - * @param {function} callback - * @private - */ -Insight.prototype.requestPost = function(path, data, callback) { - $.checkArgument(_.isString(path)); - $.checkArgument(_.isFunction(callback)); - request({ - method: 'POST', - url: this.url + path, - json: data - }, callback); -}; - -module.exports = Insight; diff --git a/lib/transport/index.js b/lib/transport/index.js deleted file mode 100644 index 6e49efa..0000000 --- a/lib/transport/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @namespace Transport - */ -module.exports = { - explorers: require('./explorers') -}; From 94969e3e99aad7c218f4dbf86f1a99f022feb385 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Wed, 14 Jan 2015 11:45:18 -0300 Subject: [PATCH 43/68] Drop tests for explorer --- test/transport/explorers/insight.js | 108 ---------------------------- 1 file changed, 108 deletions(-) delete mode 100644 test/transport/explorers/insight.js diff --git a/test/transport/explorers/insight.js b/test/transport/explorers/insight.js deleted file mode 100644 index 433370a..0000000 --- a/test/transport/explorers/insight.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; - -var sinon = require('sinon'); -var should = require('chai').should(); -var expect = require('chai').expect; -var bitcore = require('../../..'); - -var Insight = bitcore.transport.explorers.Insight; -var Address = bitcore.Address; -var Transaction = bitcore.Transaction; -var Networks = bitcore.Networks; - -describe('Insight', function() { - - describe('instantiation', function() { - it('can be created without any parameters', function() { - var insight = new Insight(); - should.exist(insight.url); - should.exist(insight.network); - if (insight.network === Networks.livenet) { - insight.url.should.equal('https://insight.bitpay.com'); - } else if (insight.network === Networks.testnet) { - insight.url.should.equal('https://test-insight.bitpay.com'); - } - }); - it('can be created providing just a network', function() { - var insight = new Insight(Networks.testnet); - insight.url.should.equal('https://test-insight.bitpay.com'); - insight.network.should.equal(Networks.testnet); - }); - it('can be created with a custom url', function() { - var url = 'https://localhost:1234'; - var insight = new Insight(url); - insight.url.should.equal(url); - }); - it('can be created with a custom url and network', function() { - var url = 'https://localhost:1234'; - var insight = new Insight(url, Networks.testnet); - insight.url.should.equal(url); - insight.network.should.equal(Networks.testnet); - }); - it('defaults to defaultNetwork on a custom url', function() { - var insight = new Insight('https://localhost:1234'); - insight.network.should.equal(Networks.defaultNetwork); - }); - }); - - describe('getting unspent utxos', function() { - var insight = new Insight(); - var address = '371mZyMp4t6uVtcEr4DAAbTZyby9Lvia72'; - beforeEach(function() { - insight.requestPost = sinon.stub(); - insight.requestPost.onFirstCall().callsArgWith(2, null, {statusCode: 200}); - }); - it('can receive an address', function(callback) { - insight.getUnspentUtxos(new Address(address), callback); - }); - it('can receive a address as a string', function(callback) { - insight.getUnspentUtxos(address, callback); - }); - it('can receive an array of addresses', function(callback) { - insight.getUnspentUtxos([address, new Address(address)], callback); - }); - it('errors if server is not available', function(callback) { - insight.requestPost.onFirstCall().callsArgWith(2, 'Unable to connect'); - insight.getUnspentUtxos(address, function(error) { - expect(error).to.equal('Unable to connect'); - callback(); - }); - }); - it('errors if server returns errorcode', function(callback) { - insight.requestPost.onFirstCall().callsArgWith(2, null, {statusCode: 400}); - insight.getUnspentUtxos(address, function(error) { - expect(error).to.deep.equal({statusCode: 400}); - callback(); - }); - }); - }); - - describe('broadcasting a transaction', function() { - var insight = new Insight(); - var tx = require('../../data/tx_creation.json')[0][7]; - beforeEach(function() { - insight.requestPost = sinon.stub(); - insight.requestPost.onFirstCall().callsArgWith(2, null, {statusCode: 200}); - }); - it('accepts a raw transaction', function(callback) { - insight.broadcast(tx, callback); - }); - it('accepts a transaction model', function(callback) { - insight.broadcast(new Transaction(tx), callback); - }); - it('errors if server is not available', function(callback) { - insight.requestPost.onFirstCall().callsArgWith(2, 'Unable to connect'); - insight.broadcast(tx, function(error) { - expect(error).to.equal('Unable to connect'); - callback(); - }); - }); - it('errors if server returns errorcode', function(callback) { - insight.requestPost.onFirstCall().callsArgWith(2, null, {statusCode: 400}, 'error'); - insight.broadcast(tx, function(error) { - expect(error).to.equal('error'); - callback(); - }); - }); - }); -}); From 258c33a3b3d7014f01b0c53e743e079e04e19905 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Wed, 14 Jan 2015 11:47:31 -0300 Subject: [PATCH 44/68] Drop unused dependencies --- package.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index 654ed2b..09e7818 100644 --- a/package.json +++ b/package.json @@ -73,15 +73,12 @@ }, "dependencies": { "bn.js": "=0.16.1", - "browser-request": "^0.3.3", "bs58": "=2.0.0", "elliptic": "=0.16.0", "hash.js": "=0.3.2", "inherits": "=2.0.1", "lodash": "=2.4.1", - "request": "^2.51.0", - "sha512": "=0.0.1", - "socks5-client": "^0.3.6" + "sha512": "=0.0.1" }, "devDependencies": { "brfs": "1.2.0", From 94b20e66d2bc482cb181eab27b91c753847217c2 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Wed, 14 Jan 2015 11:49:00 -0300 Subject: [PATCH 45/68] Drop transport require --- index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/index.js b/index.js index 9d514f3..a31b588 100644 --- a/index.js +++ b/index.js @@ -49,9 +49,6 @@ bitcore.deps.bs58 = require('bs58'); bitcore.deps.Buffer = Buffer; bitcore.deps.elliptic = require('elliptic'); -// transport -bitcore.transport = require('./lib/transport'); - // Internal usage, exposed for testing/advanced tweaking bitcore._HDKeyCache = require('./lib/hdkeycache'); From f935bb1ba3ef01c77371be31e2917811242e576c Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Wed, 14 Jan 2015 16:26:28 -0300 Subject: [PATCH 46/68] Drop dependencies from npm-shrinkwrap --- npm-shrinkwrap.json | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index becad21..a74eb85 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,41 +2,16 @@ "name": "bitcore", "version": "0.8.5", "dependencies": { - "aes": { - "version": "0.1.0", - "from": "aes@=0.1.0", - "resolved": "https://registry.npmjs.org/aes/-/aes-0.1.0.tgz" - }, - "asn1.js": { - "version": "0.4.1", - "from": "aes@=0.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-0.4.1.tgz" - }, "bn.js": { "version": "0.16.1", "from": "bn.js@0.16.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.1.tgz" }, - "browser-request": { - "version": "0.3.3", - "from": "browser-request@*", - "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz" - }, "bs58": { "version": "2.0.0", "from": "bs58@2.0.0", "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz" }, - "bufferput": { - "version": "0.1.2", - "from": "bufferput@0.1.2", - "resolved": "https://registry.npmjs.org/bufferput/-/bufferput-0.1.2.tgz" - }, - "buffers": { - "version": "0.1.1", - "from": "buffers@0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" - }, "elliptic": { "version": "0.16.0", "from": "elliptic@0.16.0", @@ -84,30 +59,10 @@ "from": "lodash@=2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, - "jsrsasign": { - "version": "0.0.3", - "from": "jsrsasign@0.0.3", - "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-0.0.3.tgz" - }, - "protobufjs": { - "version": "3.0.0", - "from": "protobufjs@3.0.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-3.0.0.tgz" - }, - "request": { - "version": "2.51.0", - "from": "request@*", - "resolved": "https://registry.npmjs.org/request/-/request-2.51.0.tgz" - }, "sha512": { "version": "0.0.1", "from": "sha512@=0.0.1", "resolved": "https://registry.npmjs.org/sha512/-/sha512-0.0.1.tgz" - }, - "socks5-client": { - "version": "0.3.6", - "from": "socks5-client@0.3.6", - "resolved": "https://registry.npmjs.org/socks5-client/-/socks5-client-0.3.6.tgz" } } } From 067a8d5690e816797168d5637cc1ff8c99d3a3f6 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 14 Jan 2015 16:40:09 -0300 Subject: [PATCH 47/68] remove saucelabs keys --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index f928bdf..85c1de6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,3 @@ install: - npm install after_script: - gulp coveralls -env: - global: - - SAUCE_USERNAME=maraoz - - SAUCE_ACCESS_KEY=30055bf8-2def-4e6a-8edd-4adb9fd1de66 From 42e2c6c5250ff7cd036f5dad1d6879d155d9b89c Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 15 Jan 2015 18:17:15 -0300 Subject: [PATCH 48/68] Implement I5 on URI --- lib/uri.js | 4 ++++ test/uri.js | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/uri.js b/lib/uri.js index 06aa702..13c8cfd 100644 --- a/lib/uri.js +++ b/lib/uri.js @@ -34,6 +34,10 @@ var JSUtil = require('./util/js'); * @constructor */ var URI = function(data, knownParams) { + if (!(this instanceof URI)) { + return new URI(data, knownParams); + } + this.extras = {}; this.knownParams = knownParams || []; this.address = this.network = this.amount = this.message = null; diff --git a/test/uri.js b/test/uri.js index c52aa5e..abbe002 100644 --- a/test/uri.js +++ b/test/uri.js @@ -68,6 +68,11 @@ describe('URI', function() { }).should.throw(TypeError); }); + it('do not need new keyword', function() { + var uri = URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj'); + uri.should.be.instanceof(URI); + }); + describe('instantiation from bitcoin uri', function() { /* jshint maxstatements: 25 */ var uri; From 81509debbd038e2967426f8e89fc9d542a812fe0 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 11:59:22 -0500 Subject: [PATCH 49/68] Fix package.json by replacing gulp-bitcore with bitcore-build --- gulpfile.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 53191d2..a22eb1c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,5 @@ -var gulp_bitcore = require('gulp-bitcore'); +var bitcoreTasks = require('bitcore-build'); -gulp_bitcore(); +bitcoreTasks(); diff --git a/package.json b/package.json index 09e7818..d1e3a80 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "chai": "~1.10.0", "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", "gulp": "^3.8.10", - "gulp-bitcore": "^0.3.0", + "bitcore-build": "^0.4.1", "istanbul": "^0.3.5", "jsdoc": "^3.3.0-alpha11", "jsdoc-to-markdown": "=0.5.9", From 4997c2df4399727aa6694a98e4f875c8c789484a Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 13:17:12 -0500 Subject: [PATCH 50/68] Removed karma from devDependencies since it's defined in bitcore-build --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index d1e3a80..42c4997 100644 --- a/package.json +++ b/package.json @@ -90,11 +90,6 @@ "istanbul": "^0.3.5", "jsdoc": "^3.3.0-alpha11", "jsdoc-to-markdown": "=0.5.9", - "karma": "^0.12.28", - "karma-chrome-launcher": "^0.1.7", - "karma-detect-browsers": "^0.1.3", - "karma-firefox-launcher": "^0.1.3", - "karma-mocha": "^0.1.9", "mocha": "~2.0.1", "more-fs": "=0.5.0", "plato": "^1.3.0", From bfc7edf5f5390575f9635e9f6fd9105c518bb6b9 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 11:30:09 -0500 Subject: [PATCH 51/68] Docs: Update browser build documentation to reflect the current module development strategy. --- docs/guide/browser.md | 46 +++++++++++-------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/docs/guide/browser.md b/docs/guide/browser.md index 56f04be..59d9d50 100644 --- a/docs/guide/browser.md +++ b/docs/guide/browser.md @@ -4,61 +4,39 @@ description: Guide to writing modules and optimizing browser bundles. # Browser Builds -When developing a module that will need to work in a browser and does not use the entire Bitcore namespace, it's recommended to narrow the scope of the requires to the particular modules that are needed. It will produce a smaller browser bundle as it will only include the JavaScript that is nessessary. Below is a quick tutorial that will use three modules. +When developing a module that will depend on Bitcore, it's recommended to exclude Bitcore in the distributed browser bundle when using browserify and to use the `--external bitcore` parameter. It will produce a smaller browser bundle, as it will only include the JavaScript that is nessessary, and will depend on the Bitcore browser build which is better for distribution. ## Tutorial -**Step 1**: Require Bitcore Modules +**Step 1**: Require Bitcore -Here we require specific Bitcore modules that will be used in a `index.js` file: +Here we require Bitcore and define the namespace (`index.js`): ```javascript -var PrivateKey = require('bitcore/lib/privatekey'); -var PublicKey = require('bitcore/lib/publickey'); -var Address = require('bitcore/lib/address'); - -// the rest of the module here +var bitcore = require('bitcore'); +var PrivateKey = bitcore.PrivateKey; +var PublicKey = bitcore.PublicKey; +var Address = bitcore.Address; ``` +See the [main file](https://github.com/bitpay/bitcore/blob/master/index.js) for bitcore for a complete list, as well as the [Bitcore Documentation](index.md). + **Step 2**: Browserifying Next we will generate a browser bundle using [browserify](https://www.npmjs.com/package/browserify) by running the command: ```bash -browserify index.js -o index.browser.js +browserify index.js:module-name --external bitcore -o module-name.js ``` -This will output a file `index.browser.js` at around 700KB *(the entire Bitcore namespace is around 2MB)*. +This will output a file `module-name.js` with only the code loaded from `index.js` (bitcore.js will need to be loaded beforehand, which is around 145KB gzipped) **Step 3**: Uglifying This can be further optimized by using [uglifyjs](https://www.npmjs.com/package/uglify-js), and running the command: ```bash -uglifyjs index.browser.js --compress --mangle -o index.browser.min.js +uglifyjs module-name.js --compress --mangle -o module-name.min.js ``` - -The resulting file `index.browser.min.js` in this case should be less than 300KB. - -## Modules - -Here is a list of some of the common modules: - -```javascript -var Address = require('bitcore/lib/address'); -var Block = require('bitcore/lib/block'); -var BlockHeader = require('bitcore/lib/blockheader'); -var HDPrivateKey = require('bitcore/lib/hdprivatekey'); -var HDPublicKey = require('bitcore/lib/hdpublickey'); -var PaymentProtocol = require('bitcore/lib/paymentprotocol'); -var PrivateKey = require('bitcore/lib/privatekey'); -var PublicKey = require('bitcore/lib/publickey'); -var Script = require('bitcore/lib/script'); -var Transaction = require('bitcore/lib/transaction'); -var URI = require('bitcore/lib/uri'); -var Unit = require('bitcore/lib/unit'); -``` - -For more informatation about each of the modules please see the [Bitcore Documentation](index.md). \ No newline at end of file From b6ba5dbc5a17502e5120c26279025d00160e55bf Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 9 Jan 2015 16:50:24 -0500 Subject: [PATCH 52/68] Added test data for blocks from bitcoin core. --- test/block.js | 9 +++++++++ test/data/bitcoind/blocks.json | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/data/bitcoind/blocks.json diff --git a/test/block.js b/test/block.js index 0ed37ca..8df1360 100644 --- a/test/block.js +++ b/test/block.js @@ -1,5 +1,6 @@ 'use strict'; +var assert = require('assert'); var bitcore = require('..'); var BN = require('../lib/crypto/bn'); var BufferReader = bitcore.encoding.BufferReader; @@ -17,6 +18,7 @@ var dataRawBlockBuffer = fs.readFileSync('test/data/blk86756-testnet.dat'); var dataRawBlockBinary = fs.readFileSync('test/data/blk86756-testnet.dat', 'binary'); var dataJson = fs.readFileSync('test/data/blk86756-testnet.json').toString(); var data = require('./data/blk86756-testnet'); +var dataBlocks = require('./data/bitcoind/blocks'); describe('Block', function() { @@ -64,6 +66,13 @@ describe('Block', function() { should.exist(b.txs); }); + it('should properly deserialize blocks', function() { + dataBlocks.forEach(function(block){ + var b = Block.fromBuffer(new Buffer(block.data, 'hex')); + b.txs.length.should.equal(block.transactions); + }); + }); + }); describe('#fromRawBlock', function() { diff --git a/test/data/bitcoind/blocks.json b/test/data/bitcoind/blocks.json new file mode 100644 index 0000000..8f7ceb8 --- /dev/null +++ b/test/data/bitcoind/blocks.json @@ -0,0 +1,27 @@ +[ + { + "comment": "A random real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) with 9 transactions", + "transactions": 9, + "data": "0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000" + }, + { + "comment": "Random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6) with 4 transactions", + "transactions": 4, + "data": "0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000" + }, + { + "comment": "A random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6) with 4 transactions", + "transactions": 4, + "data": "0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000" + }, + { + "comment": "A random real block (000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45) with one tx", + "transactions": 1, + "data": "0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020a02ffffffff0100f2052a01000000434104ecd3229b0571c3be876feaac0442a9f13c5a572742927af1dc623353ecf8c202225f64868137a18cdd85cbbb4c74fbccfd4f49639cf1bdc94a5672bb15ad5d4cac00000000" + }, + { + "comment": "A random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4) with 7 transactions", + "transactions": 7, + "data": "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000" + } +] From b41665522287caa066012243128dba5e4932a33e Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 16 Jan 2015 16:54:32 -0300 Subject: [PATCH 53/68] block serialization: Add option skip magic numbers --- lib/block.js | 68 +++++++++++++++++---------------- lib/blockheader.js | 15 ++++---- test/block.js | 28 ++++++-------- test/data/blk86756-testnet.json | 3 +- 4 files changed, 54 insertions(+), 60 deletions(-) diff --git a/lib/block.js b/lib/block.js index e69fd8a..015d2b0 100644 --- a/lib/block.js +++ b/lib/block.js @@ -59,12 +59,11 @@ Block._from = function _from(arg) { * @type {BlockHeader} */ header: arg.header, - txsvi: arg.txsvi, /** - * @name Block#txs + * @name Block#transactions * @type {Transaction[]} */ - txs: arg.txs + transactions: arg.transactions }; } else { throw new TypeError('Unrecognized argument for Block'); @@ -81,16 +80,15 @@ Block._fromJSON = function _fromJSON(data) { if (JSUtil.isValidJSON(data)) { data = JSON.parse(data); } - var txs = []; - data.txs.forEach(function(tx) { - txs.push(Transaction().fromJSON(tx)); + var transactions = []; + data.transactions.forEach(function(data) { + transactions.push(Transaction().fromJSON(data)); }); var info = { magicnum: data.magicnum, size: data.size, header: BlockHeader.fromJSON(data.header), - txsvi: Varint().fromString(data.txsvi), - txs: txs + transactions: transactions }; return info; }; @@ -109,16 +107,22 @@ Block.fromJSON = function fromJSON(json) { * @returns {Object} - An object representing the block data * @private */ -Block._fromBufferReader = function _fromBufferReader(br) { +Block._fromBufferReader = function _fromBufferReader(br, options) { + options = options || {}; var info = {}; - info.magicnum = br.readUInt32LE(); - info.size = br.readUInt32LE(); + if (!options.skipMagic) { + info.magicnum = br.readUInt32LE(); + info.size = br.readUInt32LE(); + } info.header = BlockHeader.fromBufferReader(br); - info.txsvi = Varint(br.readVarintBuf()); - var txslen = info.txsvi.toNumber(); - info.txs = []; - for (var i = 0; i < txslen; i++) { - info.txs.push(Transaction().fromBufferReader(br)); + if (options.skipMagic) { + info.magicnum = 0; + info.size = info.header.bits; + } + var transactions = br.readVarintNum(); + info.transactions = []; + for (var i = 0; i < transactions; i++) { + info.transactions.push(Transaction().fromBufferReader(br)); } return info; }; @@ -127,8 +131,8 @@ Block._fromBufferReader = function _fromBufferReader(br) { * @param {BufferReader} - A buffer reader of the block * @returns {Block} - An instance of block */ -Block.fromBufferReader = function fromBufferReader(br) { - var info = Block._fromBufferReader(br); +Block.fromBufferReader = function fromBufferReader(br, opts) { + var info = Block._fromBufferReader(br, opts); return new Block(info); }; @@ -136,8 +140,8 @@ Block.fromBufferReader = function fromBufferReader(br) { * @param {Buffer} - A buffer of the block * @returns {Block} - An instance of block */ -Block.fromBuffer = function fromBuffer(buf) { - return Block.fromBufferReader(BufferReader(buf)); +Block.fromBuffer = function fromBuffer(buf, opts) { + return Block.fromBufferReader(BufferReader(buf), opts); }; /** @@ -166,16 +170,15 @@ Block.fromRawBlock = function fromRawBlock(data) { * @returns {Object} - A plain object with the block properties */ Block.prototype.toObject = function toObject() { - var txs = []; - this.txs.forEach(function(tx) { - txs.push(tx.toObject()); + var transactions = []; + this.transactions.forEach(function(tx) { + transactions.push(tx.toObject()); }); return { magicnum: this.magicnum, size: this.size, header: this.header.toObject(), - txsvi: this.txsvi.toString(), - txs: txs + transactions: transactions }; }; @@ -211,10 +214,9 @@ Block.prototype.toBufferWriter = function toBufferWriter(bw) { bw.writeUInt32LE(this.magicnum); bw.writeUInt32LE(this.size); bw.write(this.header.toBuffer()); - bw.write(this.txsvi.buf); - var txslen = this.txsvi.toNumber(); - for (var i = 0; i < txslen; i++) { - this.txs[i].toBufferWriter(bw); + bw.writeVarintNum(this.transactions.length); + for (var i = 0; i < this.transactions.length; i++) { + this.transactions[i].toBufferWriter(bw); } return bw; }; @@ -225,11 +227,11 @@ Block.prototype.toBufferWriter = function toBufferWriter(bw) { */ Block.prototype.getTransactionHashes = function getTransactionHashes() { var hashes = []; - if (this.txs.length === 0) { + if (this.transactions.length === 0) { return [Block.Values.NULL_HASH]; } - for (var t = 0; t < this.txs.length; t++) { - hashes.push(this.txs[t]._getHash()); + for (var t = 0; t < this.transactions.length; t++) { + hashes.push(this.transactions[t]._getHash()); } return hashes; }; @@ -245,7 +247,7 @@ Block.prototype.getMerkleTree = function getMerkleTree() { var tree = this.getTransactionHashes(); var j = 0; - for (var size = this.txs.length; size > 1; size = Math.floor((size + 1) / 2)) { + for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) { for (var i = 0; i < size; i += 2) { var i2 = Math.min(i + 1, size - 1); var buf = Buffer.concat([tree[j + i], tree[j + i2]]); diff --git a/lib/blockheader.js b/lib/blockheader.js index 80ad727..7c18c1b 100644 --- a/lib/blockheader.js +++ b/lib/blockheader.js @@ -119,14 +119,13 @@ BlockHeader.fromString = function fromString(str) { * @private */ BlockHeader._fromBufferReader = function _fromBufferReader(br) { - var info = { - version: br.readUInt32LE(), - prevHash: br.read(32), - merkleRoot: br.read(32), - time: br.readUInt32LE(), - bits: br.readUInt32LE(), - nonce: br.readUInt32LE() - }; + var info = {}; + info.version = br.readUInt32LE(); + info.prevHash = br.read(32); + info.merkleRoot = br.read(32); + info.time = br.readUInt32LE(); + info.bits = br.readUInt32LE(); + info.nonce = br.readUInt32LE(); return info; }; diff --git a/test/block.js b/test/block.js index 8df1360..d3b9771 100644 --- a/test/block.js +++ b/test/block.js @@ -27,9 +27,8 @@ describe('Block', function() { var blockbuf = new Buffer(blockhex, 'hex'); var size = data.blocksize; var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex')); - var txsvi = Varint().fromNumber(data.txsvi); var txs = []; - JSON.parse(dataJson).txs.forEach(function(tx){ + JSON.parse(dataJson).transactions.forEach(function(tx){ txs.push(new Transaction().fromJSON(tx)); }); var json = dataJson; @@ -45,7 +44,7 @@ describe('Block', function() { it('should not make an empty block', function() { (function() { - var b = new Block(); + return new Block(); }).should.throw('Unrecognized argument for Block'); }); @@ -56,20 +55,18 @@ describe('Block', function() { magicnum: magicnum, size: size, header: bh, - txsvi: txsvi, - txs: txs + transactions: txs }); should.exist(b.magicnum); should.exist(b.size); - should.exist(b.txsvi); should.exist(b.header); - should.exist(b.txs); + should.exist(b.transactions); }); it('should properly deserialize blocks', function() { dataBlocks.forEach(function(block){ - var b = Block.fromBuffer(new Buffer(block.data, 'hex')); - b.txs.length.should.equal(block.transactions); + var b = Block.fromBuffer(new Buffer(block.data, 'hex'), {skipMagic: true}); + b.transactions.length.should.equal(block.transactions); }); }); @@ -98,8 +95,7 @@ describe('Block', function() { should.exist(block.magicnum); should.exist(block.size); should.exist(block.header); - should.exist(block.txsvi); - should.exist(block.txs); + should.exist(block.transactions); }); it('should set these known values', function() { @@ -108,8 +104,7 @@ describe('Block', function() { should.exist(block.magicnum); should.exist(block.size); should.exist(block.header); - should.exist(block.txsvi); - should.exist(block.txs); + should.exist(block.transactions); }); it('accepts an object as argument', function() { @@ -127,8 +122,7 @@ describe('Block', function() { should.exist(b.magicnum); should.exist(b.size); should.exist(b.header); - should.exist(b.txsvi); - should.exist(b.txs); + should.exist(b.transactions); }); }); @@ -225,14 +219,14 @@ describe('Block', function() { it('should describe as invalid merkle root', function() { var x = Block.fromRawBlock(dataRawBlockBinary); - x.txs.push(new Transaction()); + x.transactions.push(new Transaction()); var valid = x.validMerkleRoot(); valid.should.equal(false); }); it('should get a null hash merkle root', function() { var x = Block.fromRawBlock(dataRawBlockBinary); - x.txs = []; // empty the txs + x.transactions = []; // empty the txs var mr = x.getMerkleRoot(); mr.should.deep.equal(Block.Values.NULL_HASH); }); diff --git a/test/data/blk86756-testnet.json b/test/data/blk86756-testnet.json index 0e0799f..0450b7c 100644 --- a/test/data/blk86756-testnet.json +++ b/test/data/blk86756-testnet.json @@ -9,8 +9,7 @@ "bits": 473956288, "nonce": 3594009557 }, - "txsvi": "16", - "txs": [{ + "transactions": [{ "version": 1, "txinsvi": "01", "txins": [{ From 38b8c211f33b4b325aef721e68d224f3761fef79 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 16:27:38 -0500 Subject: [PATCH 54/68] Fix jshint complaints. --- lib/block.js | 1 - test/block.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/lib/block.js b/lib/block.js index 015d2b0..1e76941 100644 --- a/lib/block.js +++ b/lib/block.js @@ -9,7 +9,6 @@ var BufferWriter = require('./encoding/bufferwriter'); var Hash = require('./crypto/hash'); var JSUtil = require('./util/js'); var Transaction = require('./transaction'); -var Varint = require('./encoding/varint'); /** * Instantiate a Block from a Buffer, JSON object, or Object with diff --git a/test/block.js b/test/block.js index d3b9771..964914f 100644 --- a/test/block.js +++ b/test/block.js @@ -1,6 +1,5 @@ 'use strict'; -var assert = require('assert'); var bitcore = require('..'); var BN = require('../lib/crypto/bn'); var BufferReader = bitcore.encoding.BufferReader; @@ -11,7 +10,6 @@ var chai = require('chai'); var fs = require('fs'); var should = chai.should(); var Transaction = bitcore.Transaction; -var Varint = bitcore.encoding.Varint; // https://test-insight.bitpay.com/block/000000000b99b16390660d79fcc138d2ad0c89a0d044c4201a02bdf1f61ffa11 var dataRawBlockBuffer = fs.readFileSync('test/data/blk86756-testnet.dat'); From 116ddac34553e43913d5e8c9eb7123f730d79de1 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 16:41:44 -0500 Subject: [PATCH 55/68] If skipMagic is enabled do not set the magic or size on the block, the values would have been incorrect. --- lib/block.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/block.js b/lib/block.js index 1e76941..d4fa1f7 100644 --- a/lib/block.js +++ b/lib/block.js @@ -114,10 +114,6 @@ Block._fromBufferReader = function _fromBufferReader(br, options) { info.size = br.readUInt32LE(); } info.header = BlockHeader.fromBufferReader(br); - if (options.skipMagic) { - info.magicnum = 0; - info.size = info.header.bits; - } var transactions = br.readVarintNum(); info.transactions = []; for (var i = 0; i < transactions; i++) { From 6aa0d14bb998ceba60aeee6fe266d30d0b7b7055 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 23:23:02 -0500 Subject: [PATCH 56/68] Removed magicnumber and size as properties of a block. --- lib/block.js | 29 +++-------------------------- test/block.js | 14 ++------------ test/data/blk86756-testnet.js | 5 +---- test/data/blk86756-testnet.json | 2 -- 4 files changed, 6 insertions(+), 44 deletions(-) diff --git a/lib/block.js b/lib/block.js index d4fa1f7..e158b4c 100644 --- a/lib/block.js +++ b/lib/block.js @@ -43,20 +43,6 @@ Block._from = function _from(arg) { info = Block._fromJSON(arg); } else if (_.isObject(arg)) { info = { - /** - * @name Block#magicnum - * @type number - */ - magicnum: arg.magicnum, - /** - * @name Block#size - * @type number - */ - size: arg.size, - /** - * @name Block#header - * @type {BlockHeader} - */ header: arg.header, /** * @name Block#transactions @@ -84,8 +70,6 @@ Block._fromJSON = function _fromJSON(data) { transactions.push(Transaction().fromJSON(data)); }); var info = { - magicnum: data.magicnum, - size: data.size, header: BlockHeader.fromJSON(data.header), transactions: transactions }; @@ -106,13 +90,8 @@ Block.fromJSON = function fromJSON(json) { * @returns {Object} - An object representing the block data * @private */ -Block._fromBufferReader = function _fromBufferReader(br, options) { - options = options || {}; +Block._fromBufferReader = function _fromBufferReader(br) { var info = {}; - if (!options.skipMagic) { - info.magicnum = br.readUInt32LE(); - info.size = br.readUInt32LE(); - } info.header = BlockHeader.fromBufferReader(br); var transactions = br.readVarintNum(); info.transactions = []; @@ -157,6 +136,7 @@ Block.fromRawBlock = function fromRawBlock(data) { data = new Buffer(data, 'binary'); } var br = BufferReader(data); + br.pos = Block.Values.START_OF_BLOCK; var info = Block._fromBufferReader(br); return new Block(info); }; @@ -170,8 +150,6 @@ Block.prototype.toObject = function toObject() { transactions.push(tx.toObject()); }); return { - magicnum: this.magicnum, - size: this.size, header: this.header.toObject(), transactions: transactions }; @@ -206,8 +184,6 @@ Block.prototype.toBufferWriter = function toBufferWriter(bw) { if (!bw) { bw = new BufferWriter(); } - bw.writeUInt32LE(this.magicnum); - bw.writeUInt32LE(this.size); bw.write(this.header.toBuffer()); bw.writeVarintNum(this.transactions.length); for (var i = 0; i < this.transactions.length; i++) { @@ -311,6 +287,7 @@ Block.prototype.inspect = function inspect() { }; Block.Values = { + START_OF_BLOCK: 8, // Start of block in raw block data NULL_HASH: new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex') }; diff --git a/test/block.js b/test/block.js index 964914f..b2f09b7 100644 --- a/test/block.js +++ b/test/block.js @@ -31,7 +31,7 @@ describe('Block', function() { }); var json = dataJson; - var genesishex = 'f9beb4d91d0100000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; + var genesishex = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; var genesisbuf = new Buffer(genesishex, 'hex'); var genesisidhex = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'; @@ -50,20 +50,16 @@ describe('Block', function() { it('should set these known values', function() { var b = new Block({ - magicnum: magicnum, - size: size, header: bh, transactions: txs }); - should.exist(b.magicnum); - should.exist(b.size); should.exist(b.header); should.exist(b.transactions); }); it('should properly deserialize blocks', function() { dataBlocks.forEach(function(block){ - var b = Block.fromBuffer(new Buffer(block.data, 'hex'), {skipMagic: true}); + var b = Block.fromBuffer(new Buffer(block.data, 'hex')); b.transactions.length.should.equal(block.transactions); }); }); @@ -90,8 +86,6 @@ describe('Block', function() { it('should set these known values', function() { var block = Block.fromJSON(json); - should.exist(block.magicnum); - should.exist(block.size); should.exist(block.header); should.exist(block.transactions); }); @@ -99,8 +93,6 @@ describe('Block', function() { it('should set these known values', function() { var block = Block(json); - should.exist(block.magicnum); - should.exist(block.size); should.exist(block.header); should.exist(block.transactions); }); @@ -117,8 +109,6 @@ describe('Block', function() { it('should recover these known values', function() { var block = Block.fromJSON(json); var b = JSON.parse(block.toJSON()); - should.exist(b.magicnum); - should.exist(b.size); should.exist(b.header); should.exist(b.transactions); }); diff --git a/test/data/blk86756-testnet.js b/test/data/blk86756-testnet.js index f8c0d73..51ed9cd 100644 --- a/test/data/blk86756-testnet.js +++ b/test/data/blk86756-testnet.js @@ -1,9 +1,6 @@ 'use strict'; module.exports = { - magicnum: 0xd9b4bef9, - blocksize: 8003, - txsvi: 22, version: 2, time: 1371410638, bits: 473956288, @@ -11,5 +8,5 @@ module.exports = { prevblockidhex: '4baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c00000000', merkleroothex: '97fc4c97868288e984ff9f246f2c38510f5c37a3d5b41aae7004b01e2dd5e658', blockheaderhex: '020000004baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c0000000097fc4c97868288e984ff9f246f2c38510f5c37a3d5b41aae7004b01e2dd5e658ce10be51c0ff3f1cd53b38d6', - blockhex: '0b110907431f0000020000004baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c0000000097fc4c97868288e984ff9f246f2c38510f5c37a3d5b41aae7004b01e2dd5e658ce10be51c0ff3f1cd53b38d61601000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0b03e45201062f503253482fffffffff034034152a010000001976a914ee9a7590f91e04832054f0645bbf243c9fac8e2288ac0000000000000000434104ffd03de44a6e11b9917f3a29f9443283d9871c9d743ef30d5eddcd37094b64d1b3d8090496b53256786bf5c82932ec23c3b74d9f05a6f95a8b5529352656664bac0000000000000000252458e99e66e2b90bd8b2a0e2bfcce91e1f09ee7621d95e9a728ca2372d45df3ded00000000000000000100000001d6e149959b6248eee5a17c23a518e5e5e399e98f7d42a2833810f3baf1525acf000000006b4830450221009273f5d777408439a40c33ee96630a877d4f29af3f60f5c230e5254ee6f08f4302207975a64f43dc632f34479aa403b9956c484ad0c90a3c50d2e1b5037e1abb586f012103449772f2c60c2f4e1f1f74cb6c521a48f12d51ea681b64c8fc074fd8108123f6ffffffff02cb6a8233000000001976a9140487c481a671649e1db182ede98d093a335d671388ac25a21d9d000000001976a914590ea00fa3a18281d3020e7ba0c3a1d6aea663c088ac0000000001000000022a24c5dfbdb9dc5e1eb5d38dc9e8c5f8643aee53fcb0d2e44a04924b55c65c6b000000006a47304402207aa649b3ba03eeac6c6fb88e74800ca418297f62da75c58284a0c5f6cdfa96b70220324eb99fecdb0eb8bd4eec05bec0f440f4c2132c1afbaa7aaf10f31d17d8ef020121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff1186e9edc6526a3ab463d1f0123ae38e5593364d2f80de9d8031a48274b718ab000000006c49304602210084cd799ec732e95a08c9e1ef98e99e43767b6bc4eb6af6cf65ecdf2be6bc96ab022100da1d1c450d675d383b92095c2b9949d693b82b54ac81ba219fad98f8500589ad012102b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786ffffffff0260dc2c00000000001976a91468340b9145127d2529dd7ebc3a4567d5579997ac88acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000020f5000a056f91d03c489d7d1558f09c7bc330af3ca8e43706d5cb08fd6c60aad010000006a47304402201068b39118afc383bb1b7de9aa8fe02cddbd8be5d29cab99d5fff23a0cef5667022020d6cfb4712fc61c13c7ca26e32028cce3d68afea7957ab4bfc5ee03bf9615d4012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff08d4577f5634796567fb0cd50abd1886df3555f71847a1977ba5bc75195405a7010000006a47304402206728ade49cb5ec883e07d8acc6450e17b0e27b7f64c81143b4632eaded365e2e02202be3b4b723200de8c070b914d0050ead71d1418196a037f55f1a6dff4e45aee30121039e65fd2479d4edb0f3db6eecacdadcdc5ddd6d8ef518cf861466dfe1c21cc891ffffffff02d0b13700000000001976a9149a704e2c99955f50694de60f93cdd449473678aa88acc0c62d00000000001976a914dac91bdfe809346e9df5e753adaaef9336344bfc88ac000000000100000002fc85133b1e259f6deec25953bccfa75df61fd23a471553c80c043c2ea716a675000000006a47304402203da7beabc48687b746a7149679bd8982032816771b5634d1d651af59ce9fa86d0220198ea81d1a547e3493988dd94ffefff3b8fe030340886aa4ffc1b205532f0f9d012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff04297137bc2c9f486713e4e4fab43134da153e0f8ee8e852554090d02f2605a5000000006a47304402206b729bfd4c132b673c9f1a66c645ed374338963f1e6a3b56229f72b4358f8077022023bea16c89d267313da6df152a976b36a36e1bbea738d698f0ce72ef315962df012103ba341f7dd2401a2cd51682d418fd8a12b4d0b09acb8971f0671c2211366a8531ffffffff0220753800000000001976a9144769612ee7c6e977df40a8cdfd837c85cc7a48f788acc0c62d00000000001976a914dac91bdfe809346e9df5e753adaaef9336344bfc88ac0000000001000000021cb5734a303cefa1ace87b8cc386a573f1eed8370e14c0a830fd04249b7756a6000000006a473044022059bbf19179b81fad8a15ba3dff94271d55d443da636dbaeba6ea0bb5901b8779022045417e208f41f8b37473caaf367a61ed21b31f1205605020de241e89b7ec0ca60121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffffbabb329d773e9101e127f7c1e95533fb384c79260789dc06fdf73296c9ef352d000000006b4830450220012c555e725f4eb0d767efdc07aec149c63522b06253e9d1ce6245b90c71951e022100edcce82ddd7e52a3b85bf9a4acc73a3b6df5c9b40fda36e8de09890860599ddf012102b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786ffffffff0210fb3000000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac20cf2900000000001976a914e1144ff8ca0ac143b83ada244040bfe9c8d1d63888ac0000000001000000029a494e6072106a040e279b4566f25fc35441a84f6228812142eb5515688832f5000000006b483045022100b35809ba9abcea1ec143c7cd0a27845b3f5139a6bb52757c9e24d86319f8d16c022079f8381c5287af7e6488d6a589e73caf23c487bf355ac22b7c01cf58830110bf0121023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6affffffffec7d5d39d4db41d7d9ba0653b6c9758f20cf89a4c2e60bb27645a966889fdfd6000000006a473044022008848d34f2ca77f8bf79eb83b89ee8a24292d0c3936350a37f1522664e2e216002204ad05817044e18d0c26e89139b9fb98a21ceda2249a7cfa58f3ec420af9477c7012103af07092ed729d97d5e2ae9f8a295f1b2da268e7414ce3df9b374051d7647092bffffffff0220753800000000001976a914b1b9b659297859bd310ba8ba6f95573c635b191a88acc0c62d00000000001976a914636c549bf6035b27cf3823f5482911ebb2bce5d088ac0000000001000000028c88435add45be7b1521756b8ee3bfc51558040c3922e11facff1d6cdc7fc841000000006a47304402201bf92a99fd85e09de43b9039801f387ad6ea996d71c02185019a18cd2691d68502204500ea82873501c25c5b1476f9cd75d70b2a34a4162470e3390f89ff6a5830110121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffffbb1d138f7c9e8df06a87cd068fc303cb960c7b5670515a7759653fd3b71c6e7e000000006b4830450220277eb0e03b897cd20ac3bfa15af82ae2c1e75472ffce0482ce1594cd4536e83802210088164c46f3fc82ed3530b7552a1da6ecd2f690647485bb0fe1a706ae0f09d5b6012102718b695944b9e6f12db75e7dc7b77f023c8b9706405b62dac6e6c94dc1c7214effffffff0230c11d00000000001976a914e22f515855329b13602778a1d681295e485390b888acd0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac000000000100000002948a4df70264c816b3c65bb1315bc20df2ee12baaba580818ed232a59dbe3282000000006b483045022100e96feaa777c517aa67498d51c52b7c177c18f7eb96c7ec109bcf4b7d1993245e02203d4f6dc06f4ac4ff947d81a45c9e53b12ee89e4223aa670eee2ca435157f6054012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff8dddf5d111131865b48f2b141f635ac6c41f14adc748ea0cd6087fd69b60d573000000006b4830450220588e7eb9477043dc7b7d9f554b5db44823d9b7108a73d224af8cb24b190ebc94022100deb2fd7cfbff5f7679a38a16c18075dc9eb705850054415eba27a0f769f94e8d012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff0220cf2900000000001976a9147ff6d70c9f71e29f3b3b77e1acb0bae8d1af12d288ac10fb3000000000001976a9141c5b740011cff8324ed10c3e8f63f6261f36613a88ac0000000001000000027624f057be29a1d4d39112006d1a1acaca84b78f5e2323c3ae587365f91b6014000000006a47304402201bfc0a95285de492ca53fd2ab89b58cdb1d9d817d7c4ade64e31bb63ccf73b7802206d4f72973c9aa804d9a5c9b749a49aec579ab7875d30c1e0b9ab8d3d7b8041ad012102926efc059307ca51862547d58b7a0c1749f0e27df6fbea550bbb291ef0a00bcbffffffffed83ae0fa16dd5602ca174f1c845be1f1c370ce483925dda6e524e6f82b93bd8000000006c4930460221008de29b6fafdadc7a1430ff453c9cb4ea96f9186c1c43b9d1f243876c4d187c5a022100f03f8a8a43c39a619c03db80bedaf9111ee817a574edf912795b3bef85024d46012102891fda8944ae461484abdc5898a94d666d8e54ed47f534218601c9a39e1058b8ffffffff02c0c62d00000000001976a914fc9c507e2cf3563c63bf9ec7b38773c2a1e1c47288acd0933c00000000001976a914736d9e4703437b3f245cda14ab4ed2d52b0a622d88ac000000000100000002a34b87af6103eac5adaba08069aca7f19c6091f6b1f4b8ca788e54970cab2039010000006b483045022049ce62033552a024ce0badb3d3c9db84af929c373b816dade2611563871e48840221009f80e97265ce861637468c98237a06df9c7482cc7c1739e1c36a8e85537c7f160121032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20fffffffffa973c9f57b44c4f70b181311ba1ab60c3f3c20663a3127d3c418b9bb3b175ef4000000006b48304502204d5decc921dff956fbcfa1a574e43e0d17b9a49ee07f294b74f854f0dd7e0160022100d49781e18670f3372961dd5799d162071e13832fa9f15197c90d7b8ab8168e8d012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff0260dc2c00000000001976a914cc0d9d6d476efe8205891836f40e00caf2fde49288acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000026904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1010000006a4730440220740a2107c2d9be5f621822667b9cc34566511c0e6767de900f3b46fa0852d62302207cf2fcf969e48fce7ad43880bd3a7ee5658a421a3fb718e3fd824e22e4bac6ee012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffffa3693948981b6fab5aeb9df82b1fc8e3fdbfeff8d934ce0617f4a9be699e06e7010000006c493046022100942e3ffd4522789f747b0c0d18a7228ba9f343294a34ffb0a53801b0d1626963022100eacf2ea0eef2c58e2666442bd331489dbda43adfd6d4809c2e71de38aff7fd92012103de66ea9a044ee251ba8a6dfe1d68ee1c2e17acaf5d8b568a515ff37752b6ea0effffffff0260dc2c00000000001976a914ac64ed9c139e44fd8d1d9ad28d1d08fc8a8f70f888acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000023b45e99dd007030fd8511434235b70a7d29041eb1e72d3cb2dda7d1e769ec13c000000006b48304502201c10c88a04850d9101b6cbcb51c28d9ca34f693fd918ba3c26775c5993cbdfc1022100e5d7708777b9592d709863859ce0f4d590f56acf5bb3655e119cac10d597c463012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff87cc87cf0be7989073235f455fe6524324bfe8cba5f4ee3c2a59c46fec3bf14a010000006b48304502205cd5ea454979d705d4573d7b6f6a1bae22e5f146e0ccd14079a959a429bf69fc022100d88f05762b394621ec967546151b682f8103bed05b6d99b80adfadd626a721c5012103803aa78d28c40170231e0520fc38daa405140ed6e177c0747ce9d8d7dd6cdee4ffffffff0210dd3500000000001976a914bc1e95774ee2e36d2687714da14551132f0588b088acc0c62d00000000001976a914859819cb59368e07d4c95b5221fa4c466d66694988ac0000000001000000027848ce7fbc4f3b3e56a778607e046aa2b2cf891cdba8b61186095d4931b44c72000000006b483045022100850533f400465b01658b7dfcb05b3bae38a89344065f8321f69f7b1b2036446f0220663a629b5f2b1cf8748558ae71c8b49cda87e43347d4cbf4c84e3a79bc904a49012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff0e33c08e14303d5660127f5d3792ca11c18321a276e71f53415af75a2319ee92010000006b483045022020d4bbbc5c300aadbc52110f7aa971d77bcf567c91d288ed6af0a98fc8f75e74022100ea84ee6d3fbeb672e92ea993d27202fc9ecd33ba7494d8b064518649fc2c17dc0121036a91343ca1c973401accb1fb902336d2a7a1b4f670ff82d9acc5c380d6a627f0ffffffff02a03c3700000000001976a9144cc35fc2651b5b3e4f22dfa9b6ebef0ca1797fb088acc0c62d00000000001976a91449452bed77744157799ba71fdb43efbd66968ad188ac0000000001000000022a6cc52c8804088ddbc164cfa01e4d9ee7e839c7a8f5d2f1b59b70a50d253f24000000006b483045022100bd72079af0ba0965d01dc6de2502ceebe38fa94fcf9850140e7ce1e5ef29d3cc02207da0e0b881594a9bc8750143dfa41ce8255e14f24784a551d3d1c4a2acecc0a2012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff36262f4b7717eca333432cd9af776bb5ef4b29a2ea1b1cf877b49642db945c62010000006b483045022100f074c81f476f50dad72d3d07cef668532bb2b0cc772b49abf67cafd476e4e41302201e36efd9eec72b2f5ff4eac4ffbbe0598c6185b63c6ba8e03737b708e73149940121022d7e055cd28a8b7ca2613687e9b5cd4ff4a959c54d74f49c12345d1d8f78b374ffffffff02c0c62d00000000001976a914fc9c507e2cf3563c63bf9ec7b38773c2a1e1c47288ac70383900000000001976a9145ab29618ded8892f8189ca3ce81bef83d3ddda1688ac000000000100000002d724e595476277be4337bb8f39ca700b4f9df1bfb84089c4afd338e1079e9add010000006b483045022100f775b297513593c1c6e461902ab6405c4c38ce3b37d9292fe074153b8c466c29022010ded748e9e7fb1fbb263b8f466e6a1352e05ddb8842a17f712478e3d9c177040121023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6affffffffff40fb739e2271f4aaa851dd46fcd1895ddd7a98850ef191ba3b50325c29a4ed010000006b4830450220686b1c5ecd7ea0e9078784f5ea0100035a962809fd1d0cf7a131604ecfb26f02022100ddf7b8874a375edfa4d0d7b93cfd214d0327e550add318f1a8a379cceae8dac601210363c3fa31a5453a29f6cde46c9d77698fd8276cf9f511dd6e5d079a231fea568effffffff02a01e3c00000000001976a914b0c1cda106bb5085bd9c0c9982773c7bd066fabc88acc0c62d00000000001976a914859819cb59368e07d4c95b5221fa4c466d66694988ac000000000100000002a9b95beed9491639bc0d1bb833005cf45429ef9a50505f9b91f3c7588feb87ef010000006c493046022100854bc0ee8b24e2b625798148fc505cb37464f72688456dc54b0c25c4dd564091022100c2863ab346c23157baaeb45e6d102e7354cc895ee0dd7b6ecdc77ab34bdd4d0f0121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff8eaaf0d722fe9deffbc6e9d543f406844c93d1dd1c073d739863c314d2adf4ef000000006a47304402203f28684b208f0f4bf87ca22544e59585a7807fcd5a2ec78fc93ce915e282335502201ab05402d3a2b2914dd955971fade92dc874e6441bc2383766ec8b4c56dca27501210251a3bd043afe5cf46a40c4ce4caf3e917190583588634711507d6ef77acc438bffffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac90ab1e00000000001976a914b27f37b7cee282e7890f4f6df9b49574f35e855288ac000000000100000002fadecb6a5b1bd5f0688fc7dd049dadd956c30006e4dc57155f22c054c1550791000000006b48304502201dcb7d73d180cda9ddb192e50fcf5f0efaa5e680931f2bc25e58dd368d4b815f0221008149257f9394b01188aa84f92aec7374339076b408360767236a3af18718cddc0121032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20fffffffff569ed0585b1d5261fe5a1839e99c23d0cd3b82972526c5bb5b812ceb493facc3010000006b48304502205665ae2983ad6ec44220810a6f4c28d77dd518cc891eb9ed67503a756e97c477022100ab456b8a9c1f977623956943d8f1892c3bf84d8adefaa405606d3473f37fb8b4012102bbdf0772bbacab8eaba47d783d30fa401b08a0ecc4bccd49357171ac38791c0effffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac504b1400000000001976a914a6a0900e3c77496dc68be8ee130a21b446b8266588ac0000000001000000023d9d0df887b3621c3c884515d1a4c0a22e2bc4aa02300493cb568189847265db010000006b483045022100af41bf6edc04de96ad8b0d0e0794a7055c9677f2616fcfc1b053f87ad5c60c0f02201ef5279534263776cca80957368791a362354d7a40f3f175874b909de2d7f9a10121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff70f6c965fcbae21ee712571b683b33e3b4d0e9c5d1fd685046db7176e3bf432e000000006b483045022033da8150f9870e045581f5894366f57345946174b43b7f8c0f9b24f7afad395c022100e3db87d42b1050ea8f2e964a13eeae86cc57e771c4dfa29f7f055c74a39be3b801210221f705f7d58ceea66122bcdc7220db0583d8ce1d7d948ed86007905268f55162ffffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac50802000000000001976a91447830d334d04acd62668904b6fab06a90742e75088ac0000000001000000022e48318fb557623da627d1c3f81ab34b99a87ce701440dfb907ad6a8691b51f2000000006c493046022100d2733fcc63dd86bc4653d268f16e467e87a7be9e1d3f45cbeccb2423b7eb1c6c022100e3963622c12dab3e9c0c76a8ef13151114cb0f17abe6c29cca2fcbac264dfc980121020ce8a0852e31812de6b8f2b2604d948cb06f8f7f404e70a19067cca01b5d0988ffffffff675f09c92aa029f3283ee9a6b8bd6f022a1ea3bdccb1d33a09416ee9389e3ecb000000006b48304502202beb8d4ff142762f12f867a1686c2a523c55ff336b8ae3992ae1292019afeaf1022100a2e7edb9ffb29628540fd02b21c84abf1cc48d70c9f6adb39550b8aff572c65a012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff02d0933c00000000001976a914449c3ac7336a78f0c6401f51710949005d2c7ffa88acc0c62d00000000001976a914636c549bf6035b27cf3823f5482911ebb2bce5d088ac00000000010000000233232e2ce65e394a2c7e46519fae48b9b711b5152f764a4d6454bfc0552f275a000000006c493046022100928f760eaabaed51bfc4db0188c84a6a19ef34a88786f2a25d8050c8356d858d022100c1a35c67f2c21b4837eaf73e195c74eb213bdaa4650fe77da072db9f84b90d0c0121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cfffffffff7fc20459ede0aeba4e9224ac667212ff815c651ca4feaaf40880b9f9d82413a010000006c493046022100c098dd6d9b20ed80de2d86d2c1bc9328b1c42f04b03c3767aec9d846d4538c9d0221009e32178215a499f22d8d3afe9f257159143c3d24f07371e0ef2de97d216e3b42012102078d4050a314870bd68960765015e5f884e35c60b44e23e0f2d264b73aaca477ffffffff0210fb3000000000001976a9141c5b740011cff8324ed10c3e8f63f6261f36613a88ac20cf2900000000001976a9147bdb65a92af2520836f77e5ebccc697d814149ce88ac000000000100000002dae9bc0142c15e33fe26a494d1233e80adf68b50a131f467eb13450caa56e43d000000006c493046022100ecf03f0bafb0cf6e08ac80336565bf79b6bac800f546e9f953fb14df7bf239ac022100982e27f2f0b3f8569cef126c0c54a88b002f00d570106c74f5c4b314c9609442012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff6904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1000000006c493046022100febc4cdfbd5073ee756c9763b0e18009893b422e13c25e8f74ca97b84c0cf73f022100a85a6c10debf45e8ad00db28fce5fcb68404e9ac4b844f0ae1d59c0ef210d714012103dc9adee9c23ca7a091b4eafc4dfef2ed07adf903dae568f345095321aa9c57e2ffffffff02a03c3700000000001976a91467a341d7fe4de6a810c182ed27a09554e0b4405d88acc0c62d00000000001976a914f7f1f64a590896dccfb869ced060f058007f388b88ac00000000' + blockhex: '020000004baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c0000000097fc4c97868288e984ff9f246f2c38510f5c37a3d5b41aae7004b01e2dd5e658ce10be51c0ff3f1cd53b38d61601000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0b03e45201062f503253482fffffffff034034152a010000001976a914ee9a7590f91e04832054f0645bbf243c9fac8e2288ac0000000000000000434104ffd03de44a6e11b9917f3a29f9443283d9871c9d743ef30d5eddcd37094b64d1b3d8090496b53256786bf5c82932ec23c3b74d9f05a6f95a8b5529352656664bac0000000000000000252458e99e66e2b90bd8b2a0e2bfcce91e1f09ee7621d95e9a728ca2372d45df3ded00000000000000000100000001d6e149959b6248eee5a17c23a518e5e5e399e98f7d42a2833810f3baf1525acf000000006b4830450221009273f5d777408439a40c33ee96630a877d4f29af3f60f5c230e5254ee6f08f4302207975a64f43dc632f34479aa403b9956c484ad0c90a3c50d2e1b5037e1abb586f012103449772f2c60c2f4e1f1f74cb6c521a48f12d51ea681b64c8fc074fd8108123f6ffffffff02cb6a8233000000001976a9140487c481a671649e1db182ede98d093a335d671388ac25a21d9d000000001976a914590ea00fa3a18281d3020e7ba0c3a1d6aea663c088ac0000000001000000022a24c5dfbdb9dc5e1eb5d38dc9e8c5f8643aee53fcb0d2e44a04924b55c65c6b000000006a47304402207aa649b3ba03eeac6c6fb88e74800ca418297f62da75c58284a0c5f6cdfa96b70220324eb99fecdb0eb8bd4eec05bec0f440f4c2132c1afbaa7aaf10f31d17d8ef020121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff1186e9edc6526a3ab463d1f0123ae38e5593364d2f80de9d8031a48274b718ab000000006c49304602210084cd799ec732e95a08c9e1ef98e99e43767b6bc4eb6af6cf65ecdf2be6bc96ab022100da1d1c450d675d383b92095c2b9949d693b82b54ac81ba219fad98f8500589ad012102b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786ffffffff0260dc2c00000000001976a91468340b9145127d2529dd7ebc3a4567d5579997ac88acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000020f5000a056f91d03c489d7d1558f09c7bc330af3ca8e43706d5cb08fd6c60aad010000006a47304402201068b39118afc383bb1b7de9aa8fe02cddbd8be5d29cab99d5fff23a0cef5667022020d6cfb4712fc61c13c7ca26e32028cce3d68afea7957ab4bfc5ee03bf9615d4012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff08d4577f5634796567fb0cd50abd1886df3555f71847a1977ba5bc75195405a7010000006a47304402206728ade49cb5ec883e07d8acc6450e17b0e27b7f64c81143b4632eaded365e2e02202be3b4b723200de8c070b914d0050ead71d1418196a037f55f1a6dff4e45aee30121039e65fd2479d4edb0f3db6eecacdadcdc5ddd6d8ef518cf861466dfe1c21cc891ffffffff02d0b13700000000001976a9149a704e2c99955f50694de60f93cdd449473678aa88acc0c62d00000000001976a914dac91bdfe809346e9df5e753adaaef9336344bfc88ac000000000100000002fc85133b1e259f6deec25953bccfa75df61fd23a471553c80c043c2ea716a675000000006a47304402203da7beabc48687b746a7149679bd8982032816771b5634d1d651af59ce9fa86d0220198ea81d1a547e3493988dd94ffefff3b8fe030340886aa4ffc1b205532f0f9d012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff04297137bc2c9f486713e4e4fab43134da153e0f8ee8e852554090d02f2605a5000000006a47304402206b729bfd4c132b673c9f1a66c645ed374338963f1e6a3b56229f72b4358f8077022023bea16c89d267313da6df152a976b36a36e1bbea738d698f0ce72ef315962df012103ba341f7dd2401a2cd51682d418fd8a12b4d0b09acb8971f0671c2211366a8531ffffffff0220753800000000001976a9144769612ee7c6e977df40a8cdfd837c85cc7a48f788acc0c62d00000000001976a914dac91bdfe809346e9df5e753adaaef9336344bfc88ac0000000001000000021cb5734a303cefa1ace87b8cc386a573f1eed8370e14c0a830fd04249b7756a6000000006a473044022059bbf19179b81fad8a15ba3dff94271d55d443da636dbaeba6ea0bb5901b8779022045417e208f41f8b37473caaf367a61ed21b31f1205605020de241e89b7ec0ca60121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffffbabb329d773e9101e127f7c1e95533fb384c79260789dc06fdf73296c9ef352d000000006b4830450220012c555e725f4eb0d767efdc07aec149c63522b06253e9d1ce6245b90c71951e022100edcce82ddd7e52a3b85bf9a4acc73a3b6df5c9b40fda36e8de09890860599ddf012102b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786ffffffff0210fb3000000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac20cf2900000000001976a914e1144ff8ca0ac143b83ada244040bfe9c8d1d63888ac0000000001000000029a494e6072106a040e279b4566f25fc35441a84f6228812142eb5515688832f5000000006b483045022100b35809ba9abcea1ec143c7cd0a27845b3f5139a6bb52757c9e24d86319f8d16c022079f8381c5287af7e6488d6a589e73caf23c487bf355ac22b7c01cf58830110bf0121023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6affffffffec7d5d39d4db41d7d9ba0653b6c9758f20cf89a4c2e60bb27645a966889fdfd6000000006a473044022008848d34f2ca77f8bf79eb83b89ee8a24292d0c3936350a37f1522664e2e216002204ad05817044e18d0c26e89139b9fb98a21ceda2249a7cfa58f3ec420af9477c7012103af07092ed729d97d5e2ae9f8a295f1b2da268e7414ce3df9b374051d7647092bffffffff0220753800000000001976a914b1b9b659297859bd310ba8ba6f95573c635b191a88acc0c62d00000000001976a914636c549bf6035b27cf3823f5482911ebb2bce5d088ac0000000001000000028c88435add45be7b1521756b8ee3bfc51558040c3922e11facff1d6cdc7fc841000000006a47304402201bf92a99fd85e09de43b9039801f387ad6ea996d71c02185019a18cd2691d68502204500ea82873501c25c5b1476f9cd75d70b2a34a4162470e3390f89ff6a5830110121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffffbb1d138f7c9e8df06a87cd068fc303cb960c7b5670515a7759653fd3b71c6e7e000000006b4830450220277eb0e03b897cd20ac3bfa15af82ae2c1e75472ffce0482ce1594cd4536e83802210088164c46f3fc82ed3530b7552a1da6ecd2f690647485bb0fe1a706ae0f09d5b6012102718b695944b9e6f12db75e7dc7b77f023c8b9706405b62dac6e6c94dc1c7214effffffff0230c11d00000000001976a914e22f515855329b13602778a1d681295e485390b888acd0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac000000000100000002948a4df70264c816b3c65bb1315bc20df2ee12baaba580818ed232a59dbe3282000000006b483045022100e96feaa777c517aa67498d51c52b7c177c18f7eb96c7ec109bcf4b7d1993245e02203d4f6dc06f4ac4ff947d81a45c9e53b12ee89e4223aa670eee2ca435157f6054012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff8dddf5d111131865b48f2b141f635ac6c41f14adc748ea0cd6087fd69b60d573000000006b4830450220588e7eb9477043dc7b7d9f554b5db44823d9b7108a73d224af8cb24b190ebc94022100deb2fd7cfbff5f7679a38a16c18075dc9eb705850054415eba27a0f769f94e8d012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff0220cf2900000000001976a9147ff6d70c9f71e29f3b3b77e1acb0bae8d1af12d288ac10fb3000000000001976a9141c5b740011cff8324ed10c3e8f63f6261f36613a88ac0000000001000000027624f057be29a1d4d39112006d1a1acaca84b78f5e2323c3ae587365f91b6014000000006a47304402201bfc0a95285de492ca53fd2ab89b58cdb1d9d817d7c4ade64e31bb63ccf73b7802206d4f72973c9aa804d9a5c9b749a49aec579ab7875d30c1e0b9ab8d3d7b8041ad012102926efc059307ca51862547d58b7a0c1749f0e27df6fbea550bbb291ef0a00bcbffffffffed83ae0fa16dd5602ca174f1c845be1f1c370ce483925dda6e524e6f82b93bd8000000006c4930460221008de29b6fafdadc7a1430ff453c9cb4ea96f9186c1c43b9d1f243876c4d187c5a022100f03f8a8a43c39a619c03db80bedaf9111ee817a574edf912795b3bef85024d46012102891fda8944ae461484abdc5898a94d666d8e54ed47f534218601c9a39e1058b8ffffffff02c0c62d00000000001976a914fc9c507e2cf3563c63bf9ec7b38773c2a1e1c47288acd0933c00000000001976a914736d9e4703437b3f245cda14ab4ed2d52b0a622d88ac000000000100000002a34b87af6103eac5adaba08069aca7f19c6091f6b1f4b8ca788e54970cab2039010000006b483045022049ce62033552a024ce0badb3d3c9db84af929c373b816dade2611563871e48840221009f80e97265ce861637468c98237a06df9c7482cc7c1739e1c36a8e85537c7f160121032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20fffffffffa973c9f57b44c4f70b181311ba1ab60c3f3c20663a3127d3c418b9bb3b175ef4000000006b48304502204d5decc921dff956fbcfa1a574e43e0d17b9a49ee07f294b74f854f0dd7e0160022100d49781e18670f3372961dd5799d162071e13832fa9f15197c90d7b8ab8168e8d012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffff0260dc2c00000000001976a914cc0d9d6d476efe8205891836f40e00caf2fde49288acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000026904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1010000006a4730440220740a2107c2d9be5f621822667b9cc34566511c0e6767de900f3b46fa0852d62302207cf2fcf969e48fce7ad43880bd3a7ee5658a421a3fb718e3fd824e22e4bac6ee012102690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807ffffffffa3693948981b6fab5aeb9df82b1fc8e3fdbfeff8d934ce0617f4a9be699e06e7010000006c493046022100942e3ffd4522789f747b0c0d18a7228ba9f343294a34ffb0a53801b0d1626963022100eacf2ea0eef2c58e2666442bd331489dbda43adfd6d4809c2e71de38aff7fd92012103de66ea9a044ee251ba8a6dfe1d68ee1c2e17acaf5d8b568a515ff37752b6ea0effffffff0260dc2c00000000001976a914ac64ed9c139e44fd8d1d9ad28d1d08fc8a8f70f888acd0ed2d00000000001976a9143770e8980281b63351861a17881cecbfaaa5c74b88ac0000000001000000023b45e99dd007030fd8511434235b70a7d29041eb1e72d3cb2dda7d1e769ec13c000000006b48304502201c10c88a04850d9101b6cbcb51c28d9ca34f693fd918ba3c26775c5993cbdfc1022100e5d7708777b9592d709863859ce0f4d590f56acf5bb3655e119cac10d597c463012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff87cc87cf0be7989073235f455fe6524324bfe8cba5f4ee3c2a59c46fec3bf14a010000006b48304502205cd5ea454979d705d4573d7b6f6a1bae22e5f146e0ccd14079a959a429bf69fc022100d88f05762b394621ec967546151b682f8103bed05b6d99b80adfadd626a721c5012103803aa78d28c40170231e0520fc38daa405140ed6e177c0747ce9d8d7dd6cdee4ffffffff0210dd3500000000001976a914bc1e95774ee2e36d2687714da14551132f0588b088acc0c62d00000000001976a914859819cb59368e07d4c95b5221fa4c466d66694988ac0000000001000000027848ce7fbc4f3b3e56a778607e046aa2b2cf891cdba8b61186095d4931b44c72000000006b483045022100850533f400465b01658b7dfcb05b3bae38a89344065f8321f69f7b1b2036446f0220663a629b5f2b1cf8748558ae71c8b49cda87e43347d4cbf4c84e3a79bc904a49012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff0e33c08e14303d5660127f5d3792ca11c18321a276e71f53415af75a2319ee92010000006b483045022020d4bbbc5c300aadbc52110f7aa971d77bcf567c91d288ed6af0a98fc8f75e74022100ea84ee6d3fbeb672e92ea993d27202fc9ecd33ba7494d8b064518649fc2c17dc0121036a91343ca1c973401accb1fb902336d2a7a1b4f670ff82d9acc5c380d6a627f0ffffffff02a03c3700000000001976a9144cc35fc2651b5b3e4f22dfa9b6ebef0ca1797fb088acc0c62d00000000001976a91449452bed77744157799ba71fdb43efbd66968ad188ac0000000001000000022a6cc52c8804088ddbc164cfa01e4d9ee7e839c7a8f5d2f1b59b70a50d253f24000000006b483045022100bd72079af0ba0965d01dc6de2502ceebe38fa94fcf9850140e7ce1e5ef29d3cc02207da0e0b881594a9bc8750143dfa41ce8255e14f24784a551d3d1c4a2acecc0a2012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff36262f4b7717eca333432cd9af776bb5ef4b29a2ea1b1cf877b49642db945c62010000006b483045022100f074c81f476f50dad72d3d07cef668532bb2b0cc772b49abf67cafd476e4e41302201e36efd9eec72b2f5ff4eac4ffbbe0598c6185b63c6ba8e03737b708e73149940121022d7e055cd28a8b7ca2613687e9b5cd4ff4a959c54d74f49c12345d1d8f78b374ffffffff02c0c62d00000000001976a914fc9c507e2cf3563c63bf9ec7b38773c2a1e1c47288ac70383900000000001976a9145ab29618ded8892f8189ca3ce81bef83d3ddda1688ac000000000100000002d724e595476277be4337bb8f39ca700b4f9df1bfb84089c4afd338e1079e9add010000006b483045022100f775b297513593c1c6e461902ab6405c4c38ce3b37d9292fe074153b8c466c29022010ded748e9e7fb1fbb263b8f466e6a1352e05ddb8842a17f712478e3d9c177040121023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6affffffffff40fb739e2271f4aaa851dd46fcd1895ddd7a98850ef191ba3b50325c29a4ed010000006b4830450220686b1c5ecd7ea0e9078784f5ea0100035a962809fd1d0cf7a131604ecfb26f02022100ddf7b8874a375edfa4d0d7b93cfd214d0327e550add318f1a8a379cceae8dac601210363c3fa31a5453a29f6cde46c9d77698fd8276cf9f511dd6e5d079a231fea568effffffff02a01e3c00000000001976a914b0c1cda106bb5085bd9c0c9982773c7bd066fabc88acc0c62d00000000001976a914859819cb59368e07d4c95b5221fa4c466d66694988ac000000000100000002a9b95beed9491639bc0d1bb833005cf45429ef9a50505f9b91f3c7588feb87ef010000006c493046022100854bc0ee8b24e2b625798148fc505cb37464f72688456dc54b0c25c4dd564091022100c2863ab346c23157baaeb45e6d102e7354cc895ee0dd7b6ecdc77ab34bdd4d0f0121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff8eaaf0d722fe9deffbc6e9d543f406844c93d1dd1c073d739863c314d2adf4ef000000006a47304402203f28684b208f0f4bf87ca22544e59585a7807fcd5a2ec78fc93ce915e282335502201ab05402d3a2b2914dd955971fade92dc874e6441bc2383766ec8b4c56dca27501210251a3bd043afe5cf46a40c4ce4caf3e917190583588634711507d6ef77acc438bffffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac90ab1e00000000001976a914b27f37b7cee282e7890f4f6df9b49574f35e855288ac000000000100000002fadecb6a5b1bd5f0688fc7dd049dadd956c30006e4dc57155f22c054c1550791000000006b48304502201dcb7d73d180cda9ddb192e50fcf5f0efaa5e680931f2bc25e58dd368d4b815f0221008149257f9394b01188aa84f92aec7374339076b408360767236a3af18718cddc0121032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20fffffffff569ed0585b1d5261fe5a1839e99c23d0cd3b82972526c5bb5b812ceb493facc3010000006b48304502205665ae2983ad6ec44220810a6f4c28d77dd518cc891eb9ed67503a756e97c477022100ab456b8a9c1f977623956943d8f1892c3bf84d8adefaa405606d3473f37fb8b4012102bbdf0772bbacab8eaba47d783d30fa401b08a0ecc4bccd49357171ac38791c0effffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac504b1400000000001976a914a6a0900e3c77496dc68be8ee130a21b446b8266588ac0000000001000000023d9d0df887b3621c3c884515d1a4c0a22e2bc4aa02300493cb568189847265db010000006b483045022100af41bf6edc04de96ad8b0d0e0794a7055c9677f2616fcfc1b053f87ad5c60c0f02201ef5279534263776cca80957368791a362354d7a40f3f175874b909de2d7f9a10121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cffffffff70f6c965fcbae21ee712571b683b33e3b4d0e9c5d1fd685046db7176e3bf432e000000006b483045022033da8150f9870e045581f5894366f57345946174b43b7f8c0f9b24f7afad395c022100e3db87d42b1050ea8f2e964a13eeae86cc57e771c4dfa29f7f055c74a39be3b801210221f705f7d58ceea66122bcdc7220db0583d8ce1d7d948ed86007905268f55162ffffffff02d0ed2d00000000001976a9141882e6174c19c4a2ac6c7d807170e76cbc75160f88ac50802000000000001976a91447830d334d04acd62668904b6fab06a90742e75088ac0000000001000000022e48318fb557623da627d1c3f81ab34b99a87ce701440dfb907ad6a8691b51f2000000006c493046022100d2733fcc63dd86bc4653d268f16e467e87a7be9e1d3f45cbeccb2423b7eb1c6c022100e3963622c12dab3e9c0c76a8ef13151114cb0f17abe6c29cca2fcbac264dfc980121020ce8a0852e31812de6b8f2b2604d948cb06f8f7f404e70a19067cca01b5d0988ffffffff675f09c92aa029f3283ee9a6b8bd6f022a1ea3bdccb1d33a09416ee9389e3ecb000000006b48304502202beb8d4ff142762f12f867a1686c2a523c55ff336b8ae3992ae1292019afeaf1022100a2e7edb9ffb29628540fd02b21c84abf1cc48d70c9f6adb39550b8aff572c65a012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff02d0933c00000000001976a914449c3ac7336a78f0c6401f51710949005d2c7ffa88acc0c62d00000000001976a914636c549bf6035b27cf3823f5482911ebb2bce5d088ac00000000010000000233232e2ce65e394a2c7e46519fae48b9b711b5152f764a4d6454bfc0552f275a000000006c493046022100928f760eaabaed51bfc4db0188c84a6a19ef34a88786f2a25d8050c8356d858d022100c1a35c67f2c21b4837eaf73e195c74eb213bdaa4650fe77da072db9f84b90d0c0121022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3cfffffffff7fc20459ede0aeba4e9224ac667212ff815c651ca4feaaf40880b9f9d82413a010000006c493046022100c098dd6d9b20ed80de2d86d2c1bc9328b1c42f04b03c3767aec9d846d4538c9d0221009e32178215a499f22d8d3afe9f257159143c3d24f07371e0ef2de97d216e3b42012102078d4050a314870bd68960765015e5f884e35c60b44e23e0f2d264b73aaca477ffffffff0210fb3000000000001976a9141c5b740011cff8324ed10c3e8f63f6261f36613a88ac20cf2900000000001976a9147bdb65a92af2520836f77e5ebccc697d814149ce88ac000000000100000002dae9bc0142c15e33fe26a494d1233e80adf68b50a131f467eb13450caa56e43d000000006c493046022100ecf03f0bafb0cf6e08ac80336565bf79b6bac800f546e9f953fb14df7bf239ac022100982e27f2f0b3f8569cef126c0c54a88b002f00d570106c74f5c4b314c9609442012103b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662ffffffff6904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1000000006c493046022100febc4cdfbd5073ee756c9763b0e18009893b422e13c25e8f74ca97b84c0cf73f022100a85a6c10debf45e8ad00db28fce5fcb68404e9ac4b844f0ae1d59c0ef210d714012103dc9adee9c23ca7a091b4eafc4dfef2ed07adf903dae568f345095321aa9c57e2ffffffff02a03c3700000000001976a91467a341d7fe4de6a810c182ed27a09554e0b4405d88acc0c62d00000000001976a914f7f1f64a590896dccfb869ced060f058007f388b88ac00000000' }; diff --git a/test/data/blk86756-testnet.json b/test/data/blk86756-testnet.json index 0450b7c..e931cf2 100644 --- a/test/data/blk86756-testnet.json +++ b/test/data/blk86756-testnet.json @@ -1,6 +1,4 @@ { - "magicnum": 118034699, - "size": 8003, "header": { "version": 2, "prevHash": "4baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c00000000", From 1f454ef63117e7e60153392dde1c025b6895883c Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 16 Jan 2015 13:57:11 -0500 Subject: [PATCH 57/68] Removed devDependencies that can be defined in bitcore-build. --- package.json | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 42c4997..f5791c6 100644 --- a/package.json +++ b/package.json @@ -81,22 +81,10 @@ "sha512": "=0.0.1" }, "devDependencies": { - "brfs": "1.2.0", - "browserify": "~6.3.3", - "chai": "~1.10.0", - "closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git", - "gulp": "^3.8.10", - "bitcore-build": "^0.4.1", - "istanbul": "^0.3.5", - "jsdoc": "^3.3.0-alpha11", - "jsdoc-to-markdown": "=0.5.9", - "mocha": "~2.0.1", - "more-fs": "=0.5.0", - "plato": "^1.3.0", - "run-sequence": "^1.0.2", - "sinon": "^1.12.2", - "through2": "=0.6.3", - "zuul": "1.16.3" + "bitcore-build": "=0.4.2", + "brfs": "^1.2.0", + "chai": "^1.10.0", + "gulp": "^3.8.10" }, "license": "MIT" } From 453ad0f311d748ec65e6fd09a61f111064cd0615 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Sat, 17 Jan 2015 01:58:12 -0500 Subject: [PATCH 58/68] Fix jshint complaints. --- test/block.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/block.js b/test/block.js index b2f09b7..056a0d5 100644 --- a/test/block.js +++ b/test/block.js @@ -20,10 +20,8 @@ var dataBlocks = require('./data/bitcoind/blocks'); describe('Block', function() { - var magicnum = data.magicnum; var blockhex = data.blockhex; var blockbuf = new Buffer(blockhex, 'hex'); - var size = data.blocksize; var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex')); var txs = []; JSON.parse(dataJson).transactions.forEach(function(tx){ From 1e21184ec389dbc808a13befc411a44302f8fffe Mon Sep 17 00:00:00 2001 From: himynameismartin Date: Sat, 17 Jan 2015 17:55:21 +0100 Subject: [PATCH 59/68] Added JavaScript syntax highlighting --- docs/guide/index.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 18e4dc0..62812f7 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -42,24 +42,27 @@ To get started, just `npm install bitcore` or `bower install bitcore`. ## Create a Private Key -``` +```javascript var privKey = new bitcore.PrivateKey(); ``` ## Create an Address -``` + +```javascript var privKey = new bitcore.PrivateKey(); var address = privKey.toAddress(); ``` ## Create a Multisig Address -``` + +```javascript // Build a 2-of-3 address from public keys var P2SHAddress = new bitcore.Address([publicKey1, publicKey2, publicKey3], 2); ``` ## Request a Payment -``` + +```javascript var paymentInfo = { address: '1DNtTk4PUCGAdiNETAzQFWZiy2fCHtGnPx', amount: 120000 //satoshis @@ -68,7 +71,8 @@ var uri = new bitcore.URI(paymentInfo).toString(); ``` ## Create a Transaction -``` + +```javascript var transaction = new Transaction() .from(utxos) // Feed information about what unspent outputs one can use .to(address, amount) // Add an output with the given amount of satoshis @@ -77,7 +81,8 @@ var transaction = new Transaction() ``` ## Connect to the Network -``` + +```javascript var peer = new Peer('5.9.85.34'); peer.on('inv', function(message) { From ae80f2825267cc9f92e1e72089c12b9f6475f8c3 Mon Sep 17 00:00:00 2001 From: himynameismartin Date: Sun, 18 Jan 2015 11:29:23 +0100 Subject: [PATCH 60/68] Added JavaScript syntax highlighting --- docs/api/index.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/api/index.md b/docs/api/index.md index 122b3c5..1988787 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -5,24 +5,27 @@ description: Sample code for the most common task in any bitcoin application. ## Create a Private Key -``` +```javascript var privKey = new bitcore.PrivateKey(); ``` ## Create an Address -``` + +```javascript var privKey = new bitcore.PrivateKey(); var address = privKey.toAddress(); ``` ## Create a Multisig Address -``` + +```javascript // Build a 2-of-3 address from public keys var P2SHAddress = new bitcore.Address([publicKey1, publicKey2, publicKey3], 2); ``` ## Request a Payment -``` + +```javascript var paymentInfo = { address: '1DNtTk4PUCGAdiNETAzQFWZiy2fCHtGnPx', amount: 120000 //satoshis @@ -31,7 +34,8 @@ var uri = new bitcore.URI(paymentInfo).toString(); ``` ## Create a Transaction -``` + +```javascript var transaction = new Transaction() .from(utxos) // Feed information about what unspend outputs one can use .to(address, amount) // Add an output with the given amount of satoshis @@ -40,7 +44,8 @@ var transaction = new Transaction() ``` ## Connect to the Network -``` + +```javascript var peer = new Peer('5.9.85.34'); peer.on('inv', function(message) { From 59a6c926d710b3c7f5684590a3abbe236e23efb0 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Sun, 18 Jan 2015 10:41:54 -0500 Subject: [PATCH 61/68] Returned jsdoc for info.header, and removed nolonger used opts argument --- lib/block.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/block.js b/lib/block.js index e158b4c..81248ff 100644 --- a/lib/block.js +++ b/lib/block.js @@ -43,6 +43,10 @@ Block._from = function _from(arg) { info = Block._fromJSON(arg); } else if (_.isObject(arg)) { info = { + /** + * @name Block#header + * @type {BlockHeader} + */ header: arg.header, /** * @name Block#transactions @@ -105,8 +109,8 @@ Block._fromBufferReader = function _fromBufferReader(br) { * @param {BufferReader} - A buffer reader of the block * @returns {Block} - An instance of block */ -Block.fromBufferReader = function fromBufferReader(br, opts) { - var info = Block._fromBufferReader(br, opts); +Block.fromBufferReader = function fromBufferReader(br) { + var info = Block._fromBufferReader(br); return new Block(info); }; @@ -114,8 +118,8 @@ Block.fromBufferReader = function fromBufferReader(br, opts) { * @param {Buffer} - A buffer of the block * @returns {Block} - An instance of block */ -Block.fromBuffer = function fromBuffer(buf, opts) { - return Block.fromBufferReader(BufferReader(buf), opts); +Block.fromBuffer = function fromBuffer(buf) { + return Block.fromBufferReader(BufferReader(buf)); }; /** From 2b3ce4de123f9abfc5fabed321078a775cf7488b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 19 Jan 2015 18:02:26 -0300 Subject: [PATCH 62/68] adds a test and small fix for transaction --- lib/transaction/transaction.js | 4 ++-- test/transaction/transaction.js | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index a22114f..45ed523 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -249,7 +249,7 @@ Transaction.prototype.toObject = function toObject() { Transaction.prototype.fromObject = function(transaction) { var self = this; _.each(transaction.inputs, function(input) { - if (input.output.script) { + if (input.output && input.output.script) { input.output.script = new Script(input.output.script); if (input.output.script.isPublicKeyHashOut()) { self.addInput(new Input.PublicKeyHash(input)); @@ -261,7 +261,7 @@ Transaction.prototype.fromObject = function(transaction) { return; } } - self.addInput(new Input(input)); + self.uncheckedAddInput(new Input(input)); }); _.each(transaction.outputs, function(output) { self.addOutput(new Output(output)); diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 2f53350..099eb1f 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -148,7 +148,9 @@ describe('Transaction', function() { it('fails when Inputs are not subclassed and verifySignature is called', function() { var tx = new Transaction(tx_1_hex); expect(function() { - return tx.isValidSignature({inputIndex: 0}); + return tx.isValidSignature({ + inputIndex: 0 + }); }).to.throw(errors.Transaction.UnableToVerifySignature); }); }); @@ -236,8 +238,12 @@ describe('Transaction', function() { var transaction = new Transaction() .from(simpleUtxoWith1BTC) .to(fromAddress, 1); - expect(function() { return transaction.serialize(); }).to.throw(); - expect(function() { return transaction.serialize(true); }).to.not.throw(); + expect(function() { + return transaction.serialize(); + }).to.throw(); + expect(function() { + return transaction.serialize(true); + }).to.not.throw(); }); }); @@ -281,6 +287,14 @@ describe('Transaction', function() { transaction.change(changeAddress); expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString()); }); + it('serializes correctly p2sh multisig signed tx', function() { + var t = new Transaction(tx_2_hex); + expect(t.toString()).to.equal(tx_2_hex); + var r = new Transaction(t); + expect(r.toString()).to.equal(tx_2_hex); + var j = new Transaction(t.toObject()); + expect(j.toString()).to.equal(tx_2_hex); + }); }); describe('serialization of inputs', function() { @@ -313,3 +327,6 @@ var tx_empty_hex = '01000000000000000000'; /* jshint maxlen: 1000 */ var tx_1_hex = '01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a473044022013fa3089327b50263029265572ae1b022a91d10ac80eb4f32f291c914533670b02200d8a5ed5f62634a7e1a0dc9188a3cc460a986267ae4d58faf50c79105431327501210223078d2942df62c45621d209fab84ea9a7a23346201b7727b9b45a29c4e76f5effffffff0150690f00000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000'; var tx_1_id = '779a3e5b3c2c452c85333d8521f804c1a52800e60f4b7c3bbe36f4bab350b72c'; + + +var tx_2_hex = '0100000001e07d8090f4d4e6fcba6a2819e805805517eb19e669e9d2f856b41d4277953d640000000091004730440220248bc60bb309dd0215fbde830b6371e3fdc55685d11daa9a3c43828892e26ce202205f10cd4011f3a43657260a211f6c4d1fa81b6b6bdd6577263ed097cc22f4e5b50147522102fa38420cec94843ba963684b771ba3ca7ce1728dc2c7e7cade0bf298324d6b942103f948a83c20b2e7228ca9f3b71a96c2f079d9c32164cd07f08fbfdb483427d2ee52aeffffffff01180fe200000000001976a914ccee7ce8e8b91ec0bc23e1cfb6324461429e6b0488ac00000000'; From d862506fedd9649b195d0eea3542fd0eb80b7468 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 19 Jan 2015 18:27:35 -0300 Subject: [PATCH 63/68] fix code style --- test/transaction/transaction.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 099eb1f..cb8938c 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -288,12 +288,12 @@ describe('Transaction', function() { expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString()); }); it('serializes correctly p2sh multisig signed tx', function() { - var t = new Transaction(tx_2_hex); - expect(t.toString()).to.equal(tx_2_hex); + var t = new Transaction(tx2hex); + expect(t.toString()).to.equal(tx2hex); var r = new Transaction(t); - expect(r.toString()).to.equal(tx_2_hex); + expect(r.toString()).to.equal(tx2hex); var j = new Transaction(t.toObject()); - expect(j.toString()).to.equal(tx_2_hex); + expect(j.toString()).to.equal(tx2hex); }); }); @@ -329,4 +329,4 @@ var tx_1_hex = '01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267 var tx_1_id = '779a3e5b3c2c452c85333d8521f804c1a52800e60f4b7c3bbe36f4bab350b72c'; -var tx_2_hex = '0100000001e07d8090f4d4e6fcba6a2819e805805517eb19e669e9d2f856b41d4277953d640000000091004730440220248bc60bb309dd0215fbde830b6371e3fdc55685d11daa9a3c43828892e26ce202205f10cd4011f3a43657260a211f6c4d1fa81b6b6bdd6577263ed097cc22f4e5b50147522102fa38420cec94843ba963684b771ba3ca7ce1728dc2c7e7cade0bf298324d6b942103f948a83c20b2e7228ca9f3b71a96c2f079d9c32164cd07f08fbfdb483427d2ee52aeffffffff01180fe200000000001976a914ccee7ce8e8b91ec0bc23e1cfb6324461429e6b0488ac00000000'; +var tx2hex = '0100000001e07d8090f4d4e6fcba6a2819e805805517eb19e669e9d2f856b41d4277953d640000000091004730440220248bc60bb309dd0215fbde830b6371e3fdc55685d11daa9a3c43828892e26ce202205f10cd4011f3a43657260a211f6c4d1fa81b6b6bdd6577263ed097cc22f4e5b50147522102fa38420cec94843ba963684b771ba3ca7ce1728dc2c7e7cade0bf298324d6b942103f948a83c20b2e7228ca9f3b71a96c2f079d9c32164cd07f08fbfdb483427d2ee52aeffffffff01180fe200000000001976a914ccee7ce8e8b91ec0bc23e1cfb6324461429e6b0488ac00000000'; From 05c7c5dd65d4bbd636c53efc3a67fc1c5afd8883 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 20 Jan 2015 15:56:39 -0500 Subject: [PATCH 64/68] Update documentation with changes based on the seperation of modules. --- docs/guide/index.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 62812f7..d3853a2 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -1,4 +1,4 @@ -# Bitcore v0.8 +# Bitcore v0.9 ## Principles @@ -11,26 +11,19 @@ To get started, just `npm install bitcore` or `bower install bitcore`. ## Addresses and Key Management * [Addresses](address.md) -* [Using different networks](networks.md) +* [Using Different Networks](networks.md) * [Private Keys](privatekey.md) and [Public Keys](publickey.md) * [Hierarchically-derived Private and Public Keys](hierarchical.md) -## Payment handling -* [Using different Units](unit.md) -* [Acknowledging and Requesting payments: Bitcoin URIs](uri.md) -* [Payment Protocol Support](paymentprotocol.md) +## Payment Handling +* [Using Different Units](unit.md) +* [Acknowledging and Requesting Payments: Bitcoin URIs](uri.md) * [The Transaction Class](transaction.md) -## Bitcoin internals +## Bitcoin Internals * [Scripts](script.md) * [Block](block.md) -## Networking -* [Interface to the Bitcoin P2P network](peer.md) -* [Managing a pool of peers](pool.md) -* [Connecting to a bitcoind instance through JSON-RPC](jsonrpc.md) -* [Connecting to a Insight instance to retrieve informetion](insight.md) - ## Extra * [Crypto](crypto.md) * [Encoding](encoding.md) @@ -38,6 +31,18 @@ To get started, just `npm install bitcore` or `bower install bitcore`. ## Module Development * [Browser Builds](browser.md) +## Modules + +Some functionality is implemented as a module that can be installed seperately: + +* [Payment Protocol Support](https://github.com/bitpay/bitcore-payment-protocol) +* [Peer to Peer Networking](https://github.com/bitpay/bitcore-payment-protocol) +* [Bitcoin Core JSON-RPC](https://github.com/bitpay/bitcoind-rpc) +* [Payment Channels](https://github.com/bitpay/bitcore-channel) +* [Mnemonics](https://github.com/bitpay/bitcore-mnemonic) +* [Elliptical Curve Integrated Encryption Scheme](https://github.com/bitpay/bitcore-ecies) +* [Blockchain Explorers](https://github.com/bitpay/bitcore-explorers) + # Examples ## Create a Private Key From 86819a8f6d433b4f6e50547133504e0a7906b50a Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 19 Jan 2015 16:57:48 -0500 Subject: [PATCH 65/68] Moved documentation from docs/guide to docs directory, in preparation for combined submodule documentation. --- docs/README.md | 4 --- docs/{guide => }/address.md | 0 docs/api/index.md | 56 ------------------------------- docs/{guide => }/block.md | 0 docs/{guide => }/browser.md | 0 docs/{guide => }/crypto.md | 0 docs/{guide => }/encoding.md | 0 docs/{guide => }/hierarchical.md | 0 docs/{guide => }/index.md | 0 docs/{guide => }/networks.md | 0 docs/{guide => }/privatekey.md | 0 docs/{guide => }/publickey.md | 0 docs/{guide => }/script.md | 0 docs/{guide => }/transaction.md | 0 docs/{guide => }/unit.md | 0 docs/{guide => }/unspentoutput.md | 0 docs/{guide => }/uri.md | 0 17 files changed, 60 deletions(-) delete mode 100644 docs/README.md rename docs/{guide => }/address.md (100%) delete mode 100644 docs/api/index.md rename docs/{guide => }/block.md (100%) rename docs/{guide => }/browser.md (100%) rename docs/{guide => }/crypto.md (100%) rename docs/{guide => }/encoding.md (100%) rename docs/{guide => }/hierarchical.md (100%) rename docs/{guide => }/index.md (100%) rename docs/{guide => }/networks.md (100%) rename docs/{guide => }/privatekey.md (100%) rename docs/{guide => }/publickey.md (100%) rename docs/{guide => }/script.md (100%) rename docs/{guide => }/transaction.md (100%) rename docs/{guide => }/unit.md (100%) rename docs/{guide => }/unspentoutput.md (100%) rename docs/{guide => }/uri.md (100%) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 297420d..0000000 --- a/docs/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Bitcore API Reference -======= - -This site contains the reference docs for the bitcore library. diff --git a/docs/guide/address.md b/docs/address.md similarity index 100% rename from docs/guide/address.md rename to docs/address.md diff --git a/docs/api/index.md b/docs/api/index.md deleted file mode 100644 index 1988787..0000000 --- a/docs/api/index.md +++ /dev/null @@ -1,56 +0,0 @@ -title: Bitcore Examples -description: Sample code for the most common task in any bitcoin application. ---- -# Examples - -## Create a Private Key - -```javascript -var privKey = new bitcore.PrivateKey(); -``` - -## Create an Address - -```javascript -var privKey = new bitcore.PrivateKey(); -var address = privKey.toAddress(); -``` - -## Create a Multisig Address - -```javascript -// Build a 2-of-3 address from public keys -var P2SHAddress = new bitcore.Address([publicKey1, publicKey2, publicKey3], 2); -``` - -## Request a Payment - -```javascript -var paymentInfo = { - address: '1DNtTk4PUCGAdiNETAzQFWZiy2fCHtGnPx', - amount: 120000 //satoshis -}; -var uri = new bitcore.URI(paymentInfo).toString(); -``` - -## Create a Transaction - -```javascript -var transaction = new Transaction() - .from(utxos) // Feed information about what unspend outputs one can use - .to(address, amount) // Add an output with the given amount of satoshis - .change(address) // Sets up a change address where the rest of the funds will go - .sign(privkeySet) // Signs all the inputs it can -``` - -## Connect to the Network - -```javascript -var peer = new Peer('5.9.85.34'); - -peer.on('inv', function(message) { - // new invetory -}); - -peer.connect(); -``` diff --git a/docs/guide/block.md b/docs/block.md similarity index 100% rename from docs/guide/block.md rename to docs/block.md diff --git a/docs/guide/browser.md b/docs/browser.md similarity index 100% rename from docs/guide/browser.md rename to docs/browser.md diff --git a/docs/guide/crypto.md b/docs/crypto.md similarity index 100% rename from docs/guide/crypto.md rename to docs/crypto.md diff --git a/docs/guide/encoding.md b/docs/encoding.md similarity index 100% rename from docs/guide/encoding.md rename to docs/encoding.md diff --git a/docs/guide/hierarchical.md b/docs/hierarchical.md similarity index 100% rename from docs/guide/hierarchical.md rename to docs/hierarchical.md diff --git a/docs/guide/index.md b/docs/index.md similarity index 100% rename from docs/guide/index.md rename to docs/index.md diff --git a/docs/guide/networks.md b/docs/networks.md similarity index 100% rename from docs/guide/networks.md rename to docs/networks.md diff --git a/docs/guide/privatekey.md b/docs/privatekey.md similarity index 100% rename from docs/guide/privatekey.md rename to docs/privatekey.md diff --git a/docs/guide/publickey.md b/docs/publickey.md similarity index 100% rename from docs/guide/publickey.md rename to docs/publickey.md diff --git a/docs/guide/script.md b/docs/script.md similarity index 100% rename from docs/guide/script.md rename to docs/script.md diff --git a/docs/guide/transaction.md b/docs/transaction.md similarity index 100% rename from docs/guide/transaction.md rename to docs/transaction.md diff --git a/docs/guide/unit.md b/docs/unit.md similarity index 100% rename from docs/guide/unit.md rename to docs/unit.md diff --git a/docs/guide/unspentoutput.md b/docs/unspentoutput.md similarity index 100% rename from docs/guide/unspentoutput.md rename to docs/unspentoutput.md diff --git a/docs/guide/uri.md b/docs/uri.md similarity index 100% rename from docs/guide/uri.md rename to docs/uri.md From a81546e631aebf0f25c71f576b006c41fe0427bb Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 20 Jan 2015 17:27:20 -0500 Subject: [PATCH 66/68] Fixed formatting issue with yaml in docs. --- docs/address.md | 1 + docs/block.md | 1 + docs/browser.md | 1 + docs/crypto.md | 1 + docs/encoding.md | 1 + docs/hierarchical.md | 1 + docs/networks.md | 1 + docs/privatekey.md | 1 + docs/publickey.md | 1 + docs/script.md | 1 + docs/transaction.md | 1 + docs/unit.md | 1 + docs/unspentoutput.md | 1 + docs/uri.md | 1 + 14 files changed, 14 insertions(+) diff --git a/docs/address.md b/docs/address.md index 9718790..fb1d942 100644 --- a/docs/address.md +++ b/docs/address.md @@ -1,3 +1,4 @@ +--- title: Address description: A simple interface to generate and validate a bitcoin address. --- diff --git a/docs/block.md b/docs/block.md index 2bcec98..dfe5859 100644 --- a/docs/block.md +++ b/docs/block.md @@ -1,3 +1,4 @@ +--- title: Block description: A simple interface to parse and validate a bitcoin blocks. --- diff --git a/docs/browser.md b/docs/browser.md index 59d9d50..9db540a 100644 --- a/docs/browser.md +++ b/docs/browser.md @@ -1,3 +1,4 @@ +--- title: Browser Builds description: Guide to writing modules and optimizing browser bundles. --- diff --git a/docs/crypto.md b/docs/crypto.md index 14925e7..9e872ef 100644 --- a/docs/crypto.md +++ b/docs/crypto.md @@ -1,3 +1,4 @@ +--- title: Crypto description: Primitives and tools to deal with bitcoin cryptography. --- diff --git a/docs/encoding.md b/docs/encoding.md index a2d0d00..e58ff01 100644 --- a/docs/encoding.md +++ b/docs/encoding.md @@ -1,3 +1,4 @@ +--- title: Encoding description: Utilities for encoding information in bitcoin standard formats. --- diff --git a/docs/hierarchical.md b/docs/hierarchical.md index fa62370..9c0ebd8 100644 --- a/docs/hierarchical.md +++ b/docs/hierarchical.md @@ -1,3 +1,4 @@ +--- title: HDKeys description: Lets you create and derive extended public and private keys according to the BIP32 standard for Hierarchical Deterministic (HD) keys. --- diff --git a/docs/networks.md b/docs/networks.md index 905d805..bada23c 100644 --- a/docs/networks.md +++ b/docs/networks.md @@ -1,3 +1,4 @@ +--- title: Networks description: A simple interface to handle livenet and testnet bitcoin networks. --- diff --git a/docs/privatekey.md b/docs/privatekey.md index d8cdfe0..3b52b0e 100644 --- a/docs/privatekey.md +++ b/docs/privatekey.md @@ -1,3 +1,4 @@ +--- title: Private Key description: A simple interface to generate, import and handle private keys. --- diff --git a/docs/publickey.md b/docs/publickey.md index 983120f..03f43db 100644 --- a/docs/publickey.md +++ b/docs/publickey.md @@ -1,3 +1,4 @@ +--- title: Public Key description: A simple interface for handling private keys. --- diff --git a/docs/script.md b/docs/script.md index 5c6facd..c7929c1 100644 --- a/docs/script.md +++ b/docs/script.md @@ -1,3 +1,4 @@ +--- title: Script description: A powerful interface to create, parse and validate bitcoin scripts. --- diff --git a/docs/transaction.md b/docs/transaction.md index a655ff5..ed3ba50 100644 --- a/docs/transaction.md +++ b/docs/transaction.md @@ -1,3 +1,4 @@ +--- title: Transaction description: A robust interface to create, parse and validate bitcoin transactions. --- diff --git a/docs/unit.md b/docs/unit.md index d13c2ef..dd03c89 100644 --- a/docs/unit.md +++ b/docs/unit.md @@ -1,3 +1,4 @@ +--- title: Bitcoin Units description: Utility to easily convert between bitcoin units. --- diff --git a/docs/unspentoutput.md b/docs/unspentoutput.md index 20b9b05..ec605d1 100644 --- a/docs/unspentoutput.md +++ b/docs/unspentoutput.md @@ -1,3 +1,4 @@ +--- title: UnspentOutput description: A stateless model to represent an unspent output and associated information. --- diff --git a/docs/uri.md b/docs/uri.md index e679e12..5b9d57b 100644 --- a/docs/uri.md +++ b/docs/uri.md @@ -1,3 +1,4 @@ +--- title: Bitcoin URIs description: Utility to parse and create standard bitcoin URIs. --- From 78b81673ae0c2ec3bbfc1d7a6c8cec606ec6a159 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 21 Jan 2015 09:00:01 -0500 Subject: [PATCH 67/68] Fixed submodule link --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index d3853a2..6f41d23 100644 --- a/docs/index.md +++ b/docs/index.md @@ -36,7 +36,7 @@ To get started, just `npm install bitcore` or `bower install bitcore`. Some functionality is implemented as a module that can be installed seperately: * [Payment Protocol Support](https://github.com/bitpay/bitcore-payment-protocol) -* [Peer to Peer Networking](https://github.com/bitpay/bitcore-payment-protocol) +* [Peer to Peer Networking](https://github.com/bitpay/bitcore-p2p) * [Bitcoin Core JSON-RPC](https://github.com/bitpay/bitcoind-rpc) * [Payment Channels](https://github.com/bitpay/bitcore-channel) * [Mnemonics](https://github.com/bitpay/bitcore-mnemonic) From bdfdfebc7fc5cdbcdd94ca98bd978d0814b8a59b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 21 Jan 2015 15:46:39 -0300 Subject: [PATCH 68/68] update builder version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5791c6..7dc9161 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "sha512": "=0.0.1" }, "devDependencies": { - "bitcore-build": "=0.4.2", + "bitcore-build": "^0.5.0", "brfs": "^1.2.0", "chai": "^1.10.0", "gulp": "^3.8.10"