1 // Copyright (C) 2003 Adam Megacz <adam@ibex.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.ibex.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.ibex.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 });
326 case 2: // ServerHello
327 if (Log.on) Log.info(this, "got ServerHello");
328 byte ver_major = rec[4];
329 byte ver_minor = rec[5];
330 System.arraycopy(rec, 6, server_random, 0, server_random.length);
331 short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
332 short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
334 if (cipher_low == 0x04 || cipher_high != 0x00) {
336 if (Log.on) Log.info(this, "using SSL_RSA_WITH_RC4_128_MD5");
338 } else if (cipher_low == 0x03 || cipher_high != 0x00) {
340 if (Log.on) Log.info(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
342 } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
343 " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
344 "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
346 byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
347 if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
348 " but we don't support compression");
351 case 11: // Server's certificate(s)
352 if (Log.on) Log.info(this, "got Server Certificate(s)");
353 int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
355 X509CertificateStructure last_cert = null;
356 X509CertificateStructure this_cert = null;
358 for(int i=0; i<numcertbytes;) {
359 int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
361 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
362 this_cert = new X509CertificateStructure((DERSequence)dIn.readObject());
363 } catch (Exception e) {
364 SSLException t = new SSLException("error decoding server certificate: " + e);
365 t.fillInStackTrace();
369 if (server_cert == null) {
370 server_cert = this_cert;
371 TBSCertificateStructure tbs = server_cert.getTBSCertificate();
373 // gross hack to extract the Common Name so we can compare it to the server hostname
374 String CN = tbs.getSubject().toString() + " ";
375 boolean good = false;
376 for(int j=0; j<CN.length() - 3; j++)
377 if (CN.substring(j, j+3).equals("CN=")) {
379 CN = CN.substring(j+3, CN.indexOf(' ', j+3));
383 if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
384 if (!ignoreUntrustedCert && !CN.equalsIgnoreCase(hostname))
385 throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
387 SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss-z");
389 // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
390 String s = tbs.getStartDate().getTime();
391 s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8) + "-" +
392 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" +
393 s.substring(12, 14) + "-" + s.substring(14);
395 Date startDate = dateF.parse(s, new ParsePosition(0));
397 s = tbs.getEndDate().getTime();
398 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
399 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
400 Date endDate = dateF.parse(s, new ParsePosition(0));
402 Date now = new Date();
403 if (!ignoreUntrustedCert && now.after(endDate))
404 throw new SSLException("server certificate expired on " + endDate);
405 if (!ignoreUntrustedCert && now.before(startDate))
406 throw new SSLException("server certificate will not be valid until " + startDate);
408 Log.info(this, "server cert (name, validity dates) checks out okay");
412 // don't check the top cert since some very old root certs lack a BasicConstraints field.
413 if (certlen + 3 + i < numcertbytes) {
414 // defend against Mike Benham's attack
415 X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints);
416 if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block");
417 DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets()));
418 BasicConstraints bc = new BasicConstraints((DERSequence)dis.readObject());
419 if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing");
422 if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
423 throw new SSLException("the server sent a broken chain of certificates");
426 last_cert = this_cert;
430 if (Log.on) Log.info(this, " Certificate (" + numcerts + " certificates)");
432 if (ignoreUntrustedCert) break;
434 boolean good = false;
436 // pass 1 -- only check CA's whose subject is a partial match
437 String subject = this_cert.getSubject().toString();
438 for(int i=0; i<trusted_CA_public_keys.length; i++) {
439 if (subject.indexOf(trusted_CA_public_key_identifiers[i]) != -1 && isSignedBy(this_cert, trusted_CA_public_keys[i])) {
440 if (Log.on) Log.info(this, "pass 1: server cert was signed by trusted CA " + i);
446 // pass 2 -- try all certs
448 for(int i=0; i<trusted_CA_public_keys.length; i++) {
449 if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
450 if (Log.on) Log.info(this, "pass 2: server cert was signed by trusted CA " + i);
456 if (!good) throw new SSLException("server cert was not signed by a trusted CA");
460 if (Log.on) Log.info(this, "got ServerKeyExchange");
461 serverKeyExchange = rec;
465 if (Log.on) Log.info(this, "got Request for Client Certificates");
466 cert_requested = true;
469 case 14: if (Log.on) Log.info(this, " ServerHelloDone"); return;
470 default: throw new SSLException("unknown handshake of type " + rec[0]);
475 public void readServerFinished() throws IOException {
477 byte[] rec = readHandshake();
478 if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
480 byte[] expectedFinished = concat(new byte[][] {
481 md5(new byte[][] { master_secret, pad2,
482 md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
483 master_secret, pad1 }) }),
484 sha(new byte[][] { master_secret, pad2_sha,
485 sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
486 master_secret, pad1_sha } ) } ) } );
488 for(int i=0; i<expectedFinished.length; i++)
489 if (expectedFinished[i] != rec[i + 4])
490 throw new SSLException("server Finished message mismatch!");
492 if (Log.on) Log.info(this, "server finished message checked out okay!");
497 class SSLOutputStream extends OutputStream {
499 /** the underlying outputstream */
500 DataOutputStream raw;
502 /** the sequence number for sending */
503 public long seq_num = 0;
505 /** the encryption engine for sending */
506 RC4Engine rc4 = null;
508 public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
509 public void flush() throws IOException { raw.flush(); }
510 public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
511 public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
512 public void close() throws IOException {
513 write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
517 /** writes a single SSL Record */
518 public void write(byte[] payload, int off, int len, byte type) throws IOException {
520 // largest permissible frame is 2^14 octets
522 write(payload, off, 1 << 14, type);
523 write(payload, off + 1 << 14, len - 1 << 14, type);
528 raw.writeShort(0x0300);
532 raw.write(payload, off, len);
535 byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
536 byte[] encryptedPayload = new byte[MAC.length + len];
537 rc4.processBytes(payload, off, len, encryptedPayload, 0);
538 rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
539 raw.writeShort(encryptedPayload.length);
540 raw.write(encryptedPayload);
547 /** tacks a handshake header onto payload before sending it */
548 public void writeHandshake(int type, byte[] payload) throws IOException {
549 byte[] real_payload = new byte[payload.length + 4];
550 System.arraycopy(payload, 0, real_payload, 4, payload.length);
551 real_payload[0] = (byte)(type & 0xFF);
552 intToBytes(payload.length, real_payload, 1, 3);
553 handshakes = concat(new byte[][] { handshakes, real_payload });
554 write(real_payload, 0, real_payload.length, (byte)22);
557 public void sendClientHandshakes() throws IOException {
559 if (Log.on) Log.info(this, "shaking hands");
560 if (cert_requested) {
561 if (Log.on) Log.info(this, "telling the server we have no certificates");
562 writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
565 // generate the premaster secret
566 byte[] pre_master_secret = new byte[48];
567 pre_master_secret[0] = 0x03; // first two bytes of premaster secret are our version number
568 pre_master_secret[1] = 0x00;
569 getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
571 // encrypt and send the pre_master_secret
573 byte[] encrypted_pre_master_secret;
575 SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
576 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
577 BigInteger modulus = rsa_pks.getModulus();
578 BigInteger exponent = rsa_pks.getPublicExponent();
580 if (serverKeyExchange != null) {
582 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
583 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
585 int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
586 byte[] b_modulus = new byte[modulus_size];
587 System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
588 modulus = new BigInteger(1, b_modulus);
590 int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
591 byte[] b_exponent = new byte[exponent_size];
592 System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
593 exponent = new BigInteger(1, b_exponent);
595 byte[] server_params = new byte[modulus_size + exponent_size + 4];
596 System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
598 byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
599 sha(new byte[][] { client_random, server_random, server_params } ) } );
601 byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
602 serverKeyExchange.length - 6 - server_params.length);
604 for(int i=0; i<expectedSignature.length; i++)
605 if (expectedSignature[i] != recievedSignature[i])
606 throw new SSLException("ServerKeyExchange message had invalid signature " + i);
608 if (Log.on) Log.info(this, "ServerKeyExchange successfully processed");
611 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
612 rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
614 encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
615 writeHandshake(16, encrypted_pre_master_secret);
617 } catch (Exception e) {
618 SSLException t = new SSLException("exception encrypting premaster secret");
619 t.fillInStackTrace();
624 if (Log.on) Log.info(this, "Handshake complete; sending ChangeCipherSpec");
625 write(new byte[] { 0x01 }, 0, 1, (byte)20);
628 // compute master_secret
629 master_secret = concat(new byte[][] {
630 md5(new byte[][] { pre_master_secret,
631 sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
632 md5(new byte[][] { pre_master_secret,
633 sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
634 md5(new byte[][] { pre_master_secret,
635 sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
638 // construct the key material
639 byte[] key_material = new byte[] { };
640 for(int i=0; key_material.length < 72; i++) {
641 byte[] crap = new byte[i + 1];
642 for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
643 key_material = concat(new byte[][] { key_material,
644 md5(new byte[][] { master_secret,
645 sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
648 client_write_key = new byte[export ? 5 : 16];
649 server_write_key = new byte[export ? 5 : 16];
651 System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
652 System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
653 System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
654 System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
657 // see SSLv3 spec, 6.2.2 for explanation
658 byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
659 byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
660 client_write_key = new byte[16];
661 server_write_key = new byte[16];
662 System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
663 System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
666 rc4 = new RC4Engine();
667 rc4.init(true, new KeyParameter(client_write_key));
668 is.rc4 = new RC4Engine();
669 is.rc4.init(false, new KeyParameter(server_write_key));
672 writeHandshake(20, concat(new byte[][] {
673 md5(new byte[][] { master_secret, pad2,
674 md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
675 master_secret, pad1 }) }),
676 sha(new byte[][] { master_secret, pad2_sha,
677 sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
678 master_secret, pad1_sha } ) })
681 if (Log.on) Log.info(this, "wrote Finished message");
685 public void writeClientHello() throws IOException {
687 if (Log.on) Log.info(this, "sending ClientHello");
688 int unixtime = (int)(System.currentTimeMillis() / (long)1000);
690 byte[] out = new byte[] {
691 0x03, 0x00, // client version (SSLv3.0)
693 // space for random bytes
694 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
695 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
698 0x0, // empty vector for sessionid
699 0x0, 0x4, 0x0, 0x4, 0x0, 0x3, // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
700 0x1, 0x0 // we only support one compression method: none
703 // don't need to use secure random here since it's sent in the clear
704 Random rand = new Random(System.currentTimeMillis());
705 rand.nextBytes(client_random);
706 intToBytes(unixtime, client_random, 0, 4);
707 System.arraycopy(client_random, 0, out, 2, client_random.length);
709 writeHandshake(1, out);
714 // Static Helpers ////////////////////////////////////////////////////////////////////
716 /** copy the least significant num bytes of val into byte array b, startint at offset */
717 public static void intToBytes(long val, byte[] b, int offset, int num) {
718 for(int i=0; i<num; i++)
719 b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
722 /** fills b with random bytes */
723 public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
724 MD5Digest md5 = new MD5Digest();
725 byte[] b2 = new byte[16];
728 md5.update(randpool, 0, randpool.length);
729 intToBytes(randcnt++, b2, 0, 8);
730 md5.update(b2, 0, 8);
732 int n = len < 16 ? len : 16;
733 System.arraycopy(b2, 0, b, offset, n);
739 public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
740 byte[] MAC = new byte[16];
741 MD5Digest md5 = new MD5Digest();
742 md5.update(MAC_secret, 0, MAC_secret.length);
743 md5.update(pad1, 0, pad1.length);
745 byte[] b = new byte[11];
746 intToBytes(seq_num, b, 0, 8);
748 intToBytes(len, b, 9, 2);
749 md5.update(b, 0, b.length);
751 md5.update(payload, off, len);
754 md5.update(MAC_secret, 0, MAC_secret.length);
755 md5.update(pad2, 0, pad2.length);
756 md5.update(MAC, 0, MAC.length);
762 public static byte[] concat(byte[][] inputs) {
764 for(int i=0; i<inputs.length; i++) total += inputs[i].length;
765 byte[] ret = new byte[total];
767 for(int i=0; i<inputs.length; i++) {
768 System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
769 pos += inputs[i].length;
774 SHA1Digest master_sha1 = new SHA1Digest();
775 public byte[] sha(byte[][] inputs) {
777 for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
778 byte[] ret = new byte[master_sha1.getDigestSize()];
779 master_sha1.doFinal(ret, 0);
783 MD5Digest master_md5 = new MD5Digest();
784 public byte[] md5(byte[][] inputs) {
786 for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
787 byte[] ret = new byte[master_md5.getDigestSize()];
788 master_md5.doFinal(ret, 0);
792 // FEATURE: improve error reporting in here
793 /** returns true iff certificate "signee" is signed by public key "signer" */
794 public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
798 String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
799 if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
800 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
801 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
802 else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
805 // decrypt the signature using the signer's public key
806 byte[] ED = signee.getSignature().getBytes();
807 SubjectPublicKeyInfo pki = signer;
808 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
809 BigInteger modulus = rsa_pks.getModulus();
810 BigInteger exponent = rsa_pks.getPublicExponent();
811 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
812 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
814 // Decode the embedded octet string
815 byte[] D = rsa.processBlock(ED, 0, ED.length);
816 BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
817 DERObject derob = beris.readObject();
818 DERSequence dercs = (DERSequence)derob;
819 DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
820 byte[] MD = deros.getOctets();
822 // generate our own hash
823 ByteArrayOutputStream baos = new ByteArrayOutputStream();
824 DEROutputStream dos = new DEROutputStream(baos);
825 dos.writeObject(signee.getTBSCertificate());
827 byte[] b = baos.toByteArray();
828 hash.update(b, 0, b.length);
829 byte[] md_out = new byte[MD.length];
830 hash.doFinal(md_out, 0);
832 // compare our hash to the signed hash
833 for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
836 } catch (Exception e) {
842 // Embedded Trusted Public Keys //////////////////////////////////////////////
844 /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
845 static String[] base64_encoded_trusted_CA_public_keys = new String[] {
847 "CN=ABA.ECOM Root CA",
848 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
849 "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
850 "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
851 "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
852 "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
853 "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
856 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
857 "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
858 "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
861 "CN=Xcert EZ by DST",
862 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
863 "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
864 "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
865 "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
866 "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
867 "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
869 "CN=Certiposte Classe A Personne",
870 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
871 "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
872 "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
873 "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
874 "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
875 "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
877 "CN=Certiposte Serveur",
878 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
879 "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
880 "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
881 "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
882 "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
883 "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
885 "OU=Certisign - Autoridade Certificadora - AC2",
886 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
887 "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
888 "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
891 "OU=Certisign - Autoridade Certificadora - AC4",
892 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
893 "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
894 "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
897 "OU=Certisign Autoridade Certificadora AC1S",
898 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
899 "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
900 "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
903 "OU=Certisign Autoridade Certificadora AC3S",
904 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
905 "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
906 "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
909 "O=Certplus, CN=Class 1 Primary CA",
910 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
911 "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
912 "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
913 "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
914 "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
915 "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
917 "O=Certplus, CN=Class 2 Primary CA",
918 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
919 "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
920 "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
921 "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
922 "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
923 "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
925 "O=Certplus, CN=Class 3 Primary CA",
926 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
927 "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
928 "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
929 "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
930 "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
931 "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
933 "CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano",
934 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
935 "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
936 "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
937 "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
938 "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
939 "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
941 "O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
942 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
943 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
944 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
947 "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
948 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
949 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
950 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
953 "C=FR, O=Certplus, CN=Class 3P Primary CA",
954 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
955 "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
956 "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
957 "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
958 "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
959 "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
961 "C=FR, O=Certplus, CN=Class 3TS Primary CA",
962 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
963 "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
964 "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
965 "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
966 "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
967 "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
969 "C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority",
970 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
971 "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
972 "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
975 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1",
976 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
977 "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
978 "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
981 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2",
982 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
983 "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
984 "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
985 "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
986 "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
987 "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
989 "C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA",
990 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
991 "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
992 "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
995 "OU=National Retail Federation, CN=DST (NRF) RootCA",
996 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
997 "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
998 "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
999 "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
1000 "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
1001 "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
1003 "OU=United Parcel Service, CN=DST (UPS) RootCA",
1004 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
1005 "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
1006 "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
1007 "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
1008 "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
1009 "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
1011 "CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana",
1012 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
1013 "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
1014 "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
1015 "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
1016 "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
1017 "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
1020 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
1021 "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
1022 "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
1023 "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
1024 "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
1025 "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
1027 "OU=DSTCA X2, CN=DST RootCA X2",
1028 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
1029 "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
1030 "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
1031 "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
1032 "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
1033 "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
1035 "C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA",
1036 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
1037 "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
1038 "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
1041 "C=US, O=Digital Signature Trust Co., OU=DSTCA E1",
1042 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
1043 "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
1044 "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
1047 "C=US, O=Digital Signature Trust Co., OU=DSTCA E2",
1048 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
1049 "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
1050 "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
1053 "CN=Entrust.net Certification Authority (2048)",
1054 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
1055 "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
1056 "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
1057 "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
1058 "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
1059 "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
1061 "CN=Entrust.net Client Certification Authority",
1062 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
1063 "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
1064 "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
1067 "CN=Entrust.net Secure Server Certification Authority",
1068 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
1069 "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
1070 "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
1073 "C=US, O=Equifax, OU=Equifax Secure Certificate Authority",
1074 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
1075 "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
1076 "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
1079 "C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1",
1080 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
1081 "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
1082 "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
1085 "CN=Baltimore EZ by DST",
1086 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
1087 "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
1088 "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
1089 "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
1090 "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
1091 "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
1093 "C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2",
1094 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
1095 "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
1096 "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
1099 "C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1",
1100 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
1101 "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
1102 "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
1105 "O=EUnet International, CN=EUnet International Root CA",
1106 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
1107 "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
1108 "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
1111 "CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org",
1112 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
1113 "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
1114 "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
1117 "CN=FESTE, Verified Certs",
1118 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
1119 "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
1120 "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
1123 "CN=First Data Digital Certificates Inc. Certification Authority",
1124 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
1125 "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
1126 "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
1129 "C=ES, O=FNMT, OU=FNMT Clase 2 CA",
1130 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
1131 "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
1132 "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
1135 "CN=Belgacom E-Trust Primary CA",
1136 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
1137 "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
1138 "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
1141 "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA",
1142 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
1143 "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
1144 "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
1145 "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
1146 "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
1147 "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
1149 "CN=GTE CyberTrust Global Root",
1150 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
1151 "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
1152 "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
1155 "CN=GTE CyberTrust Root",
1156 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
1157 "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
1158 "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
1161 "C=US, O=GTE Corporation, CN=GTE CyberTrust Root",
1162 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
1163 "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
1164 "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
1167 "OU=ValiCert Class 3 Policy Validation Authority",
1168 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
1169 "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
1170 "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
1173 "OU=ValiCert Class 1 Policy Validation Authority",
1174 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
1175 "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
1176 "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
1179 "OU=ValiCert Class 2 Policy Validation Authority",
1180 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
1181 "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
1182 "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
1185 "C=hk, O=C&W HKT SecureNet CA Class A",
1186 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
1187 "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
1188 "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
1189 "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
1190 "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
1191 "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
1193 "CN=IPS SERVIDORES",
1194 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
1195 "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
1196 "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
1199 "CN=Microsoft Root Authority",
1200 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
1201 "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
1202 "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
1203 "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
1204 "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
1205 "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
1207 "CN=Microsoft Root Certificate Authority",
1208 "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
1209 "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
1210 "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
1211 "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
1212 "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
1213 "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
1214 "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
1215 "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
1216 "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
1217 "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
1218 "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
1220 "CN=NetLock Expressz (Class C) Tanusitvanykiado",
1221 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
1222 "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
1223 "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
1226 "CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado",
1227 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
1228 "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
1229 "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
1230 "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
1231 "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
1232 "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
1234 "OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado",
1235 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
1236 "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
1237 "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
1240 "CN=Post.Trust Root CA",
1241 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
1242 "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
1243 "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
1244 "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
1245 "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
1246 "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
1248 "CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl",
1249 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
1250 "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
1251 "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
1252 "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
1253 "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
1254 "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
1256 "CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi",
1257 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
1258 "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
1259 "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
1260 "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
1261 "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
1262 "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
1264 "CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi",
1265 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
1266 "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
1267 "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
1268 "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
1269 "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
1270 "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
1272 "C=hk, O=C&W HKT SecureNet CA Class B",
1273 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
1274 "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
1275 "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
1276 "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
1277 "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
1278 "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
1280 "C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
1281 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
1282 "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
1283 "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
1286 "C=au, O=SecureNet CA Class A",
1287 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
1288 "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
1289 "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
1290 "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
1291 "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
1292 "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
1294 "C=au, O=SecureNet CA Class B",
1295 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
1296 "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
1297 "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
1298 "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
1299 "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
1300 "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
1302 "C=au, O=SecureNet CA Root",
1303 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
1304 "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
1305 "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
1306 "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
1307 "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
1308 "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
1310 "C=au, O=SecureNet CA SGC Root",
1311 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
1312 "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
1313 "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
1314 "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
1315 "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
1316 "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
1318 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1319 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1320 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1321 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1322 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1323 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1324 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1326 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1327 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1328 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1329 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1330 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1331 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1332 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1334 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1335 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1336 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1337 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1338 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1339 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1340 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1342 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1343 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1344 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1345 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1346 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1347 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1348 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1350 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1351 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1352 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1353 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1354 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1355 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1356 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1358 "C=hk, O=C&W HKT SecureNet CA Root",
1359 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
1360 "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
1361 "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
1362 "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
1363 "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
1364 "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
1366 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1367 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1368 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1369 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1370 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1371 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1372 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1374 "CN=SERVICIOS DE CERTIFICACION - A.N.C.",
1375 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
1376 "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
1377 "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
1378 "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
1379 "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
1380 "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
1382 "CN=SIA Secure Client CA",
1383 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
1384 "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
1385 "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
1388 "C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA",
1389 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
1390 "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
1391 "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
1392 "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
1393 "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
1394 "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
1396 "OU=Public CA Services",
1397 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
1398 "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
1399 "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
1400 "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
1401 "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
1402 "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
1404 "OU=TC TrustCenter Class 1 CA",
1405 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
1406 "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
1407 "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
1410 "OU=TC TrustCenter Class 2 CA",
1411 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
1412 "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
1413 "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
1416 "OU=TC TrustCenter Class 3 CA",
1417 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
1418 "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
1419 "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
1422 "OU=TC TrustCenter Class 4 CA",
1423 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
1424 "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
1425 "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
1428 "CN=Thawte Premium Server CA",
1429 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
1430 "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
1431 "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
1434 "C=hk, O=C&W HKT SecureNet CA SGC Root",
1435 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
1436 "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
1437 "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
1438 "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
1439 "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
1440 "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
1442 "CN=Thawte Server CA",
1443 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
1444 "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
1445 "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
1448 "CN=UTN - DATACorp SGC",
1449 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
1450 "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
1451 "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
1452 "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
1453 "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
1454 "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
1456 "CN=UTN-USERFirst-Hardware",
1457 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
1458 "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
1459 "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
1460 "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
1461 "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
1462 "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
1464 "CN=UTN-USERFirst-Network Applications",
1465 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
1466 "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
1467 "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
1468 "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
1469 "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
1470 "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
1472 "CN=VeriSign Class 3 Public Primary Certification Authority - G3",
1473 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
1474 "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
1475 "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
1476 "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
1477 "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
1478 "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
1480 "CN=VeriSign Class 4 Public Primary Certification Authority - G3",
1481 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
1482 "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
1483 "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
1484 "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
1485 "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
1486 "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
1488 "OU=VeriSign Trust Network",
1489 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1490 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1491 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1494 "OU=VeriSign Trust Network",
1495 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1496 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1497 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1500 "OU=VeriSign Trust Network",
1501 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1502 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1503 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1506 "OU=VeriSign Trust Network",
1507 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1508 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1509 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1513 public static boolean alwaysFalse = false;
1515 static class entropySpinner extends Thread {
1516 volatile boolean stop = false;
1518 entropySpinner() { start(); }
1523 // without this line, GCJ will over-optimize this loop into an infinite loop. Argh.
1524 if (alwaysFalse) stop = true;
1531 private static volatile boolean initializationFinished = false;
1533 entropySpinner[] spinners = new entropySpinner[10];
1534 for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
1536 for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
1537 for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
1538 for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
1539 for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
1542 if (Log.on) Log.info(SSL.class, "reading in trusted root public keys...");
1543 trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length / 2];
1544 trusted_CA_public_key_identifiers = new String[base64_encoded_trusted_CA_public_keys.length / 2];
1545 for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i+=2) {
1546 trusted_CA_public_key_identifiers[i/2] = base64_encoded_trusted_CA_public_keys[i];
1547 byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i+1]);
1548 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
1549 trusted_CA_public_keys[i/2] = new SubjectPublicKeyInfo((DERSequence)dIn.readObject());
1552 } catch (Exception e) {
1553 if (Log.on) Log.info(SSL.class, e);
1556 if (Log.on) Log.info(SSL.class, "generating entropy...");
1557 randpool = new byte[10];
1558 try { Thread.sleep(100); } catch (Exception e) { }
1559 for(int i=0; i<spinners.length; i++) {
1560 spinners[i].stop = true;
1561 randpool[i] = spinners[i].counter;
1564 MD5Digest md5 = new MD5Digest();
1565 md5.update(randpool, 0, randpool.length);
1566 intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
1567 intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1568 intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1569 intToBytes(System.identityHashCode(SSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
1570 Properties p = System.getProperties();
1571 for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
1572 String s = (String)e.nextElement();
1573 byte[] b = s.getBytes();
1574 md5.update(b, 0, b.length);
1575 b = p.getProperty(s).getBytes();
1576 md5.update(b, 0, b.length);
1578 randpool = new byte[md5.getDigestSize()];
1579 md5.doFinal(randpool, 0);
1581 if (Log.on) Log.info(SSL.class, "SSL is initialized.");
1582 initializationFinished = true;
1583 SSL.class.notifyAll();
1588 * A PKCS1 encoder which uses SSL's built-in PRNG instead of java.security.SecureRandom.
1589 * This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
1591 private static class PKCS1 implements AsymmetricBlockCipher {
1592 private static int HEADER_LENGTH = 10;
1593 private AsymmetricBlockCipher engine;
1594 private boolean forEncryption;
1595 private boolean forPrivateKey;
1597 public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
1598 public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
1600 public void init(boolean forEncryption, CipherParameters param) {
1601 engine.init(forEncryption, (AsymmetricKeyParameter)param);
1602 this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
1603 this.forEncryption = forEncryption;
1606 public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
1607 public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
1609 public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1610 return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
1613 private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1614 byte[] block = new byte[engine.getInputBlockSize()];
1615 if (forPrivateKey) {
1616 block[0] = 0x01; // type code 1
1617 for (int i = 1; i != block.length - inLen - 1; i++)
1618 block[i] = (byte)0xFF;
1620 getRandomBytes(block, 0, block.length);
1621 block[0] = 0x02; // type code 2
1623 // a zero byte marks the end of the padding, so all
1624 // the pad bytes must be non-zero.
1625 for (int i = 1; i != block.length - inLen - 1; i++)
1626 while (block[i] == 0)
1627 getRandomBytes(block, i, 1);
1630 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
1631 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
1632 return engine.processBlock(block, 0, block.length);
1635 private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1636 byte[] block = engine.processBlock(in, inOff, inLen);
1637 if (block.length < getOutputBlockSize())
1638 throw new InvalidCipherTextException("block truncated");
1639 if (block[0] != 1 && block[0] != 2)
1640 throw new InvalidCipherTextException("unknown block type");
1642 // find and extract the message block.
1644 for (start = 1; start != block.length; start++)
1645 if (block[start] == 0)
1647 start++; // data should start at the next byte
1649 if (start >= block.length || start < HEADER_LENGTH)
1650 throw new InvalidCipherTextException("no data in block");
1652 byte[] result = new byte[block.length - start];
1653 System.arraycopy(block, start, result, 0, result.length);