├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── binding.gyp ├── include ├── addon.h └── x509.h ├── index.js ├── package.json ├── src ├── addon.cc └── x509.cc └── test ├── CA_chains └── enduser-example.com.chain ├── certs ├── acaline.com.crt ├── enduser-example.com.crt ├── equifax.crt ├── github.com.crt ├── google.com.crt ├── nodejitsu.com.crt ├── npmjs.org.crt ├── pushpinplanner.com.crt ├── travis-ci.org.crt ├── twitter.com.crt ├── wikipedia.org.crt └── yahoo.com.crt └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules 3 | build 4 | *.log 5 | *.DS_Store 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | addons: 5 | apt: 6 | sources: 7 | - ubuntu-toolchain-r-test 8 | packages: 9 | - g++-4.8 10 | 11 | language: node_js 12 | node_js: 13 | - "stable" 14 | - "4.0" 15 | - "0.12" 16 | - "0.10" 17 | 18 | install: 19 | - export CXX=g++-4.8 20 | - $CXX --version 21 | - npm i 22 | 23 | before_install: 24 | - npm install -g node-gyp 25 | - rm -rf ~/.node-gyp/ 26 | 27 | notifications: 28 | email: false 29 | 30 | sudo: false 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-x509 2 | ========= 3 | 4 | [![Build Status](https://travis-ci.org/Southern/node-x509.svg?branch=master)](https://travis-ci.org/Southern/node-x509) 5 | 6 | Simple X509 certificate parser. 7 | 8 | ## Installation 9 | 10 | From NPM *(recommended)*: `npm install x509` 11 | 12 | Building and testing from source: 13 | ``` 14 | sudo npm install -g node-gyp 15 | npm install 16 | npm test 17 | ``` 18 | 19 | ## Usage 20 | Reading from a file: 21 | ```js 22 | const x509 = require('x509'); 23 | var issuer = x509.getIssuer(__dirname + '/certs/your.crt'); 24 | ``` 25 | 26 | Reading from a string: 27 | ```js 28 | const fs = require('fs'), 29 | x509 = require('x509'); 30 | var issuer = x509.getIssuer(fs.readFileSync('./certs/your.crt').toString()); 31 | ``` 32 | 33 | ## Methods 34 | **Notes:** 35 | - `cert` may be a filename or a raw base64 encoded PEM string in any of these methods. 36 | 37 | #### x509.getAltNames(`cert`) 38 | Parse certificate with `x509.parseCert` and return the alternate names. 39 | 40 | ```js 41 | const x509 = require('x509'); 42 | var altNames = x509.getAltNames(__dirname + '/certs/nodejitsu.com.crt'); 43 | /* 44 | altNames = [ '*.nodejitsu.com', 'nodejitsu.com' ] 45 | */ 46 | ``` 47 | 48 | #### x509.getIssuer(`cert`) 49 | Parse certificate with `x509.parseCert` and return the issuer. 50 | 51 | ```js 52 | const x509 = require('x509'); 53 | var issuer = x509.getIssuer(__dirname + '/certs/nodejitsu.com.crt'); 54 | /* 55 | issuer = { countryName: 'GB', 56 | stateOrProvinceName: 'Greater Manchester', 57 | localityName: 'Salford', 58 | organizationName: 'COMODO CA Limited', 59 | commonName: 'COMODO High-Assurance Secure Server CA' } 60 | */ 61 | ``` 62 | 63 | #### x509.getSubject(`cert`) 64 | Parse certificate with `x509.parseCert` and return the subject. 65 | 66 | ```js 67 | const x509 = require('x509'); 68 | var subject = x509.getSubject(__dirname + '/certs/nodejitsu.com.crt'); 69 | /* 70 | subject = { countryName: 'US', 71 | postalCode: '10010', 72 | stateOrProvinceName: 'NY', 73 | localityName: 'New York', 74 | streetAddress: '902 Broadway, 4th Floor', 75 | organizationName: 'Nodejitsu', 76 | organizationalUnitName: 'PremiumSSL Wildcard', 77 | commonName: '*.nodejitsu.com' } 78 | */ 79 | ``` 80 | 81 | #### x509.parseCert(`cert`) 82 | Parse subject, issuer, valid before and after date, and alternate names from certificate. 83 | 84 | ```js 85 | const x509 = require('x509'); 86 | var cert = x509.parseCert(__dirname + '/certs/nodejitsu.com.crt'); 87 | /* 88 | cert = { subject: 89 | { countryName: 'US', 90 | postalCode: '10010', 91 | stateOrProvinceName: 'NY', 92 | localityName: 'New York', 93 | streetAddress: '902 Broadway, 4th Floor', 94 | organizationName: 'Nodejitsu', 95 | organizationalUnitName: 'PremiumSSL Wildcard', 96 | commonName: '*.nodejitsu.com' }, 97 | issuer: 98 | { countryName: 'GB', 99 | stateOrProvinceName: 'Greater Manchester', 100 | localityName: 'Salford', 101 | organizationName: 'COMODO CA Limited', 102 | commonName: 'COMODO High-Assurance Secure Server CA' }, 103 | notBefore: Sun Oct 28 2012 20:00:00 GMT-0400 (EDT), 104 | notAfter: Wed Nov 26 2014 18:59:59 GMT-0500 (EST), 105 | altNames: [ '*.nodejitsu.com', 'nodejitsu.com' ], 106 | signatureAlgorithm: 'sha1WithRSAEncryption', 107 | fingerPrint: 'E4:7E:24:8E:86:D2:BE:55:C0:4D:41:A1:C2:0E:06:96:56:B9:8E:EC', 108 | publicKey: { 109 | algorithm: 'rsaEncryption', 110 | e: '65537', 111 | n: '.......' } } 112 | */ 113 | ``` 114 | 115 | 116 | #### x509.verify(`cert`, `CABundlePath`, function(err, result){ /*...*/}) 117 | 118 | Performs basic certificate validation against a bundle of ca certificates. 119 | 120 | It accepts an error-first callback as first argument. If the error is null, then 121 | the certificate is valid. 122 | 123 | The error messages are the same returned by openssl: [x509_verify_cert_error_string](https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_get_error.html) 124 | 125 | 126 | **Note:** 127 | As now, this function only accepts absolute paths to existing files as arguments 128 | 129 | ```js 130 | const x509 = require('x509'); 131 | 132 | x509.verify( 133 | __dirname + '/certs/user.com.crt', 134 | __dirname + 'enduser-example.com.chain', 135 | function(err, result){ /*...*/} 136 | ); 137 | 138 | ``` 139 | 140 | ## Examples 141 | Checking the date to make sure the certificate is active: 142 | ```js 143 | const x509 = require('x509'); 144 | var cert = x509.parseCert('yourcert.crt'), 145 | date = new Date(); 146 | 147 | if (cert.notBefore > date) { 148 | // Certificate isn't active yet. 149 | } 150 | if (cert.notAfter < date) { 151 | // Certificate has expired. 152 | } 153 | ``` 154 | 155 | ## License 156 | 157 | MIT 158 | 159 | #### Alternative implementation / build issues 160 | If you are suffering from hard to fix build issues, there is an alternative (pure javascript) implementation using emscripten: https://github.com/encharm/x509.js (based on node-x509, slightly different API) 161 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'target_defaults': { 3 | 'variables': { 4 | 'version': ' 5 | #include 6 | 7 | using namespace v8; 8 | 9 | void init(Local exports); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/x509.h: -------------------------------------------------------------------------------- 1 | #ifndef __x509_h 2 | #define __x509_h 3 | 4 | // Include header for addon version, node/v8 inclusions, etc. 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // OpenSSL headers 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace v8; 21 | 22 | NAN_METHOD(get_altnames); 23 | NAN_METHOD(get_subject); 24 | NAN_METHOD(get_issuer); 25 | NAN_METHOD(parse_cert); 26 | NAN_METHOD(verify); 27 | 28 | Local try_parse(const std::string& dataString); 29 | Local verify(const std::string& dataString); 30 | Local parse_date(ASN1_TIME *date); 31 | Local parse_serial(ASN1_INTEGER *serial); 32 | Local parse_name(X509_NAME *subject); 33 | 34 | char* real_name(char *data); 35 | char* trim(char *data, int len); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var x509 = require('./build/Release/x509'); 2 | var fs = require('fs'); 3 | 4 | exports.version = x509.version; 5 | exports.getAltNames = x509.getAltNames; 6 | exports.getSubject = x509.getSubject; 7 | exports.getIssuer = x509.getIssuer; 8 | 9 | exports.verify = function(certPath, CABundlePath, cb) { 10 | if (!certPath) { 11 | throw new TypeError('Certificate path is required'); 12 | } 13 | if (!CABundlePath) { 14 | throw new TypeError('CA Bundle path is required'); 15 | } 16 | 17 | fs.stat(certPath, function(certPathErr) { 18 | 19 | if (certPathErr) { 20 | return cb(certPathErr); 21 | } 22 | 23 | fs.stat(CABundlePath, function(bundlePathErr) { 24 | 25 | if (bundlePathErr) { 26 | return cb(bundlePathErr); 27 | } 28 | 29 | try { 30 | x509.verify(certPath, CABundlePath); 31 | cb(null); 32 | } 33 | catch (verificationError) { 34 | cb(verificationError); 35 | } 36 | }); 37 | }); 38 | }; 39 | 40 | 41 | exports.parseCert = function(path) { 42 | var ret = x509.parseCert(path); 43 | var exts = {}; 44 | for (var key in ret.extensions) { 45 | var newkey = key.replace('X509v3', '').replace(/ /g, ''); 46 | newkey = newkey.slice(0, 1).toLowerCase() + newkey.slice(1); 47 | exts[newkey] = ret.extensions[key]; 48 | } 49 | delete ret.extensions; 50 | ret.extensions = exts; 51 | return ret; 52 | }; 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x509", 3 | "version": "0.3.4", 4 | "description": "Simple X509 certificate parser.", 5 | "author": "Colton Baker", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Southern/node-x509.git" 10 | }, 11 | "scripts": { 12 | "test": "node test/test" 13 | }, 14 | "license": "MIT", 15 | "dependencies": { 16 | "nan": "2.12.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/addon.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace v8; 8 | 9 | void init(Local exports) { 10 | Nan::Set(exports, 11 | Nan::New("version").ToLocalChecked(), 12 | Nan::New(VERSION).ToLocalChecked()); 13 | 14 | Nan::Set(exports, 15 | Nan::New("verify").ToLocalChecked(), 16 | Nan::New(verify)->GetFunction()); 17 | 18 | Nan::Set(exports, 19 | Nan::New("getAltNames").ToLocalChecked(), 20 | Nan::New(get_altnames)->GetFunction()); 21 | Nan::Set(exports, 22 | Nan::New("getSubject").ToLocalChecked(), 23 | Nan::New(get_subject)->GetFunction()); 24 | Nan::Set(exports, 25 | Nan::New("getIssuer").ToLocalChecked(), 26 | Nan::New(get_issuer)->GetFunction()); 27 | Nan::Set(exports, 28 | Nan::New("parseCert").ToLocalChecked(), 29 | Nan::New(parse_cert)->GetFunction()); 30 | } 31 | 32 | NODE_MODULE(x509, init) 33 | -------------------------------------------------------------------------------- /src/x509.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace v8; 6 | 7 | // Field names that OpenSSL is missing. 8 | static const char *MISSING[4][2] = { 9 | { 10 | "1.2.840.113533.7.65.0", 11 | "entrustVersionInfo" 12 | }, 13 | 14 | { 15 | "1.3.6.1.4.1.311.60.2.1.1", 16 | "jurisdictionOfIncorpationLocalityName" 17 | }, 18 | 19 | { 20 | "1.3.6.1.4.1.311.60.2.1.2", 21 | "jurisdictionOfIncorporationStateOrProvinceName" 22 | }, 23 | 24 | { 25 | "1.3.6.1.4.1.311.60.2.1.3", 26 | "jurisdictionOfIncorporationCountryName" 27 | } 28 | }; 29 | 30 | std::string parse_args(const Nan::FunctionCallbackInfo& info) { 31 | if (info.Length() == 0) { 32 | Nan::ThrowTypeError("Must provide a certificate string."); 33 | return std::string(); 34 | } 35 | 36 | if (!info[0]->IsString()) { 37 | Nan::ThrowTypeError("Certificate must be a string."); 38 | return std::string(); 39 | } 40 | 41 | if (info[0]->ToString()->Length() == 0) { 42 | Nan::ThrowTypeError("Certificate argument provided, but left blank."); 43 | return std::string(); 44 | } 45 | 46 | return *Nan::Utf8String(info[0]->ToString()); 47 | } 48 | 49 | 50 | 51 | NAN_METHOD(verify) { 52 | Nan::HandleScope scope; 53 | OpenSSL_add_all_algorithms(); 54 | 55 | std::string cert_path = *String::Utf8Value(info[0]->ToString()); 56 | std::string ca_bundlestr = *String::Utf8Value(info[1]->ToString()); 57 | 58 | X509_STORE *store = NULL; 59 | X509_STORE_CTX *verify_ctx = NULL; 60 | X509 *cert = NULL; 61 | BIO *cert_bio = NULL; 62 | const char *error = NULL; 63 | 64 | do { 65 | store = X509_STORE_new(); 66 | if (store == NULL) { 67 | error = "Failed to create X509 certificate store."; 68 | break; 69 | } 70 | verify_ctx = X509_STORE_CTX_new(); 71 | if (verify_ctx == NULL) { 72 | error = "Failed to create X509 verification context."; 73 | break; 74 | } 75 | cert_bio = BIO_new(BIO_s_file()); 76 | int ret = BIO_read_filename(cert_bio, cert_path.c_str()); 77 | if (ret != 1) { 78 | error = "Error reading file"; 79 | break; 80 | } 81 | cert = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); 82 | if (cert == NULL) { 83 | error = "Failed to load cert"; 84 | break; 85 | } 86 | ret = X509_STORE_load_locations(store, ca_bundlestr.c_str(), NULL); 87 | if (ret != 1) { 88 | error = "Error loading CA chain file"; 89 | break; 90 | } 91 | X509_STORE_CTX_init(verify_ctx, store, cert, NULL); 92 | ret = X509_verify_cert(verify_ctx); 93 | if (ret <= 0) { 94 | error = X509_verify_cert_error_string(X509_STORE_CTX_get_error(verify_ctx)); 95 | break; 96 | } 97 | } while(0); 98 | 99 | X509_STORE_free(store); 100 | X509_free(cert); 101 | X509_STORE_CTX_free(verify_ctx); 102 | BIO_free_all(cert_bio); 103 | if (error != NULL) { 104 | Nan::ThrowError(error); 105 | } else { 106 | info.GetReturnValue().Set(Nan::New(true)); 107 | } 108 | } 109 | 110 | 111 | 112 | NAN_METHOD(get_altnames) { 113 | Nan::HandleScope scope; 114 | std::string parsed_arg = parse_args(info); 115 | if(parsed_arg.size() == 0) { 116 | info.GetReturnValue().SetUndefined(); 117 | } 118 | Local exports(try_parse(parsed_arg)->ToObject()); 119 | Local key = Nan::New("altNames").ToLocalChecked(); 120 | info.GetReturnValue().Set( 121 | Nan::Get(exports, key).ToLocalChecked()); 122 | ERR_clear_error(); 123 | } 124 | 125 | NAN_METHOD(get_subject) { 126 | Nan::HandleScope scope; 127 | std::string parsed_arg = parse_args(info); 128 | if(parsed_arg.size() == 0) { 129 | info.GetReturnValue().SetUndefined(); 130 | } 131 | Local exports(try_parse(parsed_arg)->ToObject()); 132 | Local key = Nan::New("subject").ToLocalChecked(); 133 | info.GetReturnValue().Set( 134 | Nan::Get(exports, key).ToLocalChecked()); 135 | ERR_clear_error(); 136 | } 137 | 138 | NAN_METHOD(get_issuer) { 139 | Nan::HandleScope scope; 140 | std::string parsed_arg = parse_args(info); 141 | if(parsed_arg.size() == 0) { 142 | info.GetReturnValue().SetUndefined(); 143 | } 144 | Local exports(try_parse(parsed_arg)->ToObject()); 145 | Local key = Nan::New("issuer").ToLocalChecked(); 146 | info.GetReturnValue().Set( 147 | Nan::Get(exports, key).ToLocalChecked()); 148 | ERR_clear_error(); 149 | } 150 | 151 | NAN_METHOD(parse_cert) { 152 | Nan::HandleScope scope; 153 | std::string parsed_arg = parse_args(info); 154 | if(parsed_arg.size() == 0) { 155 | info.GetReturnValue().SetUndefined(); 156 | } 157 | Local exports(try_parse(parsed_arg)->ToObject()); 158 | info.GetReturnValue().Set(exports); 159 | ERR_clear_error(); 160 | } 161 | 162 | /* 163 | * This is where everything is handled for both -0.11.2 and 0.11.3+. 164 | */ 165 | Local try_parse(const std::string& dataString) { 166 | Nan::EscapableHandleScope scope; 167 | const char* data = dataString.c_str(); 168 | 169 | Local exports = Nan::New(); 170 | X509 *cert; 171 | 172 | BIO *bio = BIO_new(BIO_s_mem()); 173 | int result = BIO_puts(bio, data); 174 | 175 | if (result == -2) { 176 | Nan::ThrowError("BIO doesn't support BIO_puts."); 177 | BIO_free(bio); 178 | return scope.Escape(exports); 179 | } 180 | else if (result <= 0) { 181 | Nan::ThrowError("No data was written to BIO."); 182 | BIO_free(bio); 183 | return scope.Escape(exports); 184 | } 185 | 186 | // Try raw read 187 | cert = PEM_read_bio_X509(bio, NULL, 0, NULL); 188 | 189 | if (cert == NULL) { 190 | BIO_free_all(bio); 191 | // Switch to file BIO 192 | bio = BIO_new(BIO_s_file()); 193 | 194 | // If raw read fails, try reading the input as a filename. 195 | if (!BIO_read_filename(bio, data)) { 196 | ERR_clear_error(); 197 | Nan::ThrowError("File doesn't exist."); 198 | BIO_free(bio); 199 | return scope.Escape(exports); 200 | } 201 | 202 | // Try reading the bio again with the file in it. 203 | cert = PEM_read_bio_X509(bio, NULL, 0, NULL); 204 | 205 | if (cert == NULL) { 206 | ERR_clear_error(); 207 | Nan::ThrowError("Unable to parse certificate."); 208 | BIO_free(bio); 209 | return scope.Escape(exports); 210 | } 211 | } 212 | 213 | Nan::Set(exports, 214 | Nan::New("version").ToLocalChecked(), 215 | Nan::New((int) X509_get_version(cert))); 216 | Nan::Set(exports, 217 | Nan::New("subject").ToLocalChecked(), 218 | parse_name(X509_get_subject_name(cert))); 219 | Nan::Set(exports, 220 | Nan::New("issuer").ToLocalChecked(), 221 | parse_name(X509_get_issuer_name(cert))); 222 | Nan::Set(exports, 223 | Nan::New("serial").ToLocalChecked(), 224 | parse_serial(X509_get_serialNumber(cert))); 225 | Nan::Set(exports, 226 | Nan::New("notBefore").ToLocalChecked(), 227 | parse_date(X509_get_notBefore(cert))); 228 | Nan::Set(exports, 229 | Nan::New("notAfter").ToLocalChecked(), 230 | parse_date(X509_get_notAfter(cert))); 231 | 232 | // Subject hash 233 | std::stringstream stream; 234 | stream << std::hex << X509_subject_name_hash(cert); 235 | Nan::Set(exports, 236 | Nan::New("subjectHash").ToLocalChecked(), 237 | Nan::New(stream.str()).ToLocalChecked()); 238 | 239 | // Signature Algorithm 240 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 241 | int sig_alg_nid = X509_get_signature_nid(cert); 242 | #else 243 | int sig_alg_nid = OBJ_obj2nid(cert->sig_alg->algorithm); 244 | #endif 245 | if (sig_alg_nid == NID_undef) { 246 | ERR_clear_error(); 247 | Nan::ThrowError("unable to find specified signature algorithm name."); 248 | X509_free(cert); 249 | BIO_free(bio); 250 | return scope.Escape(exports); 251 | } 252 | Nan::Set(exports, 253 | Nan::New("signatureAlgorithm").ToLocalChecked(), 254 | Nan::New(OBJ_nid2ln(sig_alg_nid)).ToLocalChecked()); 255 | 256 | // fingerPrint 257 | unsigned int md_size, idx; 258 | unsigned char md[EVP_MAX_MD_SIZE]; 259 | if (X509_digest(cert, EVP_sha1(), md, &md_size)) { 260 | const char hex[] = "0123456789ABCDEF"; 261 | char fingerprint[EVP_MAX_MD_SIZE * 3]; 262 | for (idx = 0; idx < md_size; idx++) { 263 | fingerprint[3*idx] = hex[(md[idx] & 0xf0) >> 4]; 264 | fingerprint[(3*idx)+1] = hex[(md[idx] & 0x0f)]; 265 | fingerprint[(3*idx)+2] = ':'; 266 | } 267 | 268 | if (md_size > 0) { 269 | fingerprint[(3*(md_size-1))+2] = '\0'; 270 | } else { 271 | fingerprint[0] = '\0'; 272 | } 273 | Nan::Set(exports, 274 | Nan::New("fingerPrint").ToLocalChecked(), 275 | Nan::New(fingerprint).ToLocalChecked()); 276 | } 277 | 278 | // public key 279 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 280 | int pkey_nid = X509_get_signature_nid(cert); 281 | #else 282 | int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); 283 | #endif 284 | if (pkey_nid == NID_undef) { 285 | ERR_clear_error(); 286 | Nan::ThrowError("unable to find specified public key algorithm name."); 287 | X509_free(cert); 288 | BIO_free(bio); 289 | return scope.Escape(exports); 290 | } 291 | EVP_PKEY *pkey = X509_get_pubkey(cert); 292 | Local publicKey = Nan::New(); 293 | Nan::Set(publicKey, 294 | Nan::New("algorithm").ToLocalChecked(), 295 | Nan::New(OBJ_nid2ln(pkey_nid)).ToLocalChecked()); 296 | 297 | if (pkey_nid == NID_rsaEncryption) { 298 | char *rsa_e_dec, *rsa_n_hex; 299 | uint32_t rsa_key_length_int; 300 | RSA *rsa_key; 301 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 302 | rsa_key = EVP_PKEY_get1_RSA(pkey); 303 | const BIGNUM *n; 304 | const BIGNUM *e; 305 | RSA_get0_key(rsa_key, &n, &e, NULL); 306 | rsa_e_dec = BN_bn2dec(e); 307 | rsa_n_hex = BN_bn2hex(n); 308 | #else 309 | rsa_key = pkey->pkey.rsa; 310 | rsa_e_dec = BN_bn2dec(rsa_key->e); 311 | rsa_n_hex = BN_bn2hex(rsa_key->n); 312 | #endif 313 | rsa_key_length_int = RSA_size(rsa_key) * 8; 314 | Nan::Set(publicKey, 315 | Nan::New("e").ToLocalChecked(), 316 | Nan::New(rsa_e_dec).ToLocalChecked()); 317 | OPENSSL_free(rsa_e_dec); 318 | Nan::Set(publicKey, 319 | Nan::New("n").ToLocalChecked(), 320 | Nan::New(rsa_n_hex).ToLocalChecked()); 321 | OPENSSL_free(rsa_n_hex); 322 | Nan::Set(publicKey, 323 | Nan::New("bitSize").ToLocalChecked(), 324 | Nan::New(rsa_key_length_int)); 325 | } 326 | Nan::Set(exports, Nan::New("publicKey").ToLocalChecked(), publicKey); 327 | EVP_PKEY_free(pkey); 328 | 329 | // alt names 330 | Local altNames(Nan::New()); 331 | STACK_OF(GENERAL_NAME) *names = NULL; 332 | int i; 333 | 334 | names = (STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); 335 | 336 | if (names != NULL) { 337 | int length = sk_GENERAL_NAME_num(names); 338 | for (i = 0; i < length; i++) { 339 | GENERAL_NAME *current = sk_GENERAL_NAME_value(names, i); 340 | 341 | if (current->type == GEN_DNS) { 342 | char *name = NULL; 343 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 344 | name = (char *)ASN1_STRING_get0_data(current->d.dNSName); 345 | #else 346 | name = (char *)ASN1_STRING_data(current->d.dNSName); 347 | #endif 348 | 349 | if (ASN1_STRING_length(current->d.dNSName) != (int) strlen(name)) { 350 | ERR_clear_error(); 351 | Nan::ThrowError("Malformed alternative names field."); 352 | X509_free(cert); 353 | BIO_free(bio); 354 | return scope.Escape(exports); 355 | } 356 | Nan::Set(altNames, i, Nan::New(name).ToLocalChecked()); 357 | } 358 | } 359 | sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); 360 | } 361 | Nan::Set(exports, Nan::New("altNames").ToLocalChecked(), altNames); 362 | 363 | // Extensions 364 | Local extensions(Nan::New()); 365 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 366 | const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); 367 | #else 368 | STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; 369 | #endif 370 | int num_of_exts; 371 | int index_of_exts; 372 | if (exts) { 373 | num_of_exts = sk_X509_EXTENSION_num(exts); 374 | } else { 375 | num_of_exts = 0; 376 | } 377 | 378 | // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); 379 | 380 | for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) { 381 | X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, index_of_exts); 382 | // IFNULL_FAIL(ext, "unable to extract extension from stack"); 383 | ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); 384 | // IFNULL_FAIL(obj, "unable to extract ASN1 object from extension"); 385 | 386 | BIO *ext_bio = BIO_new(BIO_s_mem()); 387 | // IFNULL_FAIL(ext_bio, "unable to allocate memory for extension value BIO"); 388 | if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) { 389 | unsigned char *buf = NULL; 390 | int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), &buf); 391 | if (len >= 0) { 392 | BIO_write(ext_bio, static_cast(buf), len); 393 | } 394 | } 395 | 396 | BUF_MEM *bptr; 397 | BIO_get_mem_ptr(ext_bio, &bptr); 398 | BIO_set_close(ext_bio, BIO_CLOSE); 399 | 400 | char *data = new char[bptr->length + 1]; 401 | BUF_strlcpy(data, bptr->data, bptr->length + 1); 402 | char *trimmed_data = trim(data, bptr->length); 403 | 404 | BIO_free(ext_bio); 405 | 406 | unsigned nid = OBJ_obj2nid(obj); 407 | if (nid == NID_undef) { 408 | char extname[100]; 409 | OBJ_obj2txt(extname, 100, (const ASN1_OBJECT *) obj, 1); 410 | Nan::Set(extensions, 411 | Nan::New(real_name(extname)).ToLocalChecked(), 412 | Nan::New(trimmed_data).ToLocalChecked()); 413 | 414 | } else { 415 | const char *c_ext_name = OBJ_nid2ln(nid); 416 | // IFNULL_FAIL(c_ext_name, "invalid X509v3 extension name"); 417 | Nan::Set(extensions, 418 | Nan::New(real_name((char*)c_ext_name)).ToLocalChecked(), 419 | Nan::New(trimmed_data).ToLocalChecked()); 420 | } 421 | delete[] data; 422 | } 423 | Nan::Set(exports, 424 | Nan::New("extensions").ToLocalChecked(), extensions); 425 | 426 | ERR_clear_error(); 427 | X509_free(cert); 428 | BIO_free(bio); 429 | 430 | return scope.Escape(exports); 431 | } 432 | 433 | Local parse_serial(ASN1_INTEGER *serial) { 434 | Nan::EscapableHandleScope scope; 435 | Local serialNumber; 436 | BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); 437 | char *hex = BN_bn2hex(bn); 438 | 439 | serialNumber = Nan::New(hex).ToLocalChecked(); 440 | BN_free(bn); 441 | OPENSSL_free(hex); 442 | return scope.Escape(serialNumber); 443 | } 444 | 445 | Local parse_date(ASN1_TIME *date) { 446 | Nan::EscapableHandleScope scope; 447 | BIO *bio; 448 | BUF_MEM *bm; 449 | char formatted[64]; 450 | Local args[1]; 451 | 452 | formatted[0] = '\0'; 453 | bio = BIO_new(BIO_s_mem()); 454 | ASN1_TIME_print(bio, date); 455 | BIO_get_mem_ptr(bio, &bm); 456 | BUF_strlcpy(formatted, bm->data, bm->length + 1); 457 | BIO_free(bio); 458 | args[0] = Nan::New(formatted).ToLocalChecked(); 459 | 460 | Local global = Nan::GetCurrentContext()->Global(); 461 | Local DateObject = Nan::Get(global, 462 | Nan::New("Date").ToLocalChecked()).ToLocalChecked()->ToObject(); 463 | return scope.Escape(Nan::CallAsConstructor(DateObject, 1, args).ToLocalChecked()); 464 | } 465 | 466 | Local parse_name(X509_NAME *subject) { 467 | Nan::EscapableHandleScope scope; 468 | Local cert = Nan::New(); 469 | int i, length; 470 | ASN1_OBJECT *entry; 471 | const unsigned char *value; 472 | char buf[255]; 473 | length = X509_NAME_entry_count(subject); 474 | for (i = 0; i < length; i++) { 475 | entry = X509_NAME_ENTRY_get_object(X509_NAME_get_entry(subject, i)); 476 | OBJ_obj2txt(buf, 255, entry, 0); 477 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L 478 | value = ASN1_STRING_get0_data( 479 | X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); 480 | #else 481 | value = ASN1_STRING_data( 482 | X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); 483 | #endif 484 | Nan::Set(cert, 485 | Nan::New(real_name(buf)).ToLocalChecked(), 486 | Nan::New((const char*) value).ToLocalChecked()); 487 | } 488 | return scope.Escape(cert); 489 | } 490 | 491 | // Fix for missing fields in OpenSSL. 492 | char* real_name(char *data) { 493 | int i, length = (int) sizeof(MISSING) / sizeof(MISSING[0]); 494 | 495 | for (i = 0; i < length; i++) { 496 | if (strcmp(data, MISSING[i][0]) == 0) 497 | return (char*) MISSING[i][1]; 498 | } 499 | 500 | return data; 501 | } 502 | 503 | char* trim(char *data, int len) { 504 | if (data[0] == '\n' || data[0] == '\r') { 505 | data = data+1; 506 | } 507 | else if (len > 1 && (data[len-1] == '\n' || data[len-1] == '\r')) { 508 | data[len-1] = (char) 0; 509 | } 510 | else if (len > 0 && (data[len] == '\n' || data[len] == '\r')) { 511 | data[len] = (char) 0; 512 | } 513 | else { 514 | return data; 515 | } 516 | 517 | return trim(data, len - 1); 518 | } 519 | -------------------------------------------------------------------------------- /test/CA_chains/enduser-example.com.chain: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAI6zVCRN44FlMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCXg1MDktdGVzdDAeFw0xNzExMjgwODQ2NDdaFw0yNzExMjYwODQ2NDdaMBQx 4 | EjAQBgNVBAMMCXg1MDktdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAMmi9qSlfyxP9Btj1WlPcfymRQg3qHi0cpM8hxlevWf87cP5SQA1QEPq17xQ 6 | EoLUt6nEf9a8BjoE/GCPXifYD6cPb3fqxGi/IiMjuNwznlfGWNhOnqKbhJo0FZna 7 | /wdCEP8upRmmWqx1pHgr7QQgPYHZIMiCbtG66+VV4KNgD5YjIOMABEJfalh3GOFh 8 | STWbFEUXqLjqttFF4xfve88Xk6+xpCFCCzC5SraVCR1OL2UiUyOMMKkyWlLL2Jd3 9 | TsVbRTTuxLBPohajwGPxuusqaoMLvQ73WzArnfDADRHqm67rlx6EFe1BjCyzKiT7 10 | f354LnsZZhj6jnPOQxs6rrsqH9kCAwEAAaNQME4wHQYDVR0OBBYEFGimY7g6t0Uh 11 | lrr3ZpBqPXpvW/T+MB8GA1UdIwQYMBaAFGimY7g6t0Uhlrr3ZpBqPXpvW/T+MAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKjz0ylupkmE/FtiDLz1x3uL 13 | UsLo/a82HoAwUi/GPICQdp5wjI5E02GoM04HdRvRZXVXiTdPlZrSEvHHLuBo/BdK 14 | XkEpwFFYhBNg3n+KmU7M4NNL8Uwb2BLX7432I1blQKe756T4A1O8OxKIhD7JyxGn 15 | SAaz5PZNQIm9hw2Elt/P9/7n86aHrsFYOl4K2rUlCfuh+9KzBkjpykU50idbd+FI 16 | V4mmvN9s8XXcYpCzQB5mfVgTSSRpvYxmrkHUODOnxQJ4jn0LNNEhq6HsB5tUhu0b 17 | RZASyTfbHfAfflGbkONnTiEHfux3CCYM2BuJ0Mdk5gZPcCY3yRgZP1i8PGTIaOc= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /test/certs/acaline.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFRTCCBC2gAwIBAgIHJ6yuMLnzIzANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE 3 | BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY 4 | BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm 5 | aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5 6 | IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky 7 | ODcwHhcNMTMwNDI2MTQ1MTE3WhcNMTQwNDI2MTQ1MTE3WjA9MSEwHwYDVQQLExhE 8 | b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxGDAWBgNVBAMTD3d3dy5hY2FsaW5lLmNv 9 | bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ9t6lDUaTlQiRZF8V5 10 | x9/IpwPO3hjVzApA20GysXt5r/VZ+blSgkt42NQUdQYNXX5E1H42CtAwg8giLqw6 11 | 2aEkHLQ3aFXMmcMktCU+//vm3cMD5ShKRKxxY9azlQ1AYIUXJJJgK79o1vTCp62A 12 | oQaR5dEcyn6jkR7s35j5lG+rNRk9VtcSntiqFUX6HcokIvHffpl6YWtAbZigfm6w 13 | 7sElt7bgD+jlh53mF9v2EpbQaLsVKaMaHLlbgeG4Oww+AwWnpfUmBFHik2T3RE94 14 | WxqklUCYDNsvNLTQwa34dDI0JbUI1ExLC7lo0+fJgCnLf3U3avsUbuo+8nmSVLhd 15 | zkcCAwEAAaOCAbowggG2MA8GA1UdEwEB/wQFMAMBAQAwHQYDVR0lBBYwFAYIKwYB 16 | BQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAzBgNVHR8ELDAqMCigJqAk 17 | hiJodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkczEtOTAuY3JsMFMGA1UdIARMMEow 18 | SAYLYIZIAYb9bQEHFwEwOTA3BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRl 19 | cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzCBgAYIKwYBBQUHAQEEdDByMCQGCCsG 20 | AQUFBzABhhhodHRwOi8vb2NzcC5nb2RhZGR5LmNvbS8wSgYIKwYBBQUHMAKGPmh0 21 | dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZF9pbnRl 22 | cm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2sYTKTbEXW4u6FX5q653aZaMznMCcG 23 | A1UdEQQgMB6CD3d3dy5hY2FsaW5lLmNvbYILYWNhbGluZS5jb20wHQYDVR0OBBYE 24 | FOZhFE5aS1EMTmxePHlhZdS9ZJS+MA0GCSqGSIb3DQEBBQUAA4IBAQBWtSoAXqwS 25 | lGHM199r4mZ8aPBgPEm8IJipk/qR4sbcSu2GdCChxpyu459tIUhOh+/noHc1Ubfx 26 | +e7W96kX1HMQETYSC8FWn6LVTURRWwA/NIqM4AEGO+d3qwwchmw6pZX7R3+4DZ8f 27 | 3IjOuovhqGt0EJEPRKqzbFzrjFCoRYpgn52aijBdZGLJaPvZOKT5fJ6ntsbgO0xK 28 | dd9L2ODL/CJzS/RRRhO0k76vCq88kX1pham8yXH6mYLcCrUcWY1HcgC/y/5EESWH 29 | Y5+UfLaeUH5QU3Wtg2qwo5fUDG8ox8PlNXKEs6u38/x84GKJdOmpzAP8/a/HPECM 30 | S0cBxC+UItcO 31 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /test/certs/enduser-example.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAI6zVCRN44FlMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCXg1MDktdGVzdDAeFw0xNzExMjgwODQ2NDdaFw0yNzExMjYwODQ2NDdaMBQx 4 | EjAQBgNVBAMMCXg1MDktdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAMmi9qSlfyxP9Btj1WlPcfymRQg3qHi0cpM8hxlevWf87cP5SQA1QEPq17xQ 6 | EoLUt6nEf9a8BjoE/GCPXifYD6cPb3fqxGi/IiMjuNwznlfGWNhOnqKbhJo0FZna 7 | /wdCEP8upRmmWqx1pHgr7QQgPYHZIMiCbtG66+VV4KNgD5YjIOMABEJfalh3GOFh 8 | STWbFEUXqLjqttFF4xfve88Xk6+xpCFCCzC5SraVCR1OL2UiUyOMMKkyWlLL2Jd3 9 | TsVbRTTuxLBPohajwGPxuusqaoMLvQ73WzArnfDADRHqm67rlx6EFe1BjCyzKiT7 10 | f354LnsZZhj6jnPOQxs6rrsqH9kCAwEAAaNQME4wHQYDVR0OBBYEFGimY7g6t0Uh 11 | lrr3ZpBqPXpvW/T+MB8GA1UdIwQYMBaAFGimY7g6t0Uhlrr3ZpBqPXpvW/T+MAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKjz0ylupkmE/FtiDLz1x3uL 13 | UsLo/a82HoAwUi/GPICQdp5wjI5E02GoM04HdRvRZXVXiTdPlZrSEvHHLuBo/BdK 14 | XkEpwFFYhBNg3n+KmU7M4NNL8Uwb2BLX7432I1blQKe756T4A1O8OxKIhD7JyxGn 15 | SAaz5PZNQIm9hw2Elt/P9/7n86aHrsFYOl4K2rUlCfuh+9KzBkjpykU50idbd+FI 16 | V4mmvN9s8XXcYpCzQB5mfVgTSSRpvYxmrkHUODOnxQJ4jn0LNNEhq6HsB5tUhu0b 17 | RZASyTfbHfAfflGbkONnTiEHfux3CCYM2BuJ0Mdk5gZPcCY3yRgZP1i8PGTIaOc= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /test/certs/equifax.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 3 | UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy 4 | dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 5 | MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx 6 | dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B 7 | AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f 8 | BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A 9 | cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC 10 | AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ 11 | MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm 12 | aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw 13 | ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj 14 | IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF 15 | MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA 16 | A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 17 | 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 18 | 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 19 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /test/certs/github.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIHOjCCBiKgAwIBAgIQBH++LkveAITSyvjj7P5wWDANBgkqhkiG9w0BAQUFADBp 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSgwJgYDVQQDEx9EaWdpQ2VydCBIaWdoIEFzc3VyYW5j 5 | ZSBFViBDQS0xMB4XDTEzMDYxMDAwMDAwMFoXDTE1MDkwMjEyMDAwMFowgfAxHTAb 6 | BgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVT 7 | MRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMRcw 8 | FQYDVQQJEw41NDggNHRoIFN0cmVldDEOMAwGA1UEERMFOTQxMDcxCzAJBgNVBAYT 9 | AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv 10 | MRUwEwYDVQQKEwxHaXRIdWIsIEluYy4xEzARBgNVBAMTCmdpdGh1Yi5jb20wggEi 11 | MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDt04nDXXByCfMzTxpydNm2WpVQ 12 | u2hhn/f7Hxnh2gQxrxV8Gn/5c68d5UMrVgkARWlK6MRb38J3UlEZW9Er2TllNqAy 13 | GRxBc/sysj2fmOyCWws3ZDkstxCDcs3w6iRL+tmULsOFFTmpOvaI2vQniaaVT4Si 14 | N058JXg6yYNtAheVeH1HqFWD7hPIGRqzPPFf/jsC4YX7EWarCV2fTEPwxyReKXIo 15 | ztR1aE8kcimuOSj8341PTYNzdAxvEZun3WLe/+LrF+b/DL/ALTE71lmi8t2HSkh7 16 | bTMRFE00nzI49sgZnfG2PcVG71ELisYz7UhhxB0XG718tmfpOc+lUoAK9OrNAgMB 17 | AAGjggNUMIIDUDAfBgNVHSMEGDAWgBRMWMsl8EFPUvQoyIFDm6aooOaS5TAdBgNV 18 | HQ4EFgQUh9GPGW7kh29TjHeRB1Dfo79VRyAwJQYDVR0RBB4wHIIKZ2l0aHViLmNv 19 | bYIOd3d3LmdpdGh1Yi5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsG 20 | AQUFBwMBBggrBgEFBQcDAjBjBgNVHR8EXDBaMCugKaAnhiVodHRwOi8vY3JsMy5k 21 | aWdpY2VydC5jb20vZXZjYTEtZzIuY3JsMCugKaAnhiVodHRwOi8vY3JsNC5kaWdp 22 | Y2VydC5jb20vZXZjYTEtZzIuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB 23 | hv1sAgEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z 24 | c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A 25 | eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA 26 | ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA 27 | IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA 28 | YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA 29 | cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA 30 | aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA 31 | ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMH0G 32 | CCsGAQUFBwEBBHEwbzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu 33 | Y29tMEcGCCsGAQUFBzAChjtodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln 34 | aUNlcnRIaWdoQXNzdXJhbmNlRVZDQS0xLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqG 35 | SIb3DQEBBQUAA4IBAQBfFW1nwzrVo94WnEUzJtU9yRZ0NMqHSBsUkG31q0eGufW4 36 | 4wFFZWjuqRJ1n3Ym7xF8fTjP3fdKGQnxIHKSsE0nuuh/XbQX5DpBJknHdGFoLwY8 37 | xZ9JPI57vgvzLo8+fwHyZp3Vm/o5IYLEQViSo+nlOSUQ8YAVqu6KcsP/e612UiqS 38 | +UMBmgdx9KPDDzZy4MJZC2hbfUoXj9A54mJN8cuEOPyw3c3yKOcq/h48KzVguQXi 39 | SdJbwfqNIbQ9oJM+YzDjzS62+TCtNSNWzWbwABZCmuQxK0oEOSbTmbhxUF7rND3/ 40 | +mx9u8cY//7uAxLWYS5gIZlCbxcf0lkiKSHJB319 41 | -----END CERTIFICATE----- 42 | 43 | -------------------------------------------------------------------------------- /test/certs/google.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGKjCCBZOgAwIBAgIKZAPy8wABAACR3DANBgkqhkiG9w0BAQUFADBGMQswCQYD 3 | VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu 4 | dGVybmV0IEF1dGhvcml0eTAeFw0xMzA3MTIwOTAwMzBaFw0xMzEwMzEyMzU5NTla 5 | MGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N 6 | b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRUwEwYDVQQDFAwqLmdv 7 | b2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANRk5KDRmXcTdorq 8 | kBFq7Mz17PXY3L1XaypAA/gMju7TcS6cbMmOEhmIXX5Ul+GAxfLwmE2WSGe1K58m 9 | ++B4D153EKIXc+ilrDKt7K/BfcX1cH3qUhk6Zc3IO2PTPL3UYkWA6WiH1Ehuaf39 10 | 89FfB7Vk20Nv2QOvNOHW18qZWgbzAgMBAAGjggP9MIID+TAdBgNVHSUEFjAUBggr 11 | BgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFArP+7JSI4++2qQ6xmNmryABbF8z 12 | MB8GA1UdIwQYMBaAFL/AMOv1QxE+Z7qekfv8atrjaxIkMFsGA1UdHwRUMFIwUKBO 13 | oEyGSmh0dHA6Ly93d3cuZ3N0YXRpYy5jb20vR29vZ2xlSW50ZXJuZXRBdXRob3Jp 14 | dHkvR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkuY3JsMGYGCCsGAQUFBwEBBFowWDBW 15 | BggrBgEFBQcwAoZKaHR0cDovL3d3dy5nc3RhdGljLmNvbS9Hb29nbGVJbnRlcm5l 16 | dEF1dGhvcml0eS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS5jcnQwDAYDVR0TAQH/ 17 | BAIwADCCAsMGA1UdEQSCArowggK2ggwqLmdvb2dsZS5jb22CDSouYW5kcm9pZC5j 18 | b22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CEiouY2xvdWQuZ29vZ2xlLmNvbYIW 19 | Ki5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNs 20 | gg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVr 21 | gg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29t 22 | LmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUu 23 | Y29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5l 24 | c4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29n 25 | bGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIIPKi5nb29nbGVhcGlzLmNu 26 | ghQqLmdvb2dsZWNvbW1lcmNlLmNvbYINKi5nc3RhdGljLmNvbYIMKi51cmNoaW4u 27 | Y29tghAqLnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUuY29tgg0q 28 | LnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRpb24uY29tggsqLnl0aW1nLmNv 29 | bYILYW5kcm9pZC5jb22CBGcuY2+CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5j 30 | b22CCmdvb2dsZS5jb22CEmdvb2dsZWNvbW1lcmNlLmNvbYIKdXJjaGluLmNvbYII 31 | eW91dHUuYmWCC3lvdXR1YmUuY29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbTANBgkq 32 | hkiG9w0BAQUFAAOBgQBfxSnRtvvjE4rZn/JjpRoC9HrlCXNfMtg3feveIEhGA8Cl 33 | j5aGf2H+8RBfTYzwFmykUvlYNA47de8rHU6rAMcOR7Nq2ePB8BXpsnZ4CH0mCBNz 34 | 76V3NMkECr+o+Vn9l6sAbyjqGwA0dJ3++4SM0Hjd/6jXLXt3ICgggP4eKr09fA== 35 | -----END CERTIFICATE----- 36 | -------------------------------------------------------------------------------- /test/certs/nodejitsu.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFijCCBHKgAwIBAgIQGrJnxsVHRl8drNBuS1DYrTANBgkqhkiG9w0BAQUFADCB 3 | iTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G 4 | A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxLzAtBgNV 5 | BAMTJkNPTU9ETyBIaWdoLUFzc3VyYW5jZSBTZWN1cmUgU2VydmVyIENBMB4XDTEy 6 | MTAyOTAwMDAwMFoXDTE0MTEyNjIzNTk1OVowgasxCzAJBgNVBAYTAlVTMQ4wDAYD 7 | VQQREwUxMDAxMDELMAkGA1UECBMCTlkxETAPBgNVBAcTCE5ldyBZb3JrMSAwHgYD 8 | VQQJExc5MDIgQnJvYWR3YXksIDR0aCBGbG9vcjESMBAGA1UEChMJTm9kZWppdHN1 9 | MRwwGgYDVQQLExNQcmVtaXVtU1NMIFdpbGRjYXJkMRgwFgYDVQQDFA8qLm5vZGVq 10 | aXRzdS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbk23U9QCq 11 | I5/ifOP3q4dB6hlBYVaNf91pDI6PCgwaePlbB/7L+GrQdKLG+T6zumFM8XF5miNI 12 | vDpEj7Ej5yk/UEtHyItZ/eZdEBPitQ8r+qz1dTWnznYBYEWz7rCtJWpFPsQNZ1Mz 13 | MYhEQW7ziaU/Pm0+QhB6VEPoTjpTF/diuSV5BuBScoUEx92ONmcJWjELXlh1+tUP 14 | AQFGay0b0dgO3HRLXL/3fDSwJ57Jl+XLNPrUyfgwEH/qIIRbJo8rKz9mmjZ9CWe+ 15 | NBaLE5l2ojsjdv/XuEhFx/LcyRqaF6QaoVCLAEezEdqsewjYuaa4aa2Q80eEi4FE 16 | fzLrb9H1rwY/AgMBAAGjggHIMIIBxDAfBgNVHSMEGDAWgBQ/1bXQ1kR5UEoXo5uM 17 | Sty4sCJkazAdBgNVHQ4EFgQUWCGCWVr+6Wfeqdn3Pq6eVKhaW1YwDgYDVR0PAQH/ 18 | BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF 19 | BwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQMEMCswKQYIKwYBBQUHAgEWHWh0 20 | dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTME8GA1UdHwRIMEYwRKBCoECGPmh0 21 | dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET0hpZ2gtQXNzdXJhbmNlU2VjdXJl 22 | U2VydmVyQ0EuY3JsMIGABggrBgEFBQcBAQR0MHIwSgYIKwYBBQUHMAKGPmh0dHA6 23 | Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0hpZ2gtQXNzdXJhbmNlU2VjdXJlU2Vy 24 | dmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20w 25 | KQYDVR0RBCIwIIIPKi5ub2Rlaml0c3UuY29tgg1ub2Rlaml0c3UuY29tMA0GCSqG 26 | SIb3DQEBBQUAA4IBAQDK0E+FhKRhaAPGf9MI+uk7TBZsY/2w/lclGs1Cp/pnU/In 27 | aIRBAn5AGJSk5huaMVyjAUuKkdJMQ2sgbVrxgg08nQwbYZqGD2YeFI43aDODKHbw 28 | 8VNPEdCfdvOr0f+a0HZzB6WFsj2jZ8yXe0nXhzLx2itZexeMTqqjTy14JXkOPNsa 29 | nWMP6czPrY1cx99uaOfI2nsQhEnIJLNhamciCuxmTvHVOQLow1ACEsvGadMLOXzI 30 | U/B6O8LPD/ZVNR85MkfVT+r0MVT4Ig5TC7P0/Sz/uR5YFWd9yAzixcEOK6EHqMP/ 31 | I+n4s4codplzn0C0CFfmuwByibUmjbTpM2n7rGkP 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test/certs/npmjs.org.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFnDCCBISgAwIBAgISESFVSDMXLS4GTvZKq3C/6JLaMA0GCSqGSIb3DQEBBQUA 3 | MF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYD 4 | VQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gRzIw 5 | HhcNMTIwODI0MTkzMzEwWhcNMTQwODI1MTkzMzEwWjBeMQswCQYDVQQGEwJVUzEL 6 | MAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFTATBgNVBAoTDEpv 7 | eWVudCwgSW5jLjETMBEGA1UEAxMKbm9kZWpzLm9yZzCCASIwDQYJKoZIhvcNAQEB 8 | BQADggEPADCCAQoCggEBANNR/dsxDcwb/llUfhIurRlzkAtJR8iBR4iYLWY1g9Ew 9 | bUgjVIKeLjGuUTG2K/iOK4/s6xtBndaq3JXY9fCDXmUSURwjMfa7tkI51Cxz46qf 10 | NsQB825+/aRAaabRMvAP94Et0G/FGFYKvJ2tswVe3X1Oz9+W+/NbYLhLTQ82qxk4 11 | LxqEXPy50MPxGSRjIYuK+ScTzmmYYm09UJBiAPp6HYbLjiohrjAhnKOtYg8xN0B8 12 | 0JyLzkHmItwNLrwLogLTREyEN0ZPZiLAYVoJehmhnxQCuYbJlzHmPu9FrRSJAlO3 13 | isD8WlCNb5svV/n/bNUZgpqeQ1axx8rkFLTHzy1r7RcCAwEAAaOCAlMwggJPMA4G 14 | A1UdDwEB/wQEAwIFoDBMBgNVHSAERTBDMEEGCSsGAQQBoDIBFDA0MDIGCCsGAQUF 15 | BwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzCBpAYD 16 | VR0RBIGcMIGZggpub2RlanMub3JngglucG1qcy5vcmeCBm5wbS5pbYIScmVnaXN0 17 | cnkubnBtanMub3JnghFzY3JhdGNoLm5wbWpzLm9yZ4IQYnVpbGQubm9kZWpzLm9y 18 | Z4IKd3d3Lm5wbS5pbYITcGFja2FnZXMubm9kZWpzLm9yZ4IPY291Y2gubnBtanMu 19 | b3Jngg13d3cubnBtanMub3JnMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUH 20 | AwEGCCsGAQUFBwMCMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwuZ2xvYmFs 21 | c2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxnMi5jcmwwgZYGCCsGAQUFBwEB 22 | BIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29t 23 | L2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbGcyLmNydDA7BggrBgEFBQcwAYYvaHR0 24 | cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFsZzIwHQYD 25 | VR0OBBYEFEKByhV23+t+wxVY6PtpVh5AwjCGMB8GA1UdIwQYMBaAFF1Gso3ES3Qc 26 | u+31c7Y6tziPdZ5+MA0GCSqGSIb3DQEBBQUAA4IBAQDWOOJwWNHI+S0Q4bxUa8KS 27 | 2Enk1rPln+XsrXxRJlS2LsEvdTlBYJQLE+rTec/5OE38tCA5zGJViZP8uS/mxUlS 28 | Qu17p9cHI6K0YtWclfQXPUhjTu7hXjRqyw+4y+O+pU6jifI8+kQdjAHCrkymm99+ 29 | Rahha24ZX24LtZncRh2r/gJiGMex3Xe2fP0L8mro/KQikYRGNA2He23usKYybGTs 30 | 9iRy1q9wHtD/qaAdW/ICiNXwAoh3NqaOO1AOtUT8Yg1zOtiZxs26CrQxY+UyBb2A 31 | vPWsBMp0Os0uPW8IDstn1jC8W2NfRqx7/c7v9y8dS469zB0c5GVi6JA56KdTBjL2 32 | -----END CERTIFICATE----- 33 | 34 | -------------------------------------------------------------------------------- /test/certs/pushpinplanner.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFWzCCBEOgAwIBAgIQbXWtqGesm5OWJzDBzxQ9bDANBgkqhkiG9w0BAQUFADBy 3 | MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD 4 | VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE 5 | AxMPRXNzZW50aWFsU1NMIENBMB4XDTEzMDYyNzAwMDAwMFoXDTE0MDYyNzIzNTk1 6 | OVowYjEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMR4wHAYDVQQL 7 | ExVFc3NlbnRpYWxTU0wgV2lsZGNhcmQxHTAbBgNVBAMUFCoucHVzaHBpbnBsYW5u 8 | ZXIuY29tMIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEAx1aDHWamem5I 9 | gj06+gcqNLhrPKDCjjvmIr+h7hgAwhuHhT38kUmGoCetTUc8aGNspxoMIvESQh3D 10 | JDiP54OSfVxjy6znaGGH32L0D8wDV6jI5CLTP3x0CPk1qcnP4zCkcs2nvPdhW5Ev 11 | YBuNUloxlEz4Thw90ZTRVGACIk1+zj11mCZZd25qCcdZRqS55NVTzIF0V41wpTiV 12 | 2pKJDp+OSdDo6roFOn6ZVnIAVN4ot4TMBObB79WJ5hGPLp9AAw3aP4TLgUM2diDT 13 | DzYnL+rsyWa7T0eWQFbZBaiISBNN2PMb89bucjKd5YIEcmN6BcEdTjmrcBVjha9g 14 | vVVCevyCtyM7n3gf1n1D9zAX+s/8aieAuw4jtP1Bi4D71AG9xNP8z6h/8HsDIyF0 15 | W6CzYxOCIQIDAQABo4IByzCCAccwHwYDVR0jBBgwFoAU2svqrVsIXcz//CZUzknl 16 | VcY49PgwHQYDVR0OBBYEFLE2rq/eKNiN4y7DqXQu9WT0HZUlMA4GA1UdDwEB/wQE 17 | AwIFoDAMBgNVHRMBAf8EAjAAMDQGA1UdJQQtMCsGCCsGAQUFBwMBBggrBgEFBQcD 18 | AgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBME8GA1UdIARIMEYwOgYLKwYBBAGyMQEC 19 | AgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMw 20 | CAYGZ4EMAQIBMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwuY29tb2RvY2Eu 21 | Y29tL0Vzc2VudGlhbFNTTENBLmNybDBuBggrBgEFBQcBAQRiMGAwOAYIKwYBBQUH 22 | MAKGLGh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0Vzc2VudGlhbFNTTENBXzIuY3J0 23 | MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wMwYDVR0RBCww 24 | KoIUKi5wdXNocGlucGxhbm5lci5jb22CEnB1c2hwaW5wbGFubmVyLmNvbTANBgkq 25 | hkiG9w0BAQUFAAOCAQEAVlKaAQifs4+0fMnqbFKhHDmGOwtCgJ+RBDgrzVucIQ/S 26 | Lde1OgGN/m0MWXPztyMqsr1SHHqsMh2jafSBEjl9gJ69Xdr3sYi6s7gC0xPX+xe4 27 | 56+o9AdLcTwAQ92fOzjAou0PZ0+bQp7cVFR5xeKBkQoY8bsHFQeCF5ZPpYEMflIM 28 | nbTXyYQHKG1ZDEaB7qk91RoQeVL8XMBIQOEXXt7Doz+/eRhXGNCAGFttmXNzb/t2 29 | 3KZpowyMdaNjVWVFVxEHoaaHaLT7QEsc1522cI5gO4xz0MuE8gigsdNXsvfZ0BjD 30 | VMHiE37zHjvSloxV/wZBa4caOVG6s8NDjPMEGOu2Xw== 31 | -----END CERTIFICATE----- 32 | 33 | -----BEGIN CERTIFICATE----- 34 | MIIFWzCCBEOgAwIBAgIQbXWtqGesm5OWJzDBzxQ9bDANBgkqhkiG9w0BAQUFADBy 35 | MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD 36 | VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE 37 | AxMPRXNzZW50aWFsU1NMIENBMB4XDTEzMDYyNzAwMDAwMFoXDTE0MDYyNzIzNTk1 38 | OVowYjEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMR4wHAYDVQQL 39 | ExVFc3NlbnRpYWxTU0wgV2lsZGNhcmQxHTAbBgNVBAMUFCoucHVzaHBpbnBsYW5u 40 | ZXIuY29tMIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEAx1aDHWamem5I 41 | gj06+gcqNLhrPKDCjjvmIr+h7hgAwhuHhT38kUmGoCetTUc8aGNspxoMIvESQh3D 42 | JDiP54OSfVxjy6znaGGH32L0D8wDV6jI5CLTP3x0CPk1qcnP4zCkcs2nvPdhW5Ev 43 | YBuNUloxlEz4Thw90ZTRVGACIk1+zj11mCZZd25qCcdZRqS55NVTzIF0V41wpTiV 44 | 2pKJDp+OSdDo6roFOn6ZVnIAVN4ot4TMBObB79WJ5hGPLp9AAw3aP4TLgUM2diDT 45 | DzYnL+rsyWa7T0eWQFbZBaiISBNN2PMb89bucjKd5YIEcmN6BcEdTjmrcBVjha9g 46 | vVVCevyCtyM7n3gf1n1D9zAX+s/8aieAuw4jtP1Bi4D71AG9xNP8z6h/8HsDIyF0 47 | W6CzYxOCIQIDAQABo4IByzCCAccwHwYDVR0jBBgwFoAU2svqrVsIXcz//CZUzknl 48 | VcY49PgwHQYDVR0OBBYEFLE2rq/eKNiN4y7DqXQu9WT0HZUlMA4GA1UdDwEB/wQE 49 | AwIFoDAMBgNVHRMBAf8EAjAAMDQGA1UdJQQtMCsGCCsGAQUFBwMBBggrBgEFBQcD 50 | AgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBME8GA1UdIARIMEYwOgYLKwYBBAGyMQEC 51 | AgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMw 52 | CAYGZ4EMAQIBMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwuY29tb2RvY2Eu 53 | Y29tL0Vzc2VudGlhbFNTTENBLmNybDBuBggrBgEFBQcBAQRiMGAwOAYIKwYBBQUH 54 | MAKGLGh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0Vzc2VudGlhbFNTTENBXzIuY3J0 55 | MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wMwYDVR0RBCww 56 | KoIUKi5wdXNocGlucGxhbm5lci5jb22CEnB1c2hwaW5wbGFubmVyLmNvbTANBgkq 57 | hkiG9w0BAQUFAAOCAQEAVlKaAQifs4+0fMnqbFKhHDmGOwtCgJ+RBDgrzVucIQ/S 58 | Lde1OgGN/m0MWXPztyMqsr1SHHqsMh2jafSBEjl9gJ69Xdr3sYi6s7gC0xPX+xe4 59 | 56+o9AdLcTwAQ92fOzjAou0PZ0+bQp7cVFR5xeKBkQoY8bsHFQeCF5ZPpYEMflIM 60 | nbTXyYQHKG1ZDEaB7qk91RoQeVL8XMBIQOEXXt7Doz+/eRhXGNCAGFttmXNzb/t2 61 | 3KZpowyMdaNjVWVFVxEHoaaHaLT7QEsc1522cI5gO4xz0MuE8gigsdNXsvfZ0BjD 62 | VMHiE37zHjvSloxV/wZBa4caOVG6s8NDjPMEGOu2Xw== 63 | -----END CERTIFICATE----- 64 | -------------------------------------------------------------------------------- /test/certs/travis-ci.org.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFEjCCA/qgAwIBAgIQe8YtRyvAu2oY+kHrnGtTMDANBgkqhkiG9w0BAQUFADBy 3 | MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD 4 | VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE 5 | AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMDkyMjAwMDAwMFoXDTEzMDkyMjIzNTk1 6 | OVowXTEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMR4wHAYDVQQL 7 | ExVFc3NlbnRpYWxTU0wgV2lsZGNhcmQxGDAWBgNVBAMUDyoudHJhdmlzLWNpLm9y 8 | ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMtNoEcccyJEX25X2Fsz 9 | LFExIqxi6AoKxVBI+ufD1oppgWJRjGErP8OlUdSYgjJTkKRWfDGneMI4nI9WKzFR 10 | kPbDWlWNvG2cQirkptD4zFkoEbpTxkGaTXk3tn21+3u9XIvRbLk+/3iFh/NUcgV4 11 | N/hPB5zI7PBIkuAT8SYlMLNekUcrOON4Hww7YzLras2ilLbVVnuijMuv6kb8jun+ 12 | PTnKHu2ZXEkfeQtEhPVrCAtdnF2WN8syoe399NIM0NNgw2PQdu8oHArXqegJDhls 13 | QfTyYXViQWnMYA1RJgJV9piAvn4kG/zptvjWJmAWeuMP4KPqEngSGsl8sqvyDRAJ 14 | 5OUCAwEAAaOCAbcwggGzMB8GA1UdIwQYMBaAFNrL6q1bCF3M//wmVM5J5VXGOPT4 15 | MB0GA1UdDgQWBBRz7/8kNaKIUS3e+4I3LAN0ZIaOFDAOBgNVHQ8BAf8EBAMCBaAw 16 | DAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIGCisG 17 | AQQBgjcKAwMGCWCGSAGG+EIEATBFBgNVHSAEPjA8MDoGCysGAQQBsjEBAgIHMCsw 18 | KQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMDsGA1Ud 19 | HwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Vzc2VudGlhbFNT 20 | TENBLmNybDBuBggrBgEFBQcBAQRiMGAwOAYIKwYBBQUHMAKGLGh0dHA6Ly9jcnQu 21 | Y29tb2RvY2EuY29tL0Vzc2VudGlhbFNTTENBXzIuY3J0MCQGCCsGAQUFBzABhhho 22 | dHRwOi8vb2NzcC5jb21vZG9jYS5jb20wKQYDVR0RBCIwIIIPKi50cmF2aXMtY2ku 23 | b3Jngg10cmF2aXMtY2kub3JnMA0GCSqGSIb3DQEBBQUAA4IBAQBORdEsuAKCURKZ 24 | fts4Ahl9CVyIby0GghtVuHumn9rvZ2CpB/pdTzX1qlCF1LU0gD2qThO7Q3+63swI 25 | lnAboAFFvEIEcJPkKTG7eV4V0VDdvE5+oZ0fociN499LEPCelHQW9QHy/M0f3cUP 26 | 6Jk71ioPM8/zUC7AXHM8ejKQz4zHnQdnwqe0uz1mspBhAFGUSK41eC9XWgPdRhOo 27 | 12eHTuUjSDfJJ6FDhphhYnp0/mE9fiXRGAYvwawWP0vdPunC9aCOaGKDln9LrkTI 28 | KQDlDhp16OlvAjw3hWxxuJLnO+UVyRgPuyYz8kK6nkpfvIVlaQNpULFXCnPRHkw2 29 | 6LrlvP8X 30 | -----END CERTIFICATE----- 31 | 32 | -------------------------------------------------------------------------------- /test/certs/twitter.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGfDCCBWSgAwIBAgIQHiLHN6ORXj+rZcS1pByuRjANBgkqhkiG9w0BAQUFADCB 3 | ujELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL 4 | ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug 5 | YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE0MDIGA1UEAxMr 6 | VmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBDQTAeFw0x 7 | MjA0MTAwMDAwMDBaFw0xNDA1MTAyMzU5NTlaMIIBFzETMBEGCysGAQQBgjc8AgED 8 | EwJVUzEZMBcGCysGAQQBgjc8AgECEwhEZWxhd2FyZTEdMBsGA1UEDxMUUHJpdmF0 9 | ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzQzMzc0NDYxCzAJBgNVBAYTAlVTMQ4w 10 | DAYDVQQRFAU5NDEwNzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxQNU2Fu 11 | IEZyYW5jaXNjbzEhMB8GA1UECRQYNzk1IEZvbHNvbSBTdCwgU3VpdGUgNjAwMRYw 12 | FAYDVQQKFA1Ud2l0dGVyLCBJbmMuMRkwFwYDVQQLFBBUd2l0dGVyIFNlY3VyaXR5 13 | MRQwEgYDVQQDFAt0d2l0dGVyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC 14 | AQoCggEBAL7pd7TChZF0U21aCfxUIzdUHm4siWxcQ678xRerDI2hXmThiUyVKnHS 15 | CeSB+gDBXG4qoRHSEcwq7J1YhFscsKz6o4ktsWLqVowGSWNbW92ZbtjOGkTD3xdp 16 | O8Fqfgcs5Lq1yK517nrbtEp6OXEWcoWv15voP4wV7Z9HjCP6v5N1MmrPN187wDMH 17 | W1meJqxQ/7LiULgVQMVV/U6qLOhUeNpl/06CqxScU1bfnbep5SohUG+z6d8CUaPX 18 | 55EhGtAPzXNJAHDSkiNgSKkPr1USJ9YiXusqmjcPChRfkT77kROjWnxgV+oucF+T 19 | ja+Ist8acKy2sgCidhUyuXCWG44bIf8CAwEAAaOCAhwwggIYMCcGA1UdEQQgMB6C 20 | D3d3dy50d2l0dGVyLmNvbYILdHdpdHRlci5jb20wCQYDVR0TBAIwADAdBgNVHQ4E 21 | FgQUtXiQRnmvbuddQEjER8bw4CjBMYQwCwYDVR0PBAQDAgWgMEIGA1UdHwQ7MDkw 22 | N6A1oDOGMWh0dHA6Ly9FVlNlY3VyZS1jcmwudmVyaXNpZ24uY29tL0VWU2VjdXJl 23 | MjAwNi5jcmwwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcXBjAqMCgGCCsGAQUFBwIB 24 | FhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMB0GA1UdJQQWMBQGCCsGAQUF 25 | BwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBT8ilC6nrklWntVhU+VAGOP6VhrQzB8 26 | BggrBgEFBQcBAQRwMG4wLQYIKwYBBQUHMAGGIWh0dHA6Ly9FVlNlY3VyZS1vY3Nw 27 | LnZlcmlzaWduLmNvbTA9BggrBgEFBQcwAoYxaHR0cDovL0VWU2VjdXJlLWFpYS52 28 | ZXJpc2lnbi5jb20vRVZTZWN1cmUyMDA2LmNlcjBuBggrBgEFBQcBDARiMGChXqBc 29 | MFowWDBWFglpbWFnZS9naWYwITAfMAcGBSsOAwIaBBRLa7kolgYMu9BSOJsprEsH 30 | iyEFGDAmFiRodHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvMS5naWYwDQYJ 31 | KoZIhvcNAQEFBQADggEBAAqg81oADEdE+/Clm4Q43avFTkpuHkpYbu0bDvSVhoMS 32 | n12b0CAtIgY7Sg+kI0/T0PaaDDxy6lEm8YAu/NLNvgXhIEYKxZQ7sUrKrfY+avdM 33 | PumYGkWeQ0xEf0ZLbGCfp9DA+cwxGgZaxT0HdhLhSZOvlw3F3vWezUuriUYacRL6 34 | AW1EzC3uU2zj6T0z2v75Xa8u6AwY6YqAoMJCyR12bc7sGkRoD0ak27DdvP56qh5N 35 | 0tjHHMI1d6IJs0TAO26/SVI7YlQXEstKHk9iJzappwZ/0HZJsepX7jIxvlxyKKGb 36 | 8MQGjSCwx8bY2PbYaLe0rkk2IjH0aMUlHW77DpNAK40= 37 | -----END CERTIFICATE----- 38 | 39 | -------------------------------------------------------------------------------- /test/certs/wikipedia.org.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIKCTCCCPGgAwIBAgIQByTuqXxV8ldeKIukzPIOjjANBgkqhkiG9w0BAQUFADBm 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j 5 | ZSBDQS0zMB4XDTEyMTAyMjAwMDAwMFoXDTE2MDEyMDEyMDAwMFoweTELMAkGA1UE 6 | BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lz 7 | Y28xIzAhBgNVBAoTGldpa2ltZWRpYSBGb3VuZGF0aW9uLCBJbmMuMRgwFgYDVQQD 8 | DA8qLndpa2lwZWRpYS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 9 | AQDUaZWLhfJEgERN+dzp/AKvU/46RHPMPwfs8z6olxVP1EPDBpop9VksPl+q93lp 10 | mi6s3faOWB5Rplqp+u/1rKHhlr+2ah9qQ1Np6Xb6gKNVpZA/SSBuSexuBXwWYIgD 11 | IXivkun3u7EuzoxME/nMmN7whnbQ2JIDGM8LcfsDPjFKyVywtu3Ry8YqHRw+h3be 12 | tKaKdGzBYQQA7tDmydIGu/yJuxnmBmAyLztoE0Y4iH04/NyhIzzRfiDOkI7g99Ky 13 | tRrDYdgY4xPqLFTo8qVaTD1CRwa0stPdz79UWRmEn9k5P02GWdfxHvRvYh2Wk8eo 14 | 53rJIypXfA+65W7vbWvq16MFAgMBAAGjggaeMIIGmjAfBgNVHSMEGDAWgBRQ6nOJ 15 | 2yn7EI+e5QEg1N55mUiD9zAdBgNVHQ4EFgQUvwEkt6ooB6QGZazDQAb+1ljDE0Mw 16 | ggNxBgNVHREEggNoMIIDZIIPKi53aWtpcGVkaWEub3Jngg13aWtpcGVkaWEub3Jn 17 | gg9tLndpa2lwZWRpYS5vcmeCESoubS53aWtpcGVkaWEub3Jngg13aWtpYm9va3Mu 18 | b3Jngg9tLndpa2lib29rcy5vcmeCDyoud2lraWJvb2tzLm9yZ4IRKi5tLndpa2li 19 | b29rcy5vcmeCDHdpa2lkYXRhLm9yZ4IObS53aWtpZGF0YS5vcmeCDioud2lraWRh 20 | dGEub3JnghAqLm0ud2lraWRhdGEub3Jngg13aWtpbWVkaWEub3Jngg9tLndpa2lt 21 | ZWRpYS5vcmeCDyoud2lraW1lZGlhLm9yZ4IRKi5tLndpa2ltZWRpYS5vcmeCF3dp 22 | a2ltZWRpYWZvdW5kYXRpb24ub3JnghltLndpa2ltZWRpYWZvdW5kYXRpb24ub3Jn 23 | ghkqLndpa2ltZWRpYWZvdW5kYXRpb24ub3JnghsqLm0ud2lraW1lZGlhZm91bmRh 24 | dGlvbi5vcmeCDHdpa2luZXdzLm9yZ4IObS53aWtpbmV3cy5vcmeCDioud2lraW5l 25 | d3Mub3JnghAqLm0ud2lraW5ld3Mub3Jngg13aWtpcXVvdGUub3Jngg9tLndpa2lx 26 | dW90ZS5vcmeCDyoud2lraXF1b3RlLm9yZ4IRKi5tLndpa2lxdW90ZS5vcmeCDndp 27 | a2lzb3VyY2Uub3JnghBtLndpa2lzb3VyY2Uub3JnghAqLndpa2lzb3VyY2Uub3Jn 28 | ghIqLm0ud2lraXNvdXJjZS5vcmeCD3dpa2l2ZXJzaXR5Lm9yZ4IRbS53aWtpdmVy 29 | c2l0eS5vcmeCESoud2lraXZlcnNpdHkub3JnghMqLm0ud2lraXZlcnNpdHkub3Jn 30 | gg53aWtpdm95YWdlLm9yZ4IQbS53aWtpdm95YWdlLm9yZ4IQKi53aWtpdm95YWdl 31 | Lm9yZ4ISKi5tLndpa2l2b3lhZ2Uub3Jngg53aWt0aW9uYXJ5Lm9yZ4IQbS53aWt0 32 | aW9uYXJ5Lm9yZ4IQKi53aWt0aW9uYXJ5Lm9yZ4ISKi5tLndpa3Rpb25hcnkub3Jn 33 | gg1tZWRpYXdpa2kub3Jngg8qLm1lZGlhd2lraS5vcmeCD20ubWVkaWF3aWtpLm9y 34 | Z4IRKi5tLm1lZGlhd2lraS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG 35 | CCsGAQUFBwMBBggrBgEFBQcDAjBhBgNVHR8EWjBYMCqgKKAmhiRodHRwOi8vY3Js 36 | My5kaWdpY2VydC5jb20vY2EzLWcyMC5jcmwwKqAooCaGJGh0dHA6Ly9jcmw0LmRp 37 | Z2ljZXJ0LmNvbS9jYTMtZzIwLmNybDCCAcQGA1UdIASCAbswggG3MIIBswYJYIZI 38 | AYb9bAEBMIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3dy5kaWdpY2VydC5jb20v 39 | c3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUFBwICMIIBVh6CAVIAQQBu 40 | AHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0 41 | AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4AYwBl 42 | ACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAAUwAg 43 | AGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAAQQBn 44 | AHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkAYQBi 45 | AGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIAYQB0 46 | AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUALjB7 47 | BggrBgEFBQcBAQRvMG0wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 48 | LmNvbTBFBggrBgEFBQcwAoY5aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp 49 | Z2lDZXJ0SGlnaEFzc3VyYW5jZUNBLTMuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI 50 | hvcNAQEFBQADggEBAB9ursMdWKCOKytcZnaxEo5HDMt8DALL7stH2gIDzT2AJC3T 51 | 1C2w9kZs4ck+ZgPfhaPHlStHRG83/VyzMvEnMWU9ErbrQV3Yw852VPPZF9qg3BDR 52 | II6FI3zRBBF0zZ9EB6IuQTa2QNL1w7cQUWlyRN3edaVaT1MFi4904u2Q2KeFriPp 53 | ++jP0tX3YWmqgFOuXIX4QfZsrMQa1yRKtz/1fA0GPRHK+6lP61xpgkMMXmQJOdu8 54 | ifrxJMTON7H1eA5JSdfBm29lyvs3AqUMyb0xTCnl1BOZzxel/KrMsi48rZju4sB5 55 | fgarsxY/bPnrptsyxl5YPeskRUqr/WvEhxDczDI= 56 | -----END CERTIFICATE----- 57 | 58 | -------------------------------------------------------------------------------- /test/certs/yahoo.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIE6jCCBFOgAwIBAgIDEIGKMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT 3 | MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 4 | aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTAwNDAxMjMwMDE0WhcNMTUwNzAzMDQ1MDAw 5 | WjCBjzEpMCcGA1UEBRMgMmc4YU81d0kxYktKMlpENTg4VXNMdkRlM2dUYmc4RFUx 6 | CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5u 7 | eXZhbGUxFDASBgNVBAoTC1lhaG9vICBJbmMuMRYwFAYDVQQDEw13d3cueWFob28u 8 | Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6ZM1jHCkL8rlEKse 9 | 1riTTxyC3WvYQ5m34TlFK7dK4QFI/HPttKGqQm3aVB1Fqi0aiTxe4YQMbd++jnKt 10 | djxcpi7sJlFxjMZs4umr1eGo2KgTgSBAJyhxo23k+VpK1SprdPyM3yEfQVdV7JWC 11 | 4Y71CE2nE6+GbsIuhk/to+jJMO7jXx/430jvo8vhNPL6GvWe/D6ObbnxS72ynLSd 12 | mLtaltykOvZEZiXbbFKgIaYYmCgh89FGVvBkUbGM/Wb5Voiz7ttQLLxKOYRj8Mdk 13 | TZtzPkM9scIFG1naECPvCxw0NyMyxY3nFOdjUKJ79twanmfCclX2ZO/rk1CpiOuw 14 | lrrr/QIDAQABo4ICDjCCAgowDgYDVR0PAQH/BAQDAgTwMB0GA1UdDgQWBBSmrfKs 15 | 68m+dDUSf+S7xJrQ/FXAlzA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdl 16 | b3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDCCAVsGA1UdEQSCAVIwggFOgg13 17 | d3cueWFob28uY29tggl5YWhvby5jb22CDHVzLnlhaG9vLmNvbYIMa3IueWFob28u 18 | Y29tggx1ay55YWhvby5jb22CDGllLnlhaG9vLmNvbYIMZnIueWFob28uY29tggxp 19 | bi55YWhvby5jb22CDGNhLnlhaG9vLmNvbYIMYnIueWFob28uY29tggxkZS55YWhv 20 | by5jb22CDGVzLnlhaG9vLmNvbYIMbXgueWFob28uY29tggxpdC55YWhvby5jb22C 21 | DHNnLnlhaG9vLmNvbYIMaWQueWFob28uY29tggxwaC55YWhvby5jb22CDHFjLnlh 22 | aG9vLmNvbYIMdHcueWFob28uY29tggxoay55YWhvby5jb22CDGNuLnlhaG9vLmNv 23 | bYIMYXUueWFob28uY29tggxhci55YWhvby5jb22CDHZuLnlhaG9vLmNvbTAfBgNV 24 | HSMEGDAWgBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHSUEFjAUBggrBgEFBQcD 25 | AQYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAp9WOMtcDMM5T0yfPecGv5QhH 26 | RJZRzgeMPZitLksr1JxxicJrdgv82NWq1bw8aMuRj47ijrtaTEWXaCQCy00yXodD 27 | zoRJVNoYIvY1arYZf5zv9VZjN5I0HqUc39mNMe9XdZtbkWE+K6yVh6OimKLbizna 28 | inu9YTrN/4P/w6KzHho= 29 | -----END CERTIFICATE----- 30 | 31 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var x509 = require('../index'), 2 | fs = require('fs'), 3 | path = require('path'), 4 | assert = require('assert'); 5 | 6 | // All cert files should read without throwing an error. 7 | // Simple enough test, no? 8 | fs.readdirSync(path.join(__dirname, 'certs')).forEach(function (file) { 9 | console.log("File: %s", file); 10 | console.log(x509.parseCert(path.join(__dirname, 'certs', file))); 11 | // x509.parseCert(path.join(__dirname, 'certs', file)); 12 | console.log(); 13 | }); 14 | 15 | 16 | x509.verify( 17 | path.join(__dirname, 'certs/enduser-example.com.crt'), 18 | path.join(__dirname, 'CA_chains/enduser-example.com.chain'), 19 | function (err) { 20 | assert.strictEqual(err, null); 21 | } 22 | ); 23 | 24 | 25 | 26 | x509.verify( 27 | path.join(__dirname, 'certs/acaline.com.crt'), 28 | path.join(__dirname, 'CA_chains/enduser-example.com.chain'), 29 | function (err, result) { 30 | assert.throws(assert.ifError.bind(null, err), /unable to get local issuer/) 31 | } 32 | ); 33 | 34 | x509.verify( 35 | path.join(__dirname, 'certs/notexisting.com.crt'), 36 | path.join(__dirname, 'CA_chains/enduser-example.com.chain'), 37 | function (err, result) { 38 | assert.throws(assert.ifError.bind(null, err), /ENOENT/) 39 | } 40 | ); 41 | 42 | x509.verify( 43 | path.join(__dirname, 'certs/equifax.crt'), 44 | path.join(__dirname, '/test.js'), 45 | function(err, result) { 46 | assert.throws(assert.ifError.bind(null, err), /Error loading CA chain file/) 47 | } 48 | ); 49 | 50 | x509.verify( 51 | path.join(__dirname, '/test.js'), 52 | path.join(__dirname, 'CA_chains/enduser-example.com.chain'), 53 | function(err, result) { 54 | assert.throws(assert.ifError.bind(null, err), /Failed to load cert/) 55 | } 56 | ); --------------------------------------------------------------------------------