-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.MD2Digest;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.engines.RC4Engine;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.BERInputStream;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.ibex.util.Log;
-import java.net.*;
-import java.io.*;
-import java.util.*;
-import java.math.*;
-import java.text.*;
-
-/**
-
- TinySSL: a tiny SSL implementation in Java, built on the
- bouncycastle.org lightweight crypto library.
-
- This class implements an SSLv3 client-side socket, with the
- SSL_RSA_EXPORT_WITH_RC4_40_MD5 and SSL_RSA_WITH_RC4_128_MD5 cipher
- suites, as well as certificate chain verification against a
- collection of 93 built-in Trusted Root CA public keys (the same 93
- included with Microsoft Internet Explorer 5.5 SP2).
-
- As of 07-Dec-01, the zipped bytecode for this class is 43k, and the
- subset of bouncycastle it requires is 82k.
-
- This class should work correctly on any Java 1.1 compliant
- platform. The java.security.* classes are not used.
-
- The main design goal for this class was the smallest possible body
- of code capable of connecting to 99% of all active HTTPS
- servers. Although this class is useful in many other situations
- (IMAPS, Secure SMTP, etc), the author will refuse all feature
- requests and submitted patches which go beyond this scope.
-
- Because of the limited goals of this class, certain abstractions
- have been avoided, and certain parameters have been
- hard-coded. "Magic numbers" are often used instead of "static final
- int"'s, although they are usually accompanied by a descriptive
- comment. Numeric offsets into byte arrays are also favored over
- DataInputStream(ByteArrayInputStream(foo))'s.
-
- Much thanks and credit go to the BouncyCastle team for producing
- such a first-class library, and for helping me out on the
- dev-crypto mailing list while I was writing this.
-
- Revision History:
-
- 1.0 07-Dec-01 Initial Release
-
- 1.01 15-Mar-02 Added PKCS1 class to avoid dependancy on java.security.SecureRandom
-
- 1.02 27-Mar-02 Fixed a bug which would hang the connection when more than one
- Handshake message appeared in the same TLS Record
-
- 1.03 10-Aug-02 Fixed a vulnerability outlined at
- http://online.securityfocus.com/archive/1/286290
-
- 1.04 12-Dec-03 Renamed to org.ibex.SSL, fixed race condition
-
-*/
-
-public class SSL extends Socket {
-
- // Simple Test //////////////////////////////////////////////
-
- public static void main(String[] args) {
- Log.on = true;
- try {
- Socket s = new SSL("www.paypal.com", 443);
- PrintWriter pw = new PrintWriter(s.getOutputStream());
- BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
- pw.println("GET / HTTP/1.0");
- pw.println("");
- pw.flush();
-
- while(true) {
- String s2 = br.readLine();
- if (s2 == null) return;
- Log.info(SSL.class, s2);
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- // Static Data //////////////////////////////////////////////
-
- public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
- static SubjectPublicKeyInfo[] trusted_CA_public_keys;
- static String[] trusted_CA_public_key_identifiers;
- public static byte[] pad1 = new byte[48];
- public static byte[] pad2 = new byte[48];
- public static byte[] pad1_sha = new byte[40];
- public static byte[] pad2_sha = new byte[40];
- static byte[] randpool;
- static long randcnt = 0;
-
- // Cipher State //////////////////////////////////////////////
-
- public byte[] server_random = new byte[32];
- public byte[] client_random = new byte[32];
- public byte[] client_write_MAC_secret = new byte[16];
- public byte[] server_write_MAC_secret = new byte[16];
- public byte[] client_write_key = null;
- public byte[] server_write_key = null;
- public byte[] master_secret = null;
-
- /** the bytes of the ServerKeyExchangeMessage, null if none recieved */
- public byte[] serverKeyExchange = null;
-
- /** true iff the server asked for a certificate */
- public boolean cert_requested = false;
-
- public X509CertificateStructure server_cert = null;
-
- public SSLOutputStream os = null;
- public SSLInputStream is = null;
-
- String hostname;
-
- /** if true, we don't mind if the server's cert isn't signed by a CA. USE WITH CAUTION! */
- boolean ignoreUntrustedCert = false;
-
- /** the concatenation of all the bytes of all handshake messages sent or recieved */
- public byte[] handshakes = new byte[] { };
-
- /** true iff we're using SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
- boolean export = false;
-
- public InputStream getInputStream() throws IOException { return is != null ? is : super.getInputStream(); }
- public OutputStream getOutputStream() throws IOException { return os != null ? os : super.getOutputStream(); }
-
- public SSL(String host, int port) throws IOException { this(host, port, true, false); }
- public SSL(String host, int port, boolean negotiateImmediately) throws IOException { this(host, port, negotiateImmediately, false); }
- public SSL(String host, int port, boolean negotiateImmediately, boolean ignoreUntrustedCert) throws IOException {
- super(host, port);
- if (!initializationFinished) {
- synchronized(SSL.class) {
- while (!initializationFinished)
- try { SSL.class.wait(); } catch (Exception e) { }
- }
- }
- hostname = host;
- this.ignoreUntrustedCert = ignoreUntrustedCert;
- if (negotiateImmediately) negotiate();
- }
-
- /** negotiates the SSL connection */
- public void negotiate() throws IOException {
- os = new SSLOutputStream(super.getOutputStream());
- is = new SSLInputStream(super.getInputStream());
- os.writeClientHello();
- is.readServerHandshakes();
- os.sendClientHandshakes();
- is.readServerFinished();
- }
-
- class SSLInputStream extends InputStream {
-
- /** the underlying inputstream */
- DataInputStream raw;
-
- /** the server's sequence number */
- public int seq_num = 0;
-
- /** the decryption engine */
- public RC4Engine rc4 = null;
-
- /** pending bytes -- decrypted, but not yet fed to consumer */
- byte[] pend = null;
- int pendstart = 0;
- int pendlen = 0;
-
- public void mark() { }
- public void reset() { }
- public boolean markSupported() { return false; }
- public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
- public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
- public int available() throws IOException { return pendlen; }
-
- public int read() throws IOException {
- byte[] singlebyte = new byte[1];
- int numread = read(singlebyte);
- if (numread != 1) return -1;
- return (int)singlebyte[0];
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- if (pendlen == 0) {
- pend = readRecord();
- if (pend == null) return -1;
- pendstart = 0;
- pendlen = pend.length;
- }
- int ret = Math.min(len, pendlen);
- System.arraycopy(pend, pendstart, b, off, ret);
- pendlen -= ret;
- pendstart += ret;
- return ret;
- }
-
- /** reads and decrypts exactly one record; blocks if unavailable */
- public byte[] readRecord() throws IOException {
-
- // we only catch EOFException here, because anywhere else
- // would be "unusual", and we *want* and EOFException in
- // those cases
- byte type;
- try { type = raw.readByte();
- } catch (EOFException e) {
- if (Log.on) Log.info(this, "got EOFException reading packet type");
- return null;
- }
-
- byte ver_major = raw.readByte();
- byte ver_minor = raw.readByte();
- short len = raw.readShort();
- if (Log.on) Log.info(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
-
- byte[] ret = new byte[len];
- raw.readFully(ret);
-
- // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours
- if (type == 20) {
- if (Log.on) Log.info(this, "got ChangeCipherSpec; ignoring");
- seq_num = 0;
- return readRecord();
- }
-
- byte[] decrypted_payload;
-
- // if crypto hasn't been enabled yet; skip crypt and hash
- if (rc4 == null) decrypted_payload = ret;
- else {
- // decrypt the payload
- decrypted_payload = new byte[len - 16];
- rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
-
- // check the MAC
- byte[] MAC = new byte[16];
- rc4.processBytes(ret, len - 16, 16, MAC, 0);
- byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
- for(int i=0; i<MAC.length; i++)
- if (MAC[i] != ourMAC[i])
- throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
- }
-
- if (type == 21) {
- if (decrypted_payload[1] > 1) {
- throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
- } else if (decrypted_payload[1] == 0) {
- if (Log.on) Log.info(this, "server requested connection closure; returning null");
- return null;
- } else {
- if (Log.on) Log.info(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
- return readRecord();
- }
-
- } else if (type == 22) {
- if (Log.on) Log.info(this, "read a handshake");
-
- } else if (type != 23) {
- if (Log.on) Log.info(this, "unexpected record type: " + type + "; skipping");
- return readRecord();
-
- }
-
- if (Log.on) Log.info(this, " returning " + decrypted_payload.length + " byte record payload");
- return decrypted_payload;
- }
-
- private byte[] readHandshake() throws IOException {
- // acquire a handshake message
- byte type = (byte)read();
- int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff);
- byte[] rec = new byte[len + 4];
- rec[0] = type;
- rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff);
- rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff);
- rec[3] = (byte)((len & 0x000000ff) & 0xff);
- if (len > 0) read(rec, 4, len);
- return rec;
- }
-
- /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */
- public void readServerHandshakes() throws IOException {
- for(;;) {
-
- byte[] rec = readHandshake();
- handshakes = concat(new byte[][] { handshakes, rec });
-
- switch(rec[0]) {
- case 2: // ServerHello
- if (Log.on) Log.info(this, "got ServerHello");
- byte ver_major = rec[4];
- byte ver_minor = rec[5];
- System.arraycopy(rec, 6, server_random, 0, server_random.length);
- short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
- short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
-
- if (cipher_low == 0x04 || cipher_high != 0x00) {
- export = false;
- if (Log.on) Log.info(this, "using SSL_RSA_WITH_RC4_128_MD5");
-
- } else if (cipher_low == 0x03 || cipher_high != 0x00) {
- export = true;
- if (Log.on) Log.info(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
-
- } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
- " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
- "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
-
- byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
- if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
- " but we don't support compression");
- break;
-
- case 11: // Server's certificate(s)
- if (Log.on) Log.info(this, "got Server Certificate(s)");
- int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
- int numcerts = 0;
- X509CertificateStructure last_cert = null;
- X509CertificateStructure this_cert = null;
-
- for(int i=0; i<numcertbytes;) {
- int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
- try {
- DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
- this_cert = new X509CertificateStructure((DERSequence)dIn.readObject());
- } catch (Exception e) {
- SSLException t = new SSLException("error decoding server certificate: " + e);
- t.fillInStackTrace();
- throw t;
- }
-
- if (server_cert == null) {
- server_cert = this_cert;
- TBSCertificateStructure tbs = server_cert.getTBSCertificate();
-
- // gross hack to extract the Common Name so we can compare it to the server hostname
- String CN = tbs.getSubject().toString() + " ";
- boolean good = false;
- for(int j=0; j<CN.length() - 3; j++)
- if (CN.substring(j, j+3).equals("CN=")) {
- good = true;
- CN = CN.substring(j+3, CN.indexOf(' ', j+3));
- break;
- }
-
- if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
- if (!ignoreUntrustedCert && !CN.equalsIgnoreCase(hostname))
- throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
-
- SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss-z");
-
- // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
- String s = tbs.getStartDate().getTime();
- s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8) + "-" +
- s.substring(8, 10) + "-" + s.substring(10, 12) + "-" +
- s.substring(12, 14) + "-" + s.substring(14);
-
- Date startDate = dateF.parse(s, new ParsePosition(0));
-
- s = tbs.getEndDate().getTime();
- s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
- s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
- Date endDate = dateF.parse(s, new ParsePosition(0));
-
- Date now = new Date();
- if (!ignoreUntrustedCert && now.after(endDate))
- throw new SSLException("server certificate expired on " + endDate);
- if (!ignoreUntrustedCert && now.before(startDate))
- throw new SSLException("server certificate will not be valid until " + startDate);
-
- Log.info(this, "server cert (name, validity dates) checks out okay");
-
- } else {
-
- // don't check the top cert since some very old root certs lack a BasicConstraints field.
- if (certlen + 3 + i < numcertbytes) {
- // defend against Mike Benham's attack
- X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints);
- if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block");
- DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets()));
- BasicConstraints bc = new BasicConstraints((DERSequence)dis.readObject());
- if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing");
- }
-
- if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
- throw new SSLException("the server sent a broken chain of certificates");
- }
-
- last_cert = this_cert;
- i += certlen + 3;
- numcerts++;
- }
- if (Log.on) Log.info(this, " Certificate (" + numcerts + " certificates)");
-
- if (ignoreUntrustedCert) break;
-
- boolean good = false;
-
- // pass 1 -- only check CA's whose subject is a partial match
- String subject = this_cert.getSubject().toString();
- for(int i=0; i<trusted_CA_public_keys.length; i++) {
- if (subject.indexOf(trusted_CA_public_key_identifiers[i]) != -1 && isSignedBy(this_cert, trusted_CA_public_keys[i])) {
- if (Log.on) Log.info(this, "pass 1: server cert was signed by trusted CA " + i);
- good = true;
- break;
- }
- }
-
- // pass 2 -- try all certs
- if (!good)
- for(int i=0; i<trusted_CA_public_keys.length; i++) {
- if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
- if (Log.on) Log.info(this, "pass 2: server cert was signed by trusted CA " + i);
- good = true;
- break;
- }
- }
-
- if (!good) throw new SSLException("server cert was not signed by a trusted CA");
- break;
-
- case 12:
- if (Log.on) Log.info(this, "got ServerKeyExchange");
- serverKeyExchange = rec;
- break;
-
- case 13:
- if (Log.on) Log.info(this, "got Request for Client Certificates");
- cert_requested = true;
- break;
-
- case 14: if (Log.on) Log.info(this, " ServerHelloDone"); return;
- default: throw new SSLException("unknown handshake of type " + rec[0]);
- }
- }
- }
-
- public void readServerFinished() throws IOException {
-
- byte[] rec = readHandshake();
- if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
-
- byte[] expectedFinished = concat(new byte[][] {
- md5(new byte[][] { master_secret, pad2,
- md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
- master_secret, pad1 }) }),
- sha(new byte[][] { master_secret, pad2_sha,
- sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
- master_secret, pad1_sha } ) } ) } );
-
- for(int i=0; i<expectedFinished.length; i++)
- if (expectedFinished[i] != rec[i + 4])
- throw new SSLException("server Finished message mismatch!");
-
- if (Log.on) Log.info(this, "server finished message checked out okay!");
- }
-
- }
-
- class SSLOutputStream extends OutputStream {
-
- /** the underlying outputstream */
- DataOutputStream raw;
-
- /** the sequence number for sending */
- public long seq_num = 0;
-
- /** the encryption engine for sending */
- RC4Engine rc4 = null;
-
- public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
- public void flush() throws IOException { raw.flush(); }
- public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
- public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
- public void close() throws IOException {
- write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
- raw.close();
- }
-
- /** writes a single SSL Record */
- public void write(byte[] payload, int off, int len, byte type) throws IOException {
-
- // largest permissible frame is 2^14 octets
- if (len > 1 << 14) {
- write(payload, off, 1 << 14, type);
- write(payload, off + 1 << 14, len - 1 << 14, type);
- return;
- }
-
- raw.writeByte(type);
- raw.writeShort(0x0300);
-
- if (rc4 == null) {
- raw.writeShort(len);
- raw.write(payload, off, len);
-
- } else {
- byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
- byte[] encryptedPayload = new byte[MAC.length + len];
- rc4.processBytes(payload, off, len, encryptedPayload, 0);
- rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
- raw.writeShort(encryptedPayload.length);
- raw.write(encryptedPayload);
-
- }
-
- seq_num++;
- }
-
- /** tacks a handshake header onto payload before sending it */
- public void writeHandshake(int type, byte[] payload) throws IOException {
- byte[] real_payload = new byte[payload.length + 4];
- System.arraycopy(payload, 0, real_payload, 4, payload.length);
- real_payload[0] = (byte)(type & 0xFF);
- intToBytes(payload.length, real_payload, 1, 3);
- handshakes = concat(new byte[][] { handshakes, real_payload });
- write(real_payload, 0, real_payload.length, (byte)22);
- }
-
- public void sendClientHandshakes() throws IOException {
-
- if (Log.on) Log.info(this, "shaking hands");
- if (cert_requested) {
- if (Log.on) Log.info(this, "telling the server we have no certificates");
- writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
- }
-
- // generate the premaster secret
- byte[] pre_master_secret = new byte[48];
- pre_master_secret[0] = 0x03; // first two bytes of premaster secret are our version number
- pre_master_secret[1] = 0x00;
- getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
-
- // encrypt and send the pre_master_secret
- try {
- byte[] encrypted_pre_master_secret;
-
- SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
- RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
- BigInteger modulus = rsa_pks.getModulus();
- BigInteger exponent = rsa_pks.getPublicExponent();
-
- if (serverKeyExchange != null) {
-
- AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
- rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
-
- int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
- byte[] b_modulus = new byte[modulus_size];
- System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
- modulus = new BigInteger(1, b_modulus);
-
- int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
- byte[] b_exponent = new byte[exponent_size];
- System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
- exponent = new BigInteger(1, b_exponent);
-
- byte[] server_params = new byte[modulus_size + exponent_size + 4];
- System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
-
- byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
- sha(new byte[][] { client_random, server_random, server_params } ) } );
-
- byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
- serverKeyExchange.length - 6 - server_params.length);
-
- for(int i=0; i<expectedSignature.length; i++)
- if (expectedSignature[i] != recievedSignature[i])
- throw new SSLException("ServerKeyExchange message had invalid signature " + i);
-
- if (Log.on) Log.info(this, "ServerKeyExchange successfully processed");
- }
-
- AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
- rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
-
- encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
- writeHandshake(16, encrypted_pre_master_secret);
-
- } catch (Exception e) {
- SSLException t = new SSLException("exception encrypting premaster secret");
- t.fillInStackTrace();
- throw t;
- }
-
- // ChangeCipherSpec
- if (Log.on) Log.info(this, "Handshake complete; sending ChangeCipherSpec");
- write(new byte[] { 0x01 }, 0, 1, (byte)20);
- seq_num = 0;
-
- // compute master_secret
- master_secret = concat(new byte[][] {
- md5(new byte[][] { pre_master_secret,
- sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
- md5(new byte[][] { pre_master_secret,
- sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
- md5(new byte[][] { pre_master_secret,
- sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
- } );
-
- // construct the key material
- byte[] key_material = new byte[] { };
- for(int i=0; key_material.length < 72; i++) {
- byte[] crap = new byte[i + 1];
- for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
- key_material = concat(new byte[][] { key_material,
- md5(new byte[][] { master_secret,
- sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
- }
-
- client_write_key = new byte[export ? 5 : 16];
- server_write_key = new byte[export ? 5 : 16];
-
- System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
- System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
- System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
- System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
-
- if (export) {
- // see SSLv3 spec, 6.2.2 for explanation
- byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
- byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
- client_write_key = new byte[16];
- server_write_key = new byte[16];
- System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
- System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
- }
-
- rc4 = new RC4Engine();
- rc4.init(true, new KeyParameter(client_write_key));
- is.rc4 = new RC4Engine();
- is.rc4.init(false, new KeyParameter(server_write_key));
-
- // send Finished
- writeHandshake(20, concat(new byte[][] {
- md5(new byte[][] { master_secret, pad2,
- md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
- master_secret, pad1 }) }),
- sha(new byte[][] { master_secret, pad2_sha,
- sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
- master_secret, pad1_sha } ) })
- }));
- raw.flush();
- if (Log.on) Log.info(this, "wrote Finished message");
-
- }
-
- public void writeClientHello() throws IOException {
-
- if (Log.on) Log.info(this, "sending ClientHello");
- int unixtime = (int)(System.currentTimeMillis() / (long)1000);
-
- byte[] out = new byte[] {
- 0x03, 0x00, // client version (SSLv3.0)
-
- // space for random bytes
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0,
-
- 0x0, // empty vector for sessionid
- 0x0, 0x4, 0x0, 0x4, 0x0, 0x3, // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
- 0x1, 0x0 // we only support one compression method: none
- };
-
- // don't need to use secure random here since it's sent in the clear
- Random rand = new Random(System.currentTimeMillis());
- rand.nextBytes(client_random);
- intToBytes(unixtime, client_random, 0, 4);
- System.arraycopy(client_random, 0, out, 2, client_random.length);
-
- writeHandshake(1, out);
- flush();
- }
- }
-
- // Static Helpers ////////////////////////////////////////////////////////////////////
-
- /** copy the least significant num bytes of val into byte array b, startint at offset */
- public static void intToBytes(long val, byte[] b, int offset, int num) {
- for(int i=0; i<num; i++)
- b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
- }
-
- /** fills b with random bytes */
- public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
- MD5Digest md5 = new MD5Digest();
- byte[] b2 = new byte[16];
- while(len > 0) {
- md5.reset();
- md5.update(randpool, 0, randpool.length);
- intToBytes(randcnt++, b2, 0, 8);
- md5.update(b2, 0, 8);
- md5.doFinal(b2, 0);
- int n = len < 16 ? len : 16;
- System.arraycopy(b2, 0, b, offset, n);
- len -= n;
- offset += n;
- }
- }
-
- public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
- byte[] MAC = new byte[16];
- MD5Digest md5 = new MD5Digest();
- md5.update(MAC_secret, 0, MAC_secret.length);
- md5.update(pad1, 0, pad1.length);
-
- byte[] b = new byte[11];
- intToBytes(seq_num, b, 0, 8);
- b[8] = type;
- intToBytes(len, b, 9, 2);
- md5.update(b, 0, b.length);
-
- md5.update(payload, off, len);
- md5.doFinal(MAC, 0);
- md5.reset();
- md5.update(MAC_secret, 0, MAC_secret.length);
- md5.update(pad2, 0, pad2.length);
- md5.update(MAC, 0, MAC.length);
- md5.doFinal(MAC, 0);
-
- return MAC;
- }
-
- public static byte[] concat(byte[][] inputs) {
- int total = 0;
- for(int i=0; i<inputs.length; i++) total += inputs[i].length;
- byte[] ret = new byte[total];
- int pos = 0;
- for(int i=0; i<inputs.length; i++) {
- System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
- pos += inputs[i].length;
- }
- return ret;
- }
-
- SHA1Digest master_sha1 = new SHA1Digest();
- public byte[] sha(byte[][] inputs) {
- master_sha1.reset();
- for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
- byte[] ret = new byte[master_sha1.getDigestSize()];
- master_sha1.doFinal(ret, 0);
- return ret;
- }
-
- MD5Digest master_md5 = new MD5Digest();
- public byte[] md5(byte[][] inputs) {
- master_md5.reset();
- for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
- byte[] ret = new byte[master_md5.getDigestSize()];
- master_md5.doFinal(ret, 0);
- return ret;
- }
-
- // FEATURE: improve error reporting in here
- /** returns true iff certificate "signee" is signed by public key "signer" */
- public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
-
- Digest hash = null;
-
- String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
- if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
- else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
- else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
- else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
-
- try {
- // decrypt the signature using the signer's public key
- byte[] ED = signee.getSignature().getBytes();
- SubjectPublicKeyInfo pki = signer;
- RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
- BigInteger modulus = rsa_pks.getModulus();
- BigInteger exponent = rsa_pks.getPublicExponent();
- AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
- rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
-
- // Decode the embedded octet string
- byte[] D = rsa.processBlock(ED, 0, ED.length);
- BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
- DERObject derob = beris.readObject();
- DERSequence dercs = (DERSequence)derob;
- DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
- byte[] MD = deros.getOctets();
-
- // generate our own hash
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- DEROutputStream dos = new DEROutputStream(baos);
- dos.writeObject(signee.getTBSCertificate());
- dos.flush();
- byte[] b = baos.toByteArray();
- hash.update(b, 0, b.length);
- byte[] md_out = new byte[MD.length];
- hash.doFinal(md_out, 0);
-
- // compare our hash to the signed hash
- for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
- return true;
-
- } catch (Exception e) {
- return false;
-
- }
- }
-
- // Embedded Trusted Public Keys //////////////////////////////////////////////
-
- /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
- static String[] base64_encoded_trusted_CA_public_keys = new String[] {
-
- "CN=ABA.ECOM Root CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
- "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
- "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
- "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
- "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
- "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
-
- "O=ViaCode",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
- "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
- "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
- "IBAw==",
-
- "CN=Xcert EZ by DST",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
- "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
- "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
- "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
- "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
- "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
-
- "CN=Certiposte Classe A Personne",
- "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
- "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
- "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
- "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
- "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
- "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
-
- "CN=Certiposte Serveur",
- "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
- "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
- "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
- "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
- "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
- "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
-
- "OU=Certisign - Autoridade Certificadora - AC2",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
- "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
- "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
- "IDAQAB",
-
- "OU=Certisign - Autoridade Certificadora - AC4",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
- "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
- "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
- "IDAQAB",
-
- "OU=Certisign Autoridade Certificadora AC1S",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
- "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
- "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
- "IDAQAB",
-
- "OU=Certisign Autoridade Certificadora AC3S",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
- "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
- "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
- "IDAQAB",
-
- "O=Certplus, CN=Class 1 Primary CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
- "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
- "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
- "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
- "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
- "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
-
- "O=Certplus, CN=Class 2 Primary CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
- "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
- "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
- "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
- "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
- "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
-
- "O=Certplus, CN=Class 3 Primary CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
- "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
- "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
- "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
- "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
- "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
-
- "CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
- "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
- "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
- "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
- "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
- "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
-
- "O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
- "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
- "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
- "IDAQAB",
-
- "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
- "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
- "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
- "IDAQAB",
-
- "C=FR, O=Certplus, CN=Class 3P Primary CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
- "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
- "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
- "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
- "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
- "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
-
- "C=FR, O=Certplus, CN=Class 3TS Primary CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
- "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
- "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
- "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
- "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
- "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
-
- "C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority",
- "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
- "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
- "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
- "E=",
-
- "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
- "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
- "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
- "IDAQAB",
-
- "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
- "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
- "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
- "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
- "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
- "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
-
- "C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
- "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
- "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
- "IBAw==",
-
- "OU=National Retail Federation, CN=DST (NRF) RootCA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
- "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
- "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
- "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
- "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
- "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
-
- "OU=United Parcel Service, CN=DST (UPS) RootCA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
- "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
- "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
- "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
- "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
- "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
-
- "CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
- "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
- "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
- "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
- "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
- "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
-
- "CN=DST RootCA X1",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
- "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
- "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
- "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
- "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
- "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
-
- "OU=DSTCA X2, CN=DST RootCA X2",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
- "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
- "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
- "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
- "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
- "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
-
- "C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
- "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
- "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
- "IBAw==",
-
- "C=US, O=Digital Signature Trust Co., OU=DSTCA E1",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
- "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
- "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
- "IBAw==",
-
- "C=US, O=Digital Signature Trust Co., OU=DSTCA E2",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
- "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
- "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
- "IBAw==",
-
- "CN=Entrust.net Certification Authority (2048)",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
- "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
- "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
- "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
- "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
- "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
-
- "CN=Entrust.net Client Certification Authority",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
- "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
- "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
- "IBAw==",
-
- "CN=Entrust.net Secure Server Certification Authority",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
- "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
- "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
- "IBAw==",
-
- "C=US, O=Equifax, OU=Equifax Secure Certificate Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
- "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
- "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
- "IDAQAB",
-
- "C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
- "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
- "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
- "IDAQAB",
-
- "CN=Baltimore EZ by DST",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
- "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
- "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
- "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
- "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
- "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
-
- "C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
- "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
- "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
- "IDAQAB",
-
- "C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
- "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
- "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
- "IDAQAB",
-
- "O=EUnet International, CN=EUnet International Root CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
- "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
- "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
- "IDAQAB",
-
- "CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
- "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
- "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
- "IDAQAB",
-
- "CN=FESTE, Verified Certs",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
- "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
- "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
- "IDAQAB",
-
- "CN=First Data Digital Certificates Inc. Certification Authority",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
- "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
- "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
- "IBAw==",
-
- "C=ES, O=FNMT, OU=FNMT Clase 2 CA",
- "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
- "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
- "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
- "IBAw==",
-
- "CN=Belgacom E-Trust Primary CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
- "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
- "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
- "IDAQAB",
-
- "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
- "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
- "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
- "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
- "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
- "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
-
- "CN=GTE CyberTrust Global Root",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
- "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
- "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
- "IDAQAB",
-
- "CN=GTE CyberTrust Root",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
- "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
- "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
- "IDAQAB",
-
- "C=US, O=GTE Corporation, CN=GTE CyberTrust Root",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
- "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
- "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
- "IDAQAB",
-
- "OU=ValiCert Class 3 Policy Validation Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
- "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
- "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
- "IDAQAB",
-
- "OU=ValiCert Class 1 Policy Validation Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
- "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
- "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
- "IDAQAB",
-
- "OU=ValiCert Class 2 Policy Validation Authority",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
- "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
- "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
- "IDAQAB",
-
- "C=hk, O=C&W HKT SecureNet CA Class A",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
- "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
- "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
- "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
- "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
- "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
-
- "CN=IPS SERVIDORES",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
- "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
- "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
- "IDAQAB",
-
- "CN=Microsoft Root Authority",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
- "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
- "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
- "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
- "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
- "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
-
- "CN=Microsoft Root Certificate Authority",
- "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
- "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
- "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
- "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
- "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
- "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
- "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
- "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
- "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
- "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
- "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
-
- "CN=NetLock Expressz (Class C) Tanusitvanykiado",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
- "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
- "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
- "IDAQAB",
-
- "CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
- "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
- "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
- "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
- "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
- "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
-
- "OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
- "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
- "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
- "IDAQAB",
-
- "CN=Post.Trust Root CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
- "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
- "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
- "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
- "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
- "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
-
- "CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
- "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
- "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
- "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
- "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
- "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
-
- "CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
- "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
- "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
- "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
- "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
- "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
-
- "CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
- "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
- "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
- "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
- "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
- "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
-
- "C=hk, O=C&W HKT SecureNet CA Class B",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
- "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
- "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
- "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
- "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
- "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
-
- "C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
- "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
- "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
- "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
- "E=",
-
- "C=au, O=SecureNet CA Class A",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
- "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
- "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
- "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
- "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
- "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
-
- "C=au, O=SecureNet CA Class B",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
- "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
- "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
- "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
- "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
- "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
-
- "C=au, O=SecureNet CA Root",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
- "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
- "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
- "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
- "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
- "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
-
- "C=au, O=SecureNet CA SGC Root",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
- "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
- "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
- "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
- "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
- "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
- "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
- "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
- "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
- "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
- "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
- "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
- "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
- "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
- "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
- "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
- "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
- "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
- "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
- "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
- "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
- "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
- "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
- "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
- "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
- "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
- "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
- "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
- "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
- "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
- "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
-
- "C=hk, O=C&W HKT SecureNet CA Root",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
- "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
- "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
- "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
- "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
- "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
-
- "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
- "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
- "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
- "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
- "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
- "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
-
- "CN=SERVICIOS DE CERTIFICACION - A.N.C.",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
- "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
- "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
- "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
- "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
- "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
-
- "CN=SIA Secure Client CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
- "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
- "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
- "IDAQAB",
-
- "C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
- "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
- "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
- "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
- "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
- "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
-
- "OU=Public CA Services",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
- "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
- "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
- "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
- "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
- "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
-
- "OU=TC TrustCenter Class 1 CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
- "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
- "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
- "IDAQAB",
-
- "OU=TC TrustCenter Class 2 CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
- "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
- "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
- "IDAQAB",
-
- "OU=TC TrustCenter Class 3 CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
- "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
- "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
- "IDAQAB",
-
- "OU=TC TrustCenter Class 4 CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
- "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
- "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
- "IDAQAB",
-
- "CN=Thawte Premium Server CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
- "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
- "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
- "IDAQAB",
-
- "C=hk, O=C&W HKT SecureNet CA SGC Root",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
- "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
- "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
- "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
- "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
- "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
-
- "CN=Thawte Server CA",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
- "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
- "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
- "IDAQAB",
-
- "CN=UTN - DATACorp SGC",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
- "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
- "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
- "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
- "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
- "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
-
- "CN=UTN-USERFirst-Hardware",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
- "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
- "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
- "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
- "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
- "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
-
- "CN=UTN-USERFirst-Network Applications",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
- "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
- "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
- "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
- "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
- "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
-
- "CN=VeriSign Class 3 Public Primary Certification Authority - G3",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
- "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
- "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
- "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
- "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
- "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
-
- "CN=VeriSign Class 4 Public Primary Certification Authority - G3",
- "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
- "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
- "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
- "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
- "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
- "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
-
- "OU=VeriSign Trust Network",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
- "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
- "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
- "IDAQAB",
-
- "OU=VeriSign Trust Network",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
- "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
- "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
- "IDAQAB",
-
- "OU=VeriSign Trust Network",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
- "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
- "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
- "IDAQAB",
-
- "OU=VeriSign Trust Network",
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
- "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
- "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
- "IDAQAB"
- };
-
- public static boolean alwaysFalse = false;
-
- static class entropySpinner extends Thread {
- volatile boolean stop = false;
- byte counter = 0;
- entropySpinner() { start(); }
- public void run() {
- while (true) {
- counter++;
-
- // without this line, GCJ will over-optimize this loop into an infinite loop. Argh.
- if (alwaysFalse) stop = true;
-
- if (stop) return;
- }
- }
- }
-
- private static volatile boolean initializationFinished = false;
- static {
- entropySpinner[] spinners = new entropySpinner[10];
- for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
-
- for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
- for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
- for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
- for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
-
- try {
- if (Log.on) Log.info(SSL.class, "reading in trusted root public keys...");
- trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length / 2];
- trusted_CA_public_key_identifiers = new String[base64_encoded_trusted_CA_public_keys.length / 2];
- for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i+=2) {
- trusted_CA_public_key_identifiers[i/2] = base64_encoded_trusted_CA_public_keys[i];
- byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i+1]);
- DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
- trusted_CA_public_keys[i/2] = new SubjectPublicKeyInfo((DERSequence)dIn.readObject());
- }
-
- } catch (Exception e) {
- if (Log.on) Log.info(SSL.class, e);
- }
-
- if (Log.on) Log.info(SSL.class, "generating entropy...");
- randpool = new byte[10];
- try { Thread.sleep(100); } catch (Exception e) { }
- for(int i=0; i<spinners.length; i++) {
- spinners[i].stop = true;
- randpool[i] = spinners[i].counter;
- }
-
- MD5Digest md5 = new MD5Digest();
- md5.update(randpool, 0, randpool.length);
- intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
- intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
- intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
- intToBytes(System.identityHashCode(SSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
- Properties p = System.getProperties();
- for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
- String s = (String)e.nextElement();
- byte[] b = s.getBytes();
- md5.update(b, 0, b.length);
- b = p.getProperty(s).getBytes();
- md5.update(b, 0, b.length);
- }
- randpool = new byte[md5.getDigestSize()];
- md5.doFinal(randpool, 0);
-
- if (Log.on) Log.info(SSL.class, "SSL is initialized.");
- initializationFinished = true;
- SSL.class.notifyAll();
- }
-
-
- /**
- * A PKCS1 encoder which uses SSL's built-in PRNG instead of java.security.SecureRandom.
- * This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
- */
- private static class PKCS1 implements AsymmetricBlockCipher {
- private static int HEADER_LENGTH = 10;
- private AsymmetricBlockCipher engine;
- private boolean forEncryption;
- private boolean forPrivateKey;
-
- public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
- public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
-
- public void init(boolean forEncryption, CipherParameters param) {
- engine.init(forEncryption, (AsymmetricKeyParameter)param);
- this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
- this.forEncryption = forEncryption;
- }
-
- public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
- public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
-
- public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
- return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
- }
-
- private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
- byte[] block = new byte[engine.getInputBlockSize()];
- if (forPrivateKey) {
- block[0] = 0x01; // type code 1
- for (int i = 1; i != block.length - inLen - 1; i++)
- block[i] = (byte)0xFF;
- } else {
- getRandomBytes(block, 0, block.length);
- block[0] = 0x02; // type code 2
-
- // a zero byte marks the end of the padding, so all
- // the pad bytes must be non-zero.
- for (int i = 1; i != block.length - inLen - 1; i++)
- while (block[i] == 0)
- getRandomBytes(block, i, 1);
- }
-
- block[block.length - inLen - 1] = 0x00; // mark the end of the padding
- System.arraycopy(in, inOff, block, block.length - inLen, inLen);
- return engine.processBlock(block, 0, block.length);
- }
-
- private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
- byte[] block = engine.processBlock(in, inOff, inLen);
- if (block.length < getOutputBlockSize())
- throw new InvalidCipherTextException("block truncated");
- if (block[0] != 1 && block[0] != 2)
- throw new InvalidCipherTextException("unknown block type");
-
- // find and extract the message block.
- int start;
- for (start = 1; start != block.length; start++)
- if (block[start] == 0)
- break;
- start++; // data should start at the next byte
-
- if (start >= block.length || start < HEADER_LENGTH)
- throw new InvalidCipherTextException("no data in block");
-
- byte[] result = new byte[block.length - start];
- System.arraycopy(block, start, result, 0, result.length);
- return result;
- }
- }
-
-}
-