1 // Copyright (C) 2003 Adam Megacz <adam@xwt.org> all rights reserved.
3 // You may modify, copy, and redistribute this code under the terms of
4 // the GNU Library Public License version 2.1, with the exception of
5 // the portion of clause 6a after the semicolon (aka the "obnoxious
10 import org.bouncycastle.crypto.AsymmetricBlockCipher;
11 import org.bouncycastle.crypto.Digest;
12 import org.bouncycastle.crypto.CipherParameters;
13 import org.bouncycastle.crypto.InvalidCipherTextException;
14 import org.bouncycastle.crypto.params.RSAKeyParameters;
15 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
16 import org.bouncycastle.crypto.params.KeyParameter;
17 import org.bouncycastle.crypto.digests.SHA1Digest;
18 import org.bouncycastle.crypto.digests.MD5Digest;
19 import org.bouncycastle.crypto.digests.MD2Digest;
20 import org.bouncycastle.crypto.engines.RSAEngine;
21 import org.bouncycastle.crypto.engines.RC4Engine;
22 import org.bouncycastle.util.encoders.Base64;
23 import org.bouncycastle.asn1.DERInputStream;
24 import org.bouncycastle.asn1.DEROutputStream;
25 import org.bouncycastle.asn1.DERSequence;
26 import org.bouncycastle.asn1.DERObject;
27 import org.bouncycastle.asn1.DEROctetString;
28 import org.bouncycastle.asn1.BERInputStream;
29 import org.bouncycastle.asn1.x509.X509CertificateStructure;
30 import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
31 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
32 import org.bouncycastle.asn1.x509.TBSCertificateStructure;
33 import org.bouncycastle.asn1.x509.X509Name;
34 import org.bouncycastle.asn1.x509.X509Extensions;
35 import org.bouncycastle.asn1.x509.X509Extension;
36 import org.bouncycastle.asn1.x509.BasicConstraints;
37 import org.xwt.util.Log;
46 TinySSL: a tiny SSL implementation in Java, built on the
47 bouncycastle.org lightweight crypto library.
49 This class implements an SSLv3 client-side socket, with the
50 SSL_RSA_EXPORT_WITH_RC4_40_MD5 and SSL_RSA_WITH_RC4_128_MD5 cipher
51 suites, as well as certificate chain verification against a
52 collection of 93 built-in Trusted Root CA public keys (the same 93
53 included with Microsoft Internet Explorer 5.5 SP2).
55 As of 07-Dec-01, the zipped bytecode for this class is 43k, and the
56 subset of bouncycastle it requires is 82k.
58 This class should work correctly on any Java 1.1 compliant
59 platform. The java.security.* classes are not used.
61 The main design goal for this class was the smallest possible body
62 of code capable of connecting to 99% of all active HTTPS
63 servers. Although this class is useful in many other situations
64 (IMAPS, Secure SMTP, etc), the author will refuse all feature
65 requests and submitted patches which go beyond this scope.
67 Because of the limited goals of this class, certain abstractions
68 have been avoided, and certain parameters have been
69 hard-coded. "Magic numbers" are often used instead of "static final
70 int"'s, although they are usually accompanied by a descriptive
71 comment. Numeric offsets into byte arrays are also favored over
72 DataInputStream(ByteArrayInputStream(foo))'s.
74 Much thanks and credit go to the BouncyCastle team for producing
75 such a first-class library, and for helping me out on the
76 dev-crypto mailing list while I was writing this.
80 1.0 07-Dec-01 Initial Release
82 1.01 15-Mar-02 Added PKCS1 class to avoid dependancy on java.security.SecureRandom
84 1.02 27-Mar-02 Fixed a bug which would hang the connection when more than one
85 Handshake message appeared in the same TLS Record
87 1.03 10-Aug-02 Fixed a vulnerability outlined at
88 http://online.securityfocus.com/archive/1/286290
90 1.04 12-Dec-03 Renamed to org.xwt.SSL, fixed race condition
94 public class SSL extends Socket {
96 // Simple Test //////////////////////////////////////////////
98 public static void main(String[] args) {
101 Socket s = new SSL("www.paypal.com", 443);
102 PrintWriter pw = new PrintWriter(s.getOutputStream());
103 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
104 pw.println("GET / HTTP/1.0");
109 String s2 = br.readLine();
110 if (s2 == null) return;
111 Log.info(SSL.class, s2);
114 } catch (Exception e) {
119 // Static Data //////////////////////////////////////////////
121 public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
122 static SubjectPublicKeyInfo[] trusted_CA_public_keys;
123 static String[] trusted_CA_public_key_identifiers;
124 public static byte[] pad1 = new byte[48];
125 public static byte[] pad2 = new byte[48];
126 public static byte[] pad1_sha = new byte[40];
127 public static byte[] pad2_sha = new byte[40];
128 static byte[] randpool;
129 static long randcnt = 0;
131 // Cipher State //////////////////////////////////////////////
133 public byte[] server_random = new byte[32];
134 public byte[] client_random = new byte[32];
135 public byte[] client_write_MAC_secret = new byte[16];
136 public byte[] server_write_MAC_secret = new byte[16];
137 public byte[] client_write_key = null;
138 public byte[] server_write_key = null;
139 public byte[] master_secret = null;
141 /** the bytes of the ServerKeyExchangeMessage, null if none recieved */
142 public byte[] serverKeyExchange = null;
144 /** true iff the server asked for a certificate */
145 public boolean cert_requested = false;
147 public X509CertificateStructure server_cert = null;
149 public SSLOutputStream os = null;
150 public SSLInputStream is = null;
154 /** if true, we don't mind if the server's cert isn't signed by a CA. USE WITH CAUTION! */
155 boolean ignoreUntrustedCert = false;
157 /** the concatenation of all the bytes of all handshake messages sent or recieved */
158 public byte[] handshakes = new byte[] { };
160 /** true iff we're using SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
161 boolean export = false;
163 public InputStream getInputStream() throws IOException { return is != null ? is : super.getInputStream(); }
164 public OutputStream getOutputStream() throws IOException { return os != null ? os : super.getOutputStream(); }
166 public SSL(String host, int port) throws IOException { this(host, port, true, false); }
167 public SSL(String host, int port, boolean negotiateImmediately) throws IOException { this(host, port, negotiateImmediately, false); }
168 public SSL(String host, int port, boolean negotiateImmediately, boolean ignoreUntrustedCert) throws IOException {
170 if (!initializationFinished) {
171 synchronized(SSL.class) {
172 while (!initializationFinished)
173 try { SSL.class.wait(); } catch (Exception e) { }
177 this.ignoreUntrustedCert = ignoreUntrustedCert;
178 if (negotiateImmediately) negotiate();
181 /** negotiates the SSL connection */
182 public void negotiate() throws IOException {
183 os = new SSLOutputStream(super.getOutputStream());
184 is = new SSLInputStream(super.getInputStream());
185 os.writeClientHello();
186 is.readServerHandshakes();
187 os.sendClientHandshakes();
188 is.readServerFinished();
191 class SSLInputStream extends InputStream {
193 /** the underlying inputstream */
196 /** the server's sequence number */
197 public int seq_num = 0;
199 /** the decryption engine */
200 public RC4Engine rc4 = null;
202 /** pending bytes -- decrypted, but not yet fed to consumer */
207 public void mark() { }
208 public void reset() { }
209 public boolean markSupported() { return false; }
210 public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
211 public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
212 public int available() throws IOException { return pendlen; }
214 public int read() throws IOException {
215 byte[] singlebyte = new byte[1];
216 int numread = read(singlebyte);
217 if (numread != 1) return -1;
218 return (int)singlebyte[0];
221 public int read(byte[] b, int off, int len) throws IOException {
224 if (pend == null) return -1;
226 pendlen = pend.length;
228 int ret = Math.min(len, pendlen);
229 System.arraycopy(pend, pendstart, b, off, ret);
235 /** reads and decrypts exactly one record; blocks if unavailable */
236 public byte[] readRecord() throws IOException {
238 // we only catch EOFException here, because anywhere else
239 // would be "unusual", and we *want* and EOFException in
242 try { type = raw.readByte();
243 } catch (EOFException e) {
244 if (Log.on) Log.info(this, "got EOFException reading packet type");
248 byte ver_major = raw.readByte();
249 byte ver_minor = raw.readByte();
250 short len = raw.readShort();
251 if (Log.on) Log.info(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
253 byte[] ret = new byte[len];
256 // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours
258 if (Log.on) Log.info(this, "got ChangeCipherSpec; ignoring");
263 byte[] decrypted_payload;
265 // if crypto hasn't been enabled yet; skip crypt and hash
266 if (rc4 == null) decrypted_payload = ret;
268 // decrypt the payload
269 decrypted_payload = new byte[len - 16];
270 rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
273 byte[] MAC = new byte[16];
274 rc4.processBytes(ret, len - 16, 16, MAC, 0);
275 byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
276 for(int i=0; i<MAC.length; i++)
277 if (MAC[i] != ourMAC[i])
278 throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
282 if (decrypted_payload[1] > 1) {
283 throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
284 } else if (decrypted_payload[1] == 0) {
285 if (Log.on) Log.info(this, "server requested connection closure; returning null");
288 if (Log.on) Log.info(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
292 } else if (type == 22) {
293 if (Log.on) Log.info(this, "read a handshake");
295 } else if (type != 23) {
296 if (Log.on) Log.info(this, "unexpected record type: " + type + "; skipping");
301 if (Log.on) Log.info(this, " returning " + decrypted_payload.length + " byte record payload");
302 return decrypted_payload;
305 private byte[] readHandshake() throws IOException {
306 // acquire a handshake message
307 byte type = (byte)read();
308 int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff);
309 byte[] rec = new byte[len + 4];
311 rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff);
312 rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff);
313 rec[3] = (byte)((len & 0x000000ff) & 0xff);
314 if (len > 0) read(rec, 4, len);
318 /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */
319 public void readServerHandshakes() throws IOException {
322 byte[] rec = readHandshake();
323 handshakes = concat(new byte[][] { handshakes, rec });
324 DataInputStream stream = new DataInputStream(new ByteArrayInputStream(rec, 4, rec.length - 4));
327 case 2: // ServerHello
328 if (Log.on) Log.info(this, "got ServerHello");
329 byte ver_major = rec[4];
330 byte ver_minor = rec[5];
331 System.arraycopy(rec, 6, server_random, 0, server_random.length);
332 short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
333 short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
335 if (cipher_low == 0x04 || cipher_high != 0x00) {
337 if (Log.on) Log.info(this, "using SSL_RSA_WITH_RC4_128_MD5");
339 } else if (cipher_low == 0x03 || cipher_high != 0x00) {
341 if (Log.on) Log.info(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
343 } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
344 " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
345 "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
347 byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
348 if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
349 " but we don't support compression");
352 case 11: // Server's certificate(s)
353 if (Log.on) Log.info(this, "got Server Certificate(s)");
354 int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
356 X509CertificateStructure last_cert = null;
357 X509CertificateStructure this_cert = null;
359 for(int i=0; i<numcertbytes;) {
360 int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
362 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
363 this_cert = new X509CertificateStructure((DERSequence)dIn.readObject());
364 } catch (Exception e) {
365 SSLException t = new SSLException("error decoding server certificate: " + e);
366 t.fillInStackTrace();
370 if (server_cert == null) {
371 server_cert = this_cert;
372 TBSCertificateStructure tbs = server_cert.getTBSCertificate();
373 X509Name subject = tbs.getSubject();
375 // gross hack to extract the Common Name so we can compare it to the server hostname
376 String CN = tbs.getSubject().toString() + " ";
377 boolean good = false;
378 for(int j=0; j<CN.length() - 3; j++)
379 if (CN.substring(j, j+3).equals("CN=")) {
381 CN = CN.substring(j+3, CN.indexOf(' ', j+3));
385 if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
386 if (!ignoreUntrustedCert && !CN.equalsIgnoreCase(hostname))
387 throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
389 SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss-z");
391 // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
392 String s = tbs.getStartDate().getTime();
393 s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8) + "-" +
394 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" +
395 s.substring(12, 14) + "-" + s.substring(14);
397 Date startDate = dateF.parse(s, new ParsePosition(0));
399 s = tbs.getEndDate().getTime();
400 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
401 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
402 Date endDate = dateF.parse(s, new ParsePosition(0));
404 Date now = new Date();
405 if (!ignoreUntrustedCert && now.after(endDate))
406 throw new SSLException("server certificate expired on " + endDate);
407 if (!ignoreUntrustedCert && now.before(startDate))
408 throw new SSLException("server certificate will not be valid until " + startDate);
410 Log.info(this, "server cert (name, validity dates) checks out okay");
414 // don't check the top cert since some very old root certs lack a BasicConstraints field.
415 if (certlen + 3 + i < numcertbytes) {
416 // defend against Mike Benham's attack
417 X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints);
418 if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block");
419 DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets()));
420 BasicConstraints bc = new BasicConstraints((DERSequence)dis.readObject());
421 if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing");
424 if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
425 throw new SSLException("the server sent a broken chain of certificates");
428 last_cert = this_cert;
432 if (Log.on) Log.info(this, " Certificate (" + numcerts + " certificates)");
434 if (ignoreUntrustedCert) break;
436 boolean good = false;
438 // pass 1 -- only check CA's whose subject is a partial match
439 String subject = this_cert.getSubject().toString();
440 for(int i=0; i<trusted_CA_public_keys.length; i++) {
441 if (subject.indexOf(trusted_CA_public_key_identifiers[i]) != -1 && isSignedBy(this_cert, trusted_CA_public_keys[i])) {
442 if (Log.on) Log.info(this, "pass 1: server cert was signed by trusted CA " + i);
448 // pass 2 -- try all certs
450 for(int i=0; i<trusted_CA_public_keys.length; i++) {
451 if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
452 if (Log.on) Log.info(this, "pass 2: server cert was signed by trusted CA " + i);
458 if (!good) throw new SSLException("server cert was not signed by a trusted CA");
462 if (Log.on) Log.info(this, "got ServerKeyExchange");
463 serverKeyExchange = rec;
467 if (Log.on) Log.info(this, "got Request for Client Certificates");
468 cert_requested = true;
471 case 14: if (Log.on) Log.info(this, " ServerHelloDone"); return;
472 default: throw new SSLException("unknown handshake of type " + rec[0]);
477 public void readServerFinished() throws IOException {
479 byte[] rec = readHandshake();
480 if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
482 byte[] expectedFinished = concat(new byte[][] {
483 md5(new byte[][] { master_secret, pad2,
484 md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
485 master_secret, pad1 }) }),
486 sha(new byte[][] { master_secret, pad2_sha,
487 sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
488 master_secret, pad1_sha } ) } ) } );
490 for(int i=0; i<expectedFinished.length; i++)
491 if (expectedFinished[i] != rec[i + 4])
492 throw new SSLException("server Finished message mismatch!");
494 if (Log.on) Log.info(this, "server finished message checked out okay!");
499 class SSLOutputStream extends OutputStream {
501 /** the underlying outputstream */
502 DataOutputStream raw;
504 /** the sequence number for sending */
505 public long seq_num = 0;
507 /** the encryption engine for sending */
508 RC4Engine rc4 = null;
510 public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
511 public void flush() throws IOException { raw.flush(); }
512 public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
513 public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
514 public void close() throws IOException {
515 write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
519 /** writes a single SSL Record */
520 public void write(byte[] payload, int off, int len, byte type) throws IOException {
522 // largest permissible frame is 2^14 octets
524 write(payload, off, 1 << 14, type);
525 write(payload, off + 1 << 14, len - 1 << 14, type);
530 raw.writeShort(0x0300);
534 raw.write(payload, off, len);
537 byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
538 byte[] encryptedPayload = new byte[MAC.length + len];
539 rc4.processBytes(payload, off, len, encryptedPayload, 0);
540 rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
541 raw.writeShort(encryptedPayload.length);
542 raw.write(encryptedPayload);
549 /** tacks a handshake header onto payload before sending it */
550 public void writeHandshake(int type, byte[] payload) throws IOException {
551 byte[] real_payload = new byte[payload.length + 4];
552 System.arraycopy(payload, 0, real_payload, 4, payload.length);
553 real_payload[0] = (byte)(type & 0xFF);
554 intToBytes(payload.length, real_payload, 1, 3);
555 handshakes = concat(new byte[][] { handshakes, real_payload });
556 write(real_payload, 0, real_payload.length, (byte)22);
559 public void sendClientHandshakes() throws IOException {
561 if (Log.on) Log.info(this, "shaking hands");
562 if (cert_requested) {
563 if (Log.on) Log.info(this, "telling the server we have no certificates");
564 writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
567 // generate the premaster secret
568 byte[] pre_master_secret = new byte[48];
569 pre_master_secret[0] = 0x03; // first two bytes of premaster secret are our version number
570 pre_master_secret[1] = 0x00;
571 getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
573 // encrypt and send the pre_master_secret
575 byte[] encrypted_pre_master_secret;
577 SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
578 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
579 BigInteger modulus = rsa_pks.getModulus();
580 BigInteger exponent = rsa_pks.getPublicExponent();
582 if (serverKeyExchange != null) {
584 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
585 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
587 int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
588 byte[] b_modulus = new byte[modulus_size];
589 System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
590 modulus = new BigInteger(1, b_modulus);
592 int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
593 byte[] b_exponent = new byte[exponent_size];
594 System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
595 exponent = new BigInteger(1, b_exponent);
597 byte[] server_params = new byte[modulus_size + exponent_size + 4];
598 System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
600 byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
601 sha(new byte[][] { client_random, server_random, server_params } ) } );
603 byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
604 serverKeyExchange.length - 6 - server_params.length);
606 for(int i=0; i<expectedSignature.length; i++)
607 if (expectedSignature[i] != recievedSignature[i])
608 throw new SSLException("ServerKeyExchange message had invalid signature " + i);
610 if (Log.on) Log.info(this, "ServerKeyExchange successfully processed");
613 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
614 rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
616 encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
617 writeHandshake(16, encrypted_pre_master_secret);
619 } catch (Exception e) {
620 SSLException t = new SSLException("exception encrypting premaster secret");
621 t.fillInStackTrace();
626 if (Log.on) Log.info(this, "Handshake complete; sending ChangeCipherSpec");
627 write(new byte[] { 0x01 }, 0, 1, (byte)20);
630 // compute master_secret
631 master_secret = concat(new byte[][] {
632 md5(new byte[][] { pre_master_secret,
633 sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
634 md5(new byte[][] { pre_master_secret,
635 sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
636 md5(new byte[][] { pre_master_secret,
637 sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
640 // construct the key material
641 byte[] key_material = new byte[] { };
642 for(int i=0; key_material.length < 72; i++) {
643 byte[] crap = new byte[i + 1];
644 for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
645 key_material = concat(new byte[][] { key_material,
646 md5(new byte[][] { master_secret,
647 sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
650 client_write_key = new byte[export ? 5 : 16];
651 server_write_key = new byte[export ? 5 : 16];
653 System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
654 System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
655 System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
656 System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
659 // see SSLv3 spec, 6.2.2 for explanation
660 byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
661 byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
662 client_write_key = new byte[16];
663 server_write_key = new byte[16];
664 System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
665 System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
668 rc4 = new RC4Engine();
669 rc4.init(true, new KeyParameter(client_write_key));
670 is.rc4 = new RC4Engine();
671 is.rc4.init(false, new KeyParameter(server_write_key));
674 writeHandshake(20, concat(new byte[][] {
675 md5(new byte[][] { master_secret, pad2,
676 md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
677 master_secret, pad1 }) }),
678 sha(new byte[][] { master_secret, pad2_sha,
679 sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
680 master_secret, pad1_sha } ) })
683 if (Log.on) Log.info(this, "wrote Finished message");
687 public void writeClientHello() throws IOException {
689 if (Log.on) Log.info(this, "sending ClientHello");
690 int unixtime = (int)(System.currentTimeMillis() / (long)1000);
692 byte[] out = new byte[] {
693 0x03, 0x00, // client version (SSLv3.0)
695 // space for random bytes
696 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
697 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
700 0x0, // empty vector for sessionid
701 0x0, 0x4, 0x0, 0x4, 0x0, 0x3, // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
702 0x1, 0x0 // we only support one compression method: none
705 // don't need to use secure random here since it's sent in the clear
706 Random rand = new Random(System.currentTimeMillis());
707 rand.nextBytes(client_random);
708 intToBytes(unixtime, client_random, 0, 4);
709 System.arraycopy(client_random, 0, out, 2, client_random.length);
711 writeHandshake(1, out);
716 // Static Helpers ////////////////////////////////////////////////////////////////////
718 /** copy the least significant num bytes of val into byte array b, startint at offset */
719 public static void intToBytes(long val, byte[] b, int offset, int num) {
720 for(int i=0; i<num; i++)
721 b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
724 /** fills b with random bytes */
725 public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
726 MD5Digest md5 = new MD5Digest();
727 byte[] b2 = new byte[16];
730 md5.update(randpool, 0, randpool.length);
731 intToBytes(randcnt++, b2, 0, 8);
732 md5.update(b2, 0, 8);
734 int n = len < 16 ? len : 16;
735 System.arraycopy(b2, 0, b, offset, n);
741 public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
742 byte[] MAC = new byte[16];
743 MD5Digest md5 = new MD5Digest();
744 md5.update(MAC_secret, 0, MAC_secret.length);
745 md5.update(pad1, 0, pad1.length);
747 byte[] b = new byte[11];
748 intToBytes(seq_num, b, 0, 8);
750 intToBytes(len, b, 9, 2);
751 md5.update(b, 0, b.length);
753 md5.update(payload, off, len);
756 md5.update(MAC_secret, 0, MAC_secret.length);
757 md5.update(pad2, 0, pad2.length);
758 md5.update(MAC, 0, MAC.length);
764 public static byte[] concat(byte[][] inputs) {
766 for(int i=0; i<inputs.length; i++) total += inputs[i].length;
767 byte[] ret = new byte[total];
769 for(int i=0; i<inputs.length; i++) {
770 System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
771 pos += inputs[i].length;
776 SHA1Digest master_sha1 = new SHA1Digest();
777 public byte[] sha(byte[][] inputs) {
779 for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
780 byte[] ret = new byte[master_sha1.getDigestSize()];
781 master_sha1.doFinal(ret, 0);
785 MD5Digest master_md5 = new MD5Digest();
786 public byte[] md5(byte[][] inputs) {
788 for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
789 byte[] ret = new byte[master_md5.getDigestSize()];
790 master_md5.doFinal(ret, 0);
794 // FEATURE: improve error reporting in here
795 /** returns true iff certificate "signee" is signed by public key "signer" */
796 public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
800 String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
801 if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
802 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
803 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
804 else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
807 // decrypt the signature using the signer's public key
808 byte[] ED = signee.getSignature().getBytes();
809 SubjectPublicKeyInfo pki = signer;
810 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
811 BigInteger modulus = rsa_pks.getModulus();
812 BigInteger exponent = rsa_pks.getPublicExponent();
813 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
814 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
816 // Decode the embedded octet string
817 byte[] D = rsa.processBlock(ED, 0, ED.length);
818 BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
819 DERObject derob = beris.readObject();
820 DERSequence dercs = (DERSequence)derob;
821 DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
822 byte[] MD = deros.getOctets();
824 // generate our own hash
825 ByteArrayOutputStream baos = new ByteArrayOutputStream();
826 DEROutputStream dos = new DEROutputStream(baos);
827 dos.writeObject(signee.getTBSCertificate());
829 byte[] b = baos.toByteArray();
830 hash.update(b, 0, b.length);
831 byte[] md_out = new byte[MD.length];
832 hash.doFinal(md_out, 0);
834 // compare our hash to the signed hash
835 for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
838 } catch (Exception e) {
844 // Embedded Trusted Public Keys //////////////////////////////////////////////
846 /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
847 static String[] base64_encoded_trusted_CA_public_keys = new String[] {
849 "CN=ABA.ECOM Root CA",
850 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
851 "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
852 "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
853 "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
854 "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
855 "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
858 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
859 "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
860 "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
863 "CN=Xcert EZ by DST",
864 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
865 "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
866 "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
867 "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
868 "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
869 "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
871 "CN=Certiposte Classe A Personne",
872 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
873 "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
874 "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
875 "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
876 "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
877 "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
879 "CN=Certiposte Serveur",
880 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
881 "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
882 "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
883 "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
884 "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
885 "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
887 "OU=Certisign - Autoridade Certificadora - AC2",
888 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
889 "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
890 "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
893 "OU=Certisign - Autoridade Certificadora - AC4",
894 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
895 "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
896 "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
899 "OU=Certisign Autoridade Certificadora AC1S",
900 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
901 "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
902 "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
905 "OU=Certisign Autoridade Certificadora AC3S",
906 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
907 "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
908 "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
911 "O=Certplus, CN=Class 1 Primary CA",
912 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
913 "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
914 "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
915 "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
916 "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
917 "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
919 "O=Certplus, CN=Class 2 Primary CA",
920 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
921 "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
922 "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
923 "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
924 "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
925 "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
927 "O=Certplus, CN=Class 3 Primary CA",
928 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
929 "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
930 "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
931 "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
932 "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
933 "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
935 "CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano",
936 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
937 "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
938 "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
939 "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
940 "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
941 "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
943 "O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
944 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
945 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
946 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
949 "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
950 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
951 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
952 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
955 "C=FR, O=Certplus, CN=Class 3P Primary CA",
956 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
957 "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
958 "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
959 "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
960 "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
961 "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
963 "C=FR, O=Certplus, CN=Class 3TS Primary CA",
964 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
965 "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
966 "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
967 "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
968 "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
969 "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
971 "C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority",
972 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
973 "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
974 "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
977 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1",
978 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
979 "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
980 "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
983 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2",
984 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
985 "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
986 "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
987 "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
988 "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
989 "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
991 "C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA",
992 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
993 "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
994 "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
997 "OU=National Retail Federation, CN=DST (NRF) RootCA",
998 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
999 "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
1000 "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
1001 "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
1002 "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
1003 "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
1005 "OU=United Parcel Service, CN=DST (UPS) RootCA",
1006 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
1007 "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
1008 "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
1009 "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
1010 "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
1011 "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
1013 "CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana",
1014 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
1015 "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
1016 "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
1017 "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
1018 "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
1019 "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
1022 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
1023 "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
1024 "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
1025 "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
1026 "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
1027 "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
1029 "OU=DSTCA X2, CN=DST RootCA X2",
1030 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
1031 "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
1032 "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
1033 "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
1034 "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
1035 "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
1037 "C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA",
1038 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
1039 "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
1040 "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
1043 "C=US, O=Digital Signature Trust Co., OU=DSTCA E1",
1044 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
1045 "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
1046 "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
1049 "C=US, O=Digital Signature Trust Co., OU=DSTCA E2",
1050 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
1051 "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
1052 "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
1055 "CN=Entrust.net Certification Authority (2048)",
1056 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
1057 "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
1058 "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
1059 "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
1060 "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
1061 "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
1063 "CN=Entrust.net Client Certification Authority",
1064 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
1065 "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
1066 "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
1069 "CN=Entrust.net Secure Server Certification Authority",
1070 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
1071 "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
1072 "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
1075 "C=US, O=Equifax, OU=Equifax Secure Certificate Authority",
1076 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
1077 "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
1078 "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
1081 "C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1",
1082 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
1083 "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
1084 "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
1087 "CN=Baltimore EZ by DST",
1088 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
1089 "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
1090 "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
1091 "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
1092 "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
1093 "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
1095 "C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2",
1096 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
1097 "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
1098 "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
1101 "C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1",
1102 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
1103 "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
1104 "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
1107 "O=EUnet International, CN=EUnet International Root CA",
1108 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
1109 "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
1110 "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
1113 "CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org",
1114 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
1115 "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
1116 "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
1119 "CN=FESTE, Verified Certs",
1120 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
1121 "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
1122 "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
1125 "CN=First Data Digital Certificates Inc. Certification Authority",
1126 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
1127 "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
1128 "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
1131 "C=ES, O=FNMT, OU=FNMT Clase 2 CA",
1132 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
1133 "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
1134 "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
1137 "CN=Belgacom E-Trust Primary CA",
1138 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
1139 "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
1140 "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
1143 "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA",
1144 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
1145 "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
1146 "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
1147 "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
1148 "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
1149 "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
1151 "CN=GTE CyberTrust Global Root",
1152 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
1153 "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
1154 "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
1157 "CN=GTE CyberTrust Root",
1158 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
1159 "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
1160 "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
1163 "C=US, O=GTE Corporation, CN=GTE CyberTrust Root",
1164 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
1165 "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
1166 "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
1169 "OU=ValiCert Class 3 Policy Validation Authority",
1170 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
1171 "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
1172 "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
1175 "OU=ValiCert Class 1 Policy Validation Authority",
1176 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
1177 "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
1178 "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
1181 "OU=ValiCert Class 2 Policy Validation Authority",
1182 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
1183 "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
1184 "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
1187 "C=hk, O=C&W HKT SecureNet CA Class A",
1188 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
1189 "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
1190 "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
1191 "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
1192 "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
1193 "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
1195 "CN=IPS SERVIDORES",
1196 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
1197 "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
1198 "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
1201 "CN=Microsoft Root Authority",
1202 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
1203 "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
1204 "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
1205 "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
1206 "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
1207 "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
1209 "CN=Microsoft Root Certificate Authority",
1210 "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
1211 "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
1212 "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
1213 "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
1214 "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
1215 "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
1216 "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
1217 "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
1218 "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
1219 "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
1220 "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
1222 "CN=NetLock Expressz (Class C) Tanusitvanykiado",
1223 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
1224 "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
1225 "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
1228 "CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado",
1229 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
1230 "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
1231 "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
1232 "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
1233 "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
1234 "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
1236 "OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado",
1237 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
1238 "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
1239 "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
1242 "CN=Post.Trust Root CA",
1243 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
1244 "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
1245 "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
1246 "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
1247 "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
1248 "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
1250 "CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl",
1251 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
1252 "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
1253 "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
1254 "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
1255 "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
1256 "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
1258 "CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi",
1259 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
1260 "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
1261 "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
1262 "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
1263 "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
1264 "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
1266 "CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi",
1267 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
1268 "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
1269 "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
1270 "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
1271 "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
1272 "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
1274 "C=hk, O=C&W HKT SecureNet CA Class B",
1275 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
1276 "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
1277 "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
1278 "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
1279 "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
1280 "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
1282 "C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
1283 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
1284 "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
1285 "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
1288 "C=au, O=SecureNet CA Class A",
1289 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
1290 "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
1291 "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
1292 "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
1293 "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
1294 "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
1296 "C=au, O=SecureNet CA Class B",
1297 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
1298 "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
1299 "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
1300 "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
1301 "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
1302 "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
1304 "C=au, O=SecureNet CA Root",
1305 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
1306 "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
1307 "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
1308 "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
1309 "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
1310 "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
1312 "C=au, O=SecureNet CA SGC Root",
1313 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
1314 "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
1315 "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
1316 "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
1317 "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
1318 "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
1320 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1321 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1322 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1323 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1324 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1325 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1326 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1328 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1329 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1330 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1331 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1332 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1333 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1334 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1336 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1337 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1338 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1339 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1340 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1341 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1342 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1344 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1345 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1346 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1347 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1348 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1349 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1350 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1352 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1353 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1354 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1355 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1356 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1357 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1358 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1360 "C=hk, O=C&W HKT SecureNet CA Root",
1361 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
1362 "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
1363 "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
1364 "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
1365 "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
1366 "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
1368 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1369 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1370 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1371 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1372 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1373 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1374 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1376 "CN=SERVICIOS DE CERTIFICACION - A.N.C.",
1377 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
1378 "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
1379 "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
1380 "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
1381 "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
1382 "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
1384 "CN=SIA Secure Client CA",
1385 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
1386 "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
1387 "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
1390 "C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA",
1391 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
1392 "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
1393 "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
1394 "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
1395 "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
1396 "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
1398 "OU=Public CA Services",
1399 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
1400 "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
1401 "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
1402 "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
1403 "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
1404 "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
1406 "OU=TC TrustCenter Class 1 CA",
1407 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
1408 "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
1409 "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
1412 "OU=TC TrustCenter Class 2 CA",
1413 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
1414 "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
1415 "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
1418 "OU=TC TrustCenter Class 3 CA",
1419 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
1420 "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
1421 "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
1424 "OU=TC TrustCenter Class 4 CA",
1425 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
1426 "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
1427 "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
1430 "CN=Thawte Premium Server CA",
1431 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
1432 "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
1433 "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
1436 "C=hk, O=C&W HKT SecureNet CA SGC Root",
1437 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
1438 "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
1439 "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
1440 "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
1441 "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
1442 "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
1444 "CN=Thawte Server CA",
1445 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
1446 "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
1447 "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
1450 "CN=UTN - DATACorp SGC",
1451 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
1452 "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
1453 "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
1454 "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
1455 "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
1456 "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
1458 "CN=UTN-USERFirst-Hardware",
1459 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
1460 "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
1461 "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
1462 "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
1463 "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
1464 "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
1466 "CN=UTN-USERFirst-Network Applications",
1467 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
1468 "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
1469 "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
1470 "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
1471 "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
1472 "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
1474 "CN=VeriSign Class 3 Public Primary Certification Authority - G3",
1475 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
1476 "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
1477 "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
1478 "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
1479 "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
1480 "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
1482 "CN=VeriSign Class 4 Public Primary Certification Authority - G3",
1483 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
1484 "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
1485 "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
1486 "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
1487 "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
1488 "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
1490 "OU=VeriSign Trust Network",
1491 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1492 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1493 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1496 "OU=VeriSign Trust Network",
1497 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1498 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1499 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1502 "OU=VeriSign Trust Network",
1503 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1504 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1505 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1508 "OU=VeriSign Trust Network",
1509 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1510 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1511 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1515 public static boolean alwaysFalse = false;
1517 static class entropySpinner extends Thread {
1518 volatile boolean stop = false;
1520 entropySpinner() { start(); }
1525 // without this line, GCJ will over-optimize this loop into an infinite loop. Argh.
1526 if (alwaysFalse) stop = true;
1533 private static volatile boolean initializationFinished = false;
1535 entropySpinner[] spinners = new entropySpinner[10];
1536 for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
1538 for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
1539 for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
1540 for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
1541 for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
1544 if (Log.on) Log.info(SSL.class, "reading in trusted root public keys...");
1545 trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length / 2];
1546 trusted_CA_public_key_identifiers = new String[base64_encoded_trusted_CA_public_keys.length / 2];
1547 for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i+=2) {
1548 trusted_CA_public_key_identifiers[i/2] = base64_encoded_trusted_CA_public_keys[i];
1549 byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i+1]);
1550 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
1551 trusted_CA_public_keys[i/2] = new SubjectPublicKeyInfo((DERSequence)dIn.readObject());
1554 } catch (Exception e) {
1555 if (Log.on) Log.info(SSL.class, e);
1558 if (Log.on) Log.info(SSL.class, "generating entropy...");
1559 randpool = new byte[10];
1560 try { Thread.sleep(100); } catch (Exception e) { }
1561 for(int i=0; i<spinners.length; i++) {
1562 spinners[i].stop = true;
1563 randpool[i] = spinners[i].counter;
1566 MD5Digest md5 = new MD5Digest();
1567 md5.update(randpool, 0, randpool.length);
1568 intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
1569 intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1570 intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1571 intToBytes(System.identityHashCode(SSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
1572 Properties p = System.getProperties();
1573 for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
1574 String s = (String)e.nextElement();
1575 byte[] b = s.getBytes();
1576 md5.update(b, 0, b.length);
1577 b = p.getProperty(s).getBytes();
1578 md5.update(b, 0, b.length);
1580 randpool = new byte[md5.getDigestSize()];
1581 md5.doFinal(randpool, 0);
1583 if (Log.on) Log.info(SSL.class, "SSL is initialized.");
1584 initializationFinished = true;
1585 SSL.class.notifyAll();
1590 * A PKCS1 encoder which uses SSL's built-in PRNG instead of java.security.SecureRandom.
1591 * This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
1593 private static class PKCS1 implements AsymmetricBlockCipher {
1594 private static int HEADER_LENGTH = 10;
1595 private AsymmetricBlockCipher engine;
1596 private boolean forEncryption;
1597 private boolean forPrivateKey;
1599 public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
1600 public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
1602 public void init(boolean forEncryption, CipherParameters param) {
1603 engine.init(forEncryption, (AsymmetricKeyParameter)param);
1604 this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
1605 this.forEncryption = forEncryption;
1608 public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
1609 public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
1611 public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1612 return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
1615 private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1616 byte[] block = new byte[engine.getInputBlockSize()];
1617 if (forPrivateKey) {
1618 block[0] = 0x01; // type code 1
1619 for (int i = 1; i != block.length - inLen - 1; i++)
1620 block[i] = (byte)0xFF;
1622 getRandomBytes(block, 0, block.length);
1623 block[0] = 0x02; // type code 2
1625 // a zero byte marks the end of the padding, so all
1626 // the pad bytes must be non-zero.
1627 for (int i = 1; i != block.length - inLen - 1; i++)
1628 while (block[i] == 0)
1629 getRandomBytes(block, i, 1);
1632 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
1633 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
1634 return engine.processBlock(block, 0, block.length);
1637 private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1638 byte[] block = engine.processBlock(in, inOff, inLen);
1639 if (block.length < getOutputBlockSize())
1640 throw new InvalidCipherTextException("block truncated");
1641 if (block[0] != 1 && block[0] != 2)
1642 throw new InvalidCipherTextException("unknown block type");
1644 // find and extract the message block.
1646 for (start = 1; start != block.length; start++)
1647 if (block[start] == 0)
1649 start++; // data should start at the next byte
1651 if (start >= block.length || start < HEADER_LENGTH)
1652 throw new InvalidCipherTextException("no data in block");
1654 byte[] result = new byte[block.length - start];
1655 System.arraycopy(block, start, result, 0, result.length);