1 // Copyright (C) 2001 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.DERConstructedSequence;
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.xwt.util.Log;
43 TinySSL: a tiny SSL implementation in Java, built on the
44 bouncycastle.org lightweight crypto library.
46 This class implements an SSLv3 client-side socket, with the
47 SSL_RSA_EXPORT_WITH_RC4_40_MD5 and SSL_RSA_WITH_RC4_128_MD5 cipher
48 suites, as well as certificate chain verification against a
49 collection of 93 built-in Trusted Root CA public keys (the same 93
50 included with Microsoft Internet Explorer 5.5 SP2).
52 As of 07-Dec-01, the zipped bytecode for this class is 43k, and the
53 subset of bouncycastle it requires is 82k.
55 This class should work correctly on any Java 1.1 compliant
56 platform. The java.security.* classes are not used.
58 The main design goal for this class was the smallest possible body
59 of code capable of connecting to 99% of all active HTTPS
60 servers. Although this class is useful in many other situations
61 (IMAPS, Secure SMTP, etc), the author will refuse all feature
62 requests and submitted patches which go beyond this scope.
64 Because of the limited goals of this class, certain abstractions
65 have been avoided, and certain parameters have been
66 hard-coded. "Magic numbers" are often used instead of "static final
67 int"'s, although they are usually accompanied by a descriptive
68 comment. Numeric offsets into byte arrays are also favored over
69 DataInputStream(ByteArrayInputStream(foo))'s.
71 Much thanks and credit go to the BouncyCastle team for producing
72 such a first-class library, and for helping me out on the
73 dev-crypto mailing list while I was writing this.
77 1.0 07-Dec-01 Initial Release
79 1.01 15-Mar-02 Added PKCS1 class to avoid dependancy on java.security.SecureRandom
81 1.02 27-Mar-02 Fixed a bug which would hang the connection when more than one
82 Handshake message appeared in the same TLS Record
86 public class TinySSL extends Socket {
88 // Simple Test //////////////////////////////////////////////
90 public static void main(String[] args) {
93 Socket s = new TinySSL("www.verisign.com", 443);
94 PrintWriter pw = new PrintWriter(s.getOutputStream());
95 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
96 pw.println("GET / HTTP/1.0");
101 String s2 = br.readLine();
102 if (s2 == null) return;
103 System.out.println(s2);
106 } catch (Exception e) {
111 // Static Data //////////////////////////////////////////////
113 public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
114 static SubjectPublicKeyInfo[] trusted_CA_public_keys;
115 public static byte[] pad1 = new byte[48];
116 public static byte[] pad2 = new byte[48];
117 public static byte[] pad1_sha = new byte[40];
118 public static byte[] pad2_sha = new byte[40];
119 static byte[] randpool;
120 static long randcnt = 0;
122 // Cipher State //////////////////////////////////////////////
124 public byte[] server_random = new byte[32];
125 public byte[] client_random = new byte[32];
126 public byte[] client_write_MAC_secret = new byte[16];
127 public byte[] server_write_MAC_secret = new byte[16];
128 public byte[] client_write_key = null;
129 public byte[] server_write_key = null;
130 public byte[] master_secret = null;
132 /** the bytes of the ServerKeyExchangeMessage, null if none recieved */
133 public byte[] serverKeyExchange = null;
135 /** true iff the server asked for a certificate */
136 public boolean cert_requested = false;
138 public X509CertificateStructure server_cert = null;
140 public SSLOutputStream os;
141 public SSLInputStream is;
145 /** the concatenation of all the bytes of all handshake messages sent or recieved */
146 public byte[] handshakes = new byte[] { };
148 /** true iff we're using SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
149 boolean export = false;
151 public InputStream getInputStream() { return is; }
152 public OutputStream getOutputStream() { return os; }
154 public TinySSL(String host, int port) throws IOException { this(host, port, true); }
155 public TinySSL(String host, int port, boolean negotiateImmediately) throws IOException {
158 if (negotiateImmediately) negotiate();
161 /** negotiates the SSL connection */
162 public void negotiate() throws IOException {
163 os = new SSLOutputStream(super.getOutputStream());
164 is = new SSLInputStream(super.getInputStream());
165 os.writeClientHello();
166 is.readServerHandshakes();
167 os.sendClientHandshakes();
168 is.readServerFinished();
171 class SSLInputStream extends InputStream {
173 /** the underlying inputstream */
176 /** the server's sequence number */
177 public int seq_num = 0;
179 /** the decryption engine */
180 public RC4Engine rc4 = null;
182 /** pending bytes -- decrypted, but not yet fed to consumer */
187 public void mark() { }
188 public void reset() { }
189 public boolean markSupported() { return false; }
190 public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
191 public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
192 public int available() throws IOException { return pendlen; }
194 public int read() throws IOException {
195 byte[] singlebyte = new byte[1];
196 int numread = read(singlebyte);
197 if (numread != 1) return -1;
198 return (int)singlebyte[0];
201 public int read(byte[] b, int off, int len) throws IOException {
204 if (pend == null) return -1;
206 pendlen = pend.length;
208 int ret = Math.min(len, pendlen);
209 System.arraycopy(pend, pendstart, b, off, ret);
215 /** reads and decrypts exactly one record; blocks if unavailable */
216 public byte[] readRecord() throws IOException {
218 // we only catch EOFException here, because anywhere else
219 // would be "unusual", and we *want* and EOFException in
222 try { type = raw.readByte();
223 } catch (EOFException e) {
224 if (Log.on) Log.log(this, "got EOFException reading packet type");
228 byte ver_major = raw.readByte();
229 byte ver_minor = raw.readByte();
230 short len = raw.readShort();
231 if (Log.on) Log.log(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
233 byte[] ret = new byte[len];
236 // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours
238 if (Log.on) Log.log(this, "got ChangeCipherSpec; ignoring");
243 byte[] decrypted_payload;
245 // if crypto hasn't been enabled yet; skip crypt and hash
246 if (rc4 == null) decrypted_payload = ret;
248 // decrypt the payload
249 decrypted_payload = new byte[len - 16];
250 rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
253 byte[] MAC = new byte[16];
254 rc4.processBytes(ret, len - 16, 16, MAC, 0);
255 byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
256 for(int i=0; i<MAC.length; i++)
257 if (MAC[i] != ourMAC[i])
258 throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
262 if (decrypted_payload[1] > 1) {
263 throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
264 } else if (decrypted_payload[1] == 0) {
265 if (Log.on) Log.log(this, "server requested connection closure; returning null");
268 if (Log.on) Log.log(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
272 } else if (type == 22) {
273 if (Log.on) Log.log(this, "read a handshake");
275 } else if (type != 23) {
276 if (Log.on) Log.log(this, "unexpected record type: " + type + "; skipping");
281 if (Log.on) Log.log(this, " returning " + decrypted_payload.length + " byte record payload");
282 return decrypted_payload;
285 private byte[] readHandshake() throws IOException {
286 // acquire a handshake message
287 byte type = (byte)read();
288 int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff);
289 byte[] rec = new byte[len + 4];
291 rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff);
292 rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff);
293 rec[3] = (byte)((len & 0x000000ff) & 0xff);
294 if (len > 0) read(rec, 4, len);
298 /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */
299 public void readServerHandshakes() throws IOException {
302 byte[] rec = readHandshake();
303 handshakes = concat(new byte[][] { handshakes, rec });
304 DataInputStream stream = new DataInputStream(new ByteArrayInputStream(rec, 4, rec.length - 4));
307 case 2: // ServerHello
308 if (Log.on) Log.log(this, "got ServerHello");
309 byte ver_major = rec[4];
310 byte ver_minor = rec[5];
311 System.arraycopy(rec, 6, server_random, 0, server_random.length);
312 short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
313 short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
315 if (cipher_low == 0x04 || cipher_high != 0x00) {
317 if (Log.on) Log.log(this, "using SSL_RSA_WITH_RC4_128_MD5");
319 } else if (cipher_low == 0x03 || cipher_high != 0x00) {
321 if (Log.on) Log.log(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
323 } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
324 " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
325 "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
327 byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
328 if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
329 " but we don't support compression");
332 case 11: // Server's certificate(s)
333 if (Log.on) Log.log(this, "got Server Certificate(s)");
334 int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
336 X509CertificateStructure last_cert = null;
337 X509CertificateStructure this_cert = null;
339 for(int i=0; i<numcertbytes;) {
340 int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
342 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
343 this_cert = new X509CertificateStructure((DERConstructedSequence)dIn.readObject());
344 } catch (Exception e) {
345 SSLException t = new SSLException("error decoding server certificate: " + e);
346 t.fillInStackTrace();
350 if (server_cert == null) {
351 server_cert = this_cert;
352 TBSCertificateStructure tbs = server_cert.getTBSCertificate();
353 X509Name subject = tbs.getSubject();
355 // gross hack to extract the Common Name so we can compare it to the server hostname
356 String CN = tbs.getSubject().toString() + " ";
357 boolean good = false;
358 for(int j=0; j<CN.length() - 3; j++)
359 if (CN.substring(j, j+3).equals("CN=")) {
361 CN = CN.substring(j+3, CN.indexOf(' ', j+3));
365 if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
366 if (!CN.equals(hostname))
367 throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
369 SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yy-HH-mm-ss-z");
371 // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
372 String s = tbs.getStartDate().getTime();
373 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
374 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
375 Date startDate = dateF.parse(s, new ParsePosition(0));
377 s = tbs.getEndDate().getTime();
378 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
379 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
380 Date endDate = dateF.parse(s, new ParsePosition(0));
382 Date now = new Date();
383 if (now.after(endDate)) throw new SSLException("server certificate expired on " + endDate);
384 if (now.before(startDate)) throw new SSLException("server certificate will not be valid until " + startDate);
386 Log.log(this, "server cert (name, validity dates) checks out okay");
388 } else if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
389 throw new SSLException("certificate chain discontinuity");
391 last_cert = this_cert;
395 if (Log.on) Log.log(this, " Certificate (" + numcerts + " certificates)");
397 boolean good = false;
398 for(int i=0; i<trusted_CA_public_keys.length; i++) {
399 if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
400 if (Log.on) Log.log(this, "server cert was signed by trusted CA " + i);
405 if (!good) throw new SSLException("server cert was not signed by a trusted CA");
409 if (Log.on) Log.log(this, "got ServerKeyExchange");
410 serverKeyExchange = rec;
414 if (Log.on) Log.log(this, "got Request for Client Certificates");
415 cert_requested = true;
418 case 14: if (Log.on) Log.log(this, " ServerHelloDone"); return;
419 default: throw new SSLException("unknown handshake of type " + rec[0]);
424 public void readServerFinished() throws IOException {
426 byte[] rec = readHandshake();
427 if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
429 byte[] expectedFinished = concat(new byte[][] {
430 md5(new byte[][] { master_secret, pad2,
431 md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
432 master_secret, pad1 }) }),
433 sha(new byte[][] { master_secret, pad2_sha,
434 sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
435 master_secret, pad1_sha } ) } ) } );
437 for(int i=0; i<expectedFinished.length; i++)
438 if (expectedFinished[i] != rec[i + 4])
439 throw new SSLException("server Finished message mismatch!");
441 if (Log.on) Log.log(this, "server finished message checked out okay!");
446 class SSLOutputStream extends OutputStream {
448 /** the underlying outputstream */
449 DataOutputStream raw;
451 /** the sequence number for sending */
452 public long seq_num = 0;
454 /** the encryption engine for sending */
455 RC4Engine rc4 = null;
457 public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
458 public void flush() throws IOException { raw.flush(); }
459 public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
460 public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
461 public void close() throws IOException {
462 write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
466 /** writes a single SSL Record */
467 public void write(byte[] payload, int off, int len, byte type) throws IOException {
469 // largest permissible frame is 2^14 octets
471 write(payload, off, 1 << 14, type);
472 write(payload, off + 1 << 14, len - 1 << 14, type);
477 raw.writeShort(0x0300);
481 raw.write(payload, off, len);
484 byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
485 byte[] encryptedPayload = new byte[MAC.length + len];
486 rc4.processBytes(payload, off, len, encryptedPayload, 0);
487 rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
488 raw.writeShort(encryptedPayload.length);
489 raw.write(encryptedPayload);
496 /** tacks a handshake header onto payload before sending it */
497 public void writeHandshake(int type, byte[] payload) throws IOException {
498 byte[] real_payload = new byte[payload.length + 4];
499 System.arraycopy(payload, 0, real_payload, 4, payload.length);
500 real_payload[0] = (byte)(type & 0xFF);
501 intToBytes(payload.length, real_payload, 1, 3);
502 handshakes = concat(new byte[][] { handshakes, real_payload });
503 write(real_payload, 0, real_payload.length, (byte)22);
506 public void sendClientHandshakes() throws IOException {
508 if (Log.on) Log.log(this, "shaking hands");
509 if (cert_requested) {
510 if (Log.on) Log.log(this, "telling the server we have no certificates");
511 writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
514 // generate the premaster secret
515 byte[] pre_master_secret = new byte[48];
516 pre_master_secret[0] = 0x03; // first two bytes of premaster secret are our version number
517 pre_master_secret[1] = 0x00;
518 getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
520 // encrypt and send the pre_master_secret
522 byte[] encrypted_pre_master_secret;
524 SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
525 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERConstructedSequence)pki.getPublicKey());
526 BigInteger modulus = rsa_pks.getModulus();
527 BigInteger exponent = rsa_pks.getPublicExponent();
529 if (serverKeyExchange != null) {
531 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
532 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
534 int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
535 byte[] b_modulus = new byte[modulus_size];
536 System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
537 modulus = new BigInteger(1, b_modulus);
539 int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
540 byte[] b_exponent = new byte[exponent_size];
541 System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
542 exponent = new BigInteger(1, b_exponent);
544 byte[] server_params = new byte[modulus_size + exponent_size + 4];
545 System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
547 byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
548 sha(new byte[][] { client_random, server_random, server_params } ) } );
550 byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
551 serverKeyExchange.length - 6 - server_params.length);
553 for(int i=0; i<expectedSignature.length; i++)
554 if (expectedSignature[i] != recievedSignature[i])
555 throw new SSLException("ServerKeyExchange message had invalid signature " + i);
557 if (Log.on) Log.log(this, "ServerKeyExchange successfully processed");
560 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
561 rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
563 encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
564 writeHandshake(16, encrypted_pre_master_secret);
566 } catch (Exception e) {
567 SSLException t = new SSLException("exception encrypting premaster secret");
568 t.fillInStackTrace();
573 if (Log.on) Log.log(this, "Handshake complete; sending ChangeCipherSpec");
574 write(new byte[] { 0x01 }, 0, 1, (byte)20);
577 // compute master_secret
578 master_secret = concat(new byte[][] {
579 md5(new byte[][] { pre_master_secret,
580 sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
581 md5(new byte[][] { pre_master_secret,
582 sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
583 md5(new byte[][] { pre_master_secret,
584 sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
587 // construct the key material
588 byte[] key_material = new byte[] { };
589 for(int i=0; key_material.length < 72; i++) {
590 byte[] crap = new byte[i + 1];
591 for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
592 key_material = concat(new byte[][] { key_material,
593 md5(new byte[][] { master_secret,
594 sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
597 client_write_key = new byte[export ? 5 : 16];
598 server_write_key = new byte[export ? 5 : 16];
600 System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
601 System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
602 System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
603 System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
606 // see SSLv3 spec, 6.2.2 for explanation
607 byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
608 byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
609 client_write_key = new byte[16];
610 server_write_key = new byte[16];
611 System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
612 System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
615 rc4 = new RC4Engine();
616 rc4.init(true, new KeyParameter(client_write_key));
617 is.rc4 = new RC4Engine();
618 is.rc4.init(false, new KeyParameter(server_write_key));
621 writeHandshake(20, concat(new byte[][] {
622 md5(new byte[][] { master_secret, pad2,
623 md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
624 master_secret, pad1 }) }),
625 sha(new byte[][] { master_secret, pad2_sha,
626 sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
627 master_secret, pad1_sha } ) })
630 if (Log.on) Log.log(this, "wrote Finished message");
634 public void writeClientHello() throws IOException {
636 if (Log.on) Log.log(this, "sending ClientHello");
637 int unixtime = (int)(System.currentTimeMillis() / (long)1000);
639 byte[] out = new byte[] {
640 0x03, 0x00, // client version (SSLv3.0)
642 // space for random bytes
643 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
644 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
647 0x0, // empty vector for sessionid
648 0x0, 0x4, 0x0, 0x4, 0x0, 0x3, // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
649 0x1, 0x0 // we only support one compression method: none
652 // don't need to use secure random here since it's sent in the clear
653 Random rand = new Random(System.currentTimeMillis());
654 rand.nextBytes(client_random);
655 intToBytes(unixtime, client_random, 0, 4);
656 System.arraycopy(client_random, 0, out, 2, client_random.length);
658 writeHandshake(1, out);
663 // Static Helpers ////////////////////////////////////////////////////////////////////
665 /** copy the least significant num bytes of val into byte array b, startint at offset */
666 public static void intToBytes(long val, byte[] b, int offset, int num) {
667 for(int i=0; i<num; i++)
668 b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
671 /** fills b with random bytes */
672 public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
673 MD5Digest md5 = new MD5Digest();
674 byte[] b2 = new byte[16];
677 md5.update(randpool, 0, randpool.length);
678 intToBytes(randcnt++, b2, 0, 8);
679 md5.update(b2, 0, 8);
681 int n = len < 16 ? len : 16;
682 System.arraycopy(b2, 0, b, offset, n);
688 public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
689 byte[] MAC = new byte[16];
690 MD5Digest md5 = new MD5Digest();
691 md5.update(MAC_secret, 0, MAC_secret.length);
692 md5.update(pad1, 0, pad1.length);
694 byte[] b = new byte[11];
695 intToBytes(seq_num, b, 0, 8);
697 intToBytes(len, b, 9, 2);
698 md5.update(b, 0, b.length);
700 md5.update(payload, off, len);
703 md5.update(MAC_secret, 0, MAC_secret.length);
704 md5.update(pad2, 0, pad2.length);
705 md5.update(MAC, 0, MAC.length);
711 public static byte[] concat(byte[][] inputs) {
713 for(int i=0; i<inputs.length; i++) total += inputs[i].length;
714 byte[] ret = new byte[total];
716 for(int i=0; i<inputs.length; i++) {
717 System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
718 pos += inputs[i].length;
723 SHA1Digest master_sha1 = new SHA1Digest();
724 public byte[] sha(byte[][] inputs) {
726 for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
727 byte[] ret = new byte[master_sha1.getDigestSize()];
728 master_sha1.doFinal(ret, 0);
732 MD5Digest master_md5 = new MD5Digest();
733 public byte[] md5(byte[][] inputs) {
735 for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
736 byte[] ret = new byte[master_md5.getDigestSize()];
737 master_md5.doFinal(ret, 0);
741 // FEATURE: improve error reporting in here
742 /** returns true iff certificate "signee" is signed by public key "signer" */
743 public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
747 String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
748 if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
749 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
750 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
751 else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
754 // decrypt the signature using the signer's public key
755 byte[] ED = signee.getSignature().getBytes();
756 SubjectPublicKeyInfo pki = signer;
757 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERConstructedSequence)pki.getPublicKey());
758 BigInteger modulus = rsa_pks.getModulus();
759 BigInteger exponent = rsa_pks.getPublicExponent();
760 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
761 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
763 // Decode the embedded octet string
764 byte[] D = rsa.processBlock(ED, 0, ED.length);
765 BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
766 DERObject derob = beris.readObject();
767 DERConstructedSequence dercs = (DERConstructedSequence)derob;
768 DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
769 byte[] MD = deros.getOctets();
771 // generate our own hash
772 ByteArrayOutputStream baos = new ByteArrayOutputStream();
773 DEROutputStream dos = new DEROutputStream(baos);
774 dos.writeObject(signee.getTBSCertificate());
776 byte[] b = baos.toByteArray();
777 hash.update(b, 0, b.length);
778 byte[] md_out = new byte[MD.length];
779 hash.doFinal(md_out, 0);
781 // compare our hash to the signed hash
782 for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
785 } catch (Exception e) {
791 // Embedded Trusted Public Keys //////////////////////////////////////////////
793 /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
794 static String[] base64_encoded_trusted_CA_public_keys = new String[] {
796 // CN=ABA.ECOM Root CA
797 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
798 "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
799 "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
800 "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
801 "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
802 "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
805 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
806 "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
807 "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
810 // CN=Xcert EZ by DST
811 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
812 "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
813 "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
814 "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
815 "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
816 "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
818 // CN=Certiposte Classe A Personne
819 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
820 "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
821 "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
822 "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
823 "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
824 "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
826 // CN=Certiposte Serveur
827 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
828 "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
829 "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
830 "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
831 "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
832 "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
834 // OU=Certisign - Autoridade Certificadora - AC2
835 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
836 "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
837 "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
840 // OU=Certisign - Autoridade Certificadora - AC4
841 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
842 "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
843 "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
846 // OU=Certisign Autoridade Certificadora AC1S
847 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
848 "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
849 "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
852 // OU=Certisign Autoridade Certificadora AC3S
853 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
854 "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
855 "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
858 // O=Certplus, CN=Class 1 Primary CA
859 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
860 "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
861 "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
862 "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
863 "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
864 "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
866 // O=Certplus, CN=Class 2 Primary CA
867 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
868 "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
869 "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
870 "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
871 "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
872 "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
874 // O=Certplus, CN=Class 3 Primary CA
875 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
876 "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
877 "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
878 "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
879 "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
880 "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
882 // CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano
883 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
884 "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
885 "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
886 "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
887 "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
888 "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
890 // O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
891 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
892 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
893 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
896 // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
897 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
898 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
899 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
902 // C=FR, O=Certplus, CN=Class 3P Primary CA
903 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
904 "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
905 "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
906 "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
907 "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
908 "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
910 // C=FR, O=Certplus, CN=Class 3TS Primary CA
911 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
912 "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
913 "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
914 "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
915 "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
916 "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
918 // C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority
919 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
920 "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
921 "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
924 // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1
925 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
926 "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
927 "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
930 // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2
931 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
932 "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
933 "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
934 "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
935 "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
936 "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
938 // C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA
939 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
940 "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
941 "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
944 // OU=National Retail Federation, CN=DST (NRF) RootCA
945 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
946 "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
947 "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
948 "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
949 "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
950 "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
952 // OU=United Parcel Service, CN=DST (UPS) RootCA
953 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
954 "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
955 "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
956 "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
957 "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
958 "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
960 // CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana
961 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
962 "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
963 "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
964 "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
965 "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
966 "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
969 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
970 "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
971 "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
972 "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
973 "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
974 "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
976 // OU=DSTCA X2, CN=DST RootCA X2
977 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
978 "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
979 "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
980 "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
981 "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
982 "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
984 // C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA
985 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
986 "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
987 "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
990 // C=US, O=Digital Signature Trust Co., OU=DSTCA E1
991 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
992 "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
993 "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
996 // C=US, O=Digital Signature Trust Co., OU=DSTCA E2
997 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
998 "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
999 "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
1002 // CN=Entrust.net Certification Authority (2048)
1003 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
1004 "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
1005 "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
1006 "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
1007 "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
1008 "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
1010 // CN=Entrust.net Client Certification Authority
1011 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
1012 "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
1013 "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
1016 // CN=Entrust.net Secure Server Certification Authority
1017 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
1018 "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
1019 "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
1022 // C=US, O=Equifax, OU=Equifax Secure Certificate Authority
1023 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
1024 "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
1025 "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
1028 // C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1
1029 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
1030 "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
1031 "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
1034 // CN=Baltimore EZ by DST
1035 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
1036 "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
1037 "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
1038 "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
1039 "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
1040 "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
1042 // C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2
1043 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
1044 "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
1045 "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
1048 // C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1
1049 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
1050 "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
1051 "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
1054 // O=EUnet International, CN=EUnet International Root CA
1055 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
1056 "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
1057 "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
1060 // CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org
1061 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
1062 "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
1063 "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
1066 // CN=FESTE, Verified Certs
1067 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
1068 "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
1069 "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
1072 // CN=First Data Digital Certificates Inc. Certification Authority
1073 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
1074 "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
1075 "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
1078 // C=ES, O=FNMT, OU=FNMT Clase 2 CA
1079 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
1080 "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
1081 "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
1084 // CN=Belgacom E-Trust Primary CA
1085 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
1086 "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
1087 "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
1090 // C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
1091 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
1092 "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
1093 "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
1094 "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
1095 "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
1096 "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
1098 // CN=GTE CyberTrust Global Root
1099 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
1100 "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
1101 "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
1104 // CN=GTE CyberTrust Root
1105 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
1106 "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
1107 "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
1110 // C=US, O=GTE Corporation, CN=GTE CyberTrust Root
1111 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
1112 "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
1113 "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
1116 // OU=ValiCert Class 3 Policy Validation Authority
1117 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
1118 "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
1119 "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
1122 // OU=ValiCert Class 1 Policy Validation Authority
1123 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
1124 "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
1125 "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
1128 // OU=ValiCert Class 2 Policy Validation Authority
1129 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
1130 "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
1131 "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
1134 // C=hk, O=C&W HKT SecureNet CA Class A
1135 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
1136 "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
1137 "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
1138 "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
1139 "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
1140 "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
1142 // CN=IPS SERVIDORES
1143 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
1144 "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
1145 "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
1148 // CN=Microsoft Root Authority
1149 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
1150 "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
1151 "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
1152 "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
1153 "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
1154 "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
1156 // CN=Microsoft Root Certificate Authority
1157 "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
1158 "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
1159 "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
1160 "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
1161 "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
1162 "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
1163 "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
1164 "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
1165 "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
1166 "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
1167 "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
1169 // CN=NetLock Expressz (Class C) Tanusitvanykiado
1170 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
1171 "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
1172 "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
1175 // CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado
1176 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
1177 "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
1178 "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
1179 "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
1180 "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
1181 "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
1183 // OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado
1184 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
1185 "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
1186 "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
1189 // CN=Post.Trust Root CA
1190 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
1191 "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
1192 "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
1193 "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
1194 "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
1195 "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
1197 // CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl
1198 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
1199 "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
1200 "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
1201 "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
1202 "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
1203 "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
1205 // CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi
1206 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
1207 "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
1208 "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
1209 "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
1210 "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
1211 "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
1213 // CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi
1214 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
1215 "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
1216 "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
1217 "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
1218 "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
1219 "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
1221 // C=hk, O=C&W HKT SecureNet CA Class B
1222 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
1223 "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
1224 "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
1225 "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
1226 "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
1227 "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
1229 // C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
1230 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
1231 "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
1232 "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
1235 // C=au, O=SecureNet CA Class A
1236 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
1237 "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
1238 "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
1239 "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
1240 "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
1241 "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
1243 // C=au, O=SecureNet CA Class B
1244 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
1245 "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
1246 "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
1247 "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
1248 "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
1249 "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
1251 // C=au, O=SecureNet CA Root
1252 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
1253 "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
1254 "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
1255 "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
1256 "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
1257 "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
1259 // C=au, O=SecureNet CA SGC Root
1260 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
1261 "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
1262 "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
1263 "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
1264 "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
1265 "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
1267 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
1268 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1269 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1270 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1271 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1272 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1273 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1275 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
1276 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1277 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1278 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1279 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1280 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1281 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1283 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2
1284 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1285 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1286 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1287 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1288 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1289 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1291 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2
1292 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1293 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1294 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1295 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1296 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1297 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1299 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3
1300 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1301 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1302 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1303 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1304 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1305 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1307 // C=hk, O=C&W HKT SecureNet CA Root
1308 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
1309 "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
1310 "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
1311 "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
1312 "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
1313 "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
1315 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3
1316 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1317 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1318 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1319 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1320 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1321 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1323 // CN=SERVICIOS DE CERTIFICACION - A.N.C.
1324 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
1325 "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
1326 "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
1327 "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
1328 "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
1329 "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
1331 // CN=SIA Secure Client CA
1332 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
1333 "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
1334 "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
1337 // C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA
1338 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
1339 "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
1340 "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
1341 "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
1342 "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
1343 "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
1345 // OU=Public CA Services
1346 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
1347 "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
1348 "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
1349 "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
1350 "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
1351 "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
1353 // OU=TC TrustCenter Class 1 CA
1354 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
1355 "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
1356 "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
1359 // OU=TC TrustCenter Class 2 CA
1360 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
1361 "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
1362 "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
1365 // OU=TC TrustCenter Class 3 CA
1366 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
1367 "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
1368 "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
1371 // OU=TC TrustCenter Class 4 CA
1372 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
1373 "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
1374 "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
1377 // CN=Thawte Premium Server CA
1378 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
1379 "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
1380 "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
1383 // C=hk, O=C&W HKT SecureNet CA SGC Root
1384 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
1385 "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
1386 "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
1387 "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
1388 "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
1389 "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
1391 // CN=Thawte Server CA
1392 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
1393 "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
1394 "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
1397 // CN=UTN - DATACorp SGC
1398 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
1399 "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
1400 "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
1401 "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
1402 "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
1403 "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
1405 // CN=UTN-USERFirst-Hardware
1406 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
1407 "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
1408 "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
1409 "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
1410 "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
1411 "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
1413 // CN=UTN-USERFirst-Network Applications
1414 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
1415 "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
1416 "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
1417 "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
1418 "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
1419 "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
1421 // CN=VeriSign Class 3 Public Primary Certification Authority - G3
1422 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
1423 "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
1424 "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
1425 "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
1426 "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
1427 "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
1429 // CN=VeriSign Class 4 Public Primary Certification Authority - G3
1430 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
1431 "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
1432 "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
1433 "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
1434 "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
1435 "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
1437 // OU=VeriSign Trust Network
1438 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1439 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1440 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1443 // OU=VeriSign Trust Network
1444 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1445 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1446 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1449 // OU=VeriSign Trust Network
1450 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1451 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1452 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1455 // OU=VeriSign Trust Network
1456 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1457 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1458 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1463 static class entropySpinner extends Thread {
1464 volatile boolean stop = false;
1466 entropySpinner() { start(); }
1467 public void run() { while (!stop) counter++; }
1472 entropySpinner[] spinners = new entropySpinner[10];
1473 for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
1475 for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
1476 for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
1477 for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
1478 for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
1481 if (Log.on) Log.log(TinySSL.class, "reading in trusted root public keys...");
1482 trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length];
1483 for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i++) {
1484 byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i]);
1485 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
1486 trusted_CA_public_keys[i] = new SubjectPublicKeyInfo((DERConstructedSequence)dIn.readObject());
1489 } catch (Exception e) {
1490 if (Log.on) Log.log(TinySSL.class, e);
1493 randpool = new byte[10];
1494 try { Thread.sleep(100); } catch (Exception e) { }
1495 for(int i=0; i<spinners.length; i++) {
1496 spinners[i].stop = true;
1497 randpool[i] = spinners[i].counter;
1500 MD5Digest md5 = new MD5Digest();
1501 md5.update(randpool, 0, randpool.length);
1502 intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
1503 intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1504 intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1505 intToBytes(System.identityHashCode(TinySSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
1506 Properties p = System.getProperties();
1507 for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
1508 String s = (String)e.nextElement();
1509 byte[] b = s.getBytes();
1510 md5.update(b, 0, b.length);
1511 b = p.getProperty(s).getBytes();
1512 md5.update(b, 0, b.length);
1514 randpool = new byte[md5.getDigestSize()];
1515 md5.doFinal(randpool, 0);
1521 * A PKCS1 encoder which uses TinySSL's built-in PRNG instead of java.security.SecureRandom.
1522 * This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
1524 private static class PKCS1 implements AsymmetricBlockCipher {
1525 private static int HEADER_LENGTH = 10;
1526 private AsymmetricBlockCipher engine;
1527 private boolean forEncryption;
1528 private boolean forPrivateKey;
1530 public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
1531 public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
1533 public void init(boolean forEncryption, CipherParameters param) {
1534 engine.init(forEncryption, (AsymmetricKeyParameter)param);
1535 this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
1536 this.forEncryption = forEncryption;
1539 public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
1540 public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
1542 public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1543 return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
1546 private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1547 byte[] block = new byte[engine.getInputBlockSize()];
1548 if (forPrivateKey) {
1549 block[0] = 0x01; // type code 1
1550 for (int i = 1; i != block.length - inLen - 1; i++)
1551 block[i] = (byte)0xFF;
1553 getRandomBytes(block, 0, block.length);
1554 block[0] = 0x02; // type code 2
1556 // a zero byte marks the end of the padding, so all
1557 // the pad bytes must be non-zero.
1558 for (int i = 1; i != block.length - inLen - 1; i++)
1559 while (block[i] == 0)
1560 getRandomBytes(block, i, 1);
1563 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
1564 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
1565 return engine.processBlock(block, 0, block.length);
1568 private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1569 byte[] block = engine.processBlock(in, inOff, inLen);
1570 if (block.length < getOutputBlockSize())
1571 throw new InvalidCipherTextException("block truncated");
1572 if (block[0] != 1 && block[0] != 2)
1573 throw new InvalidCipherTextException("unknown block type");
1575 // find and extract the message block.
1577 for (start = 1; start != block.length; start++)
1578 if (block[start] == 0)
1580 start++; // data should start at the next byte
1582 if (start >= block.length || start < HEADER_LENGTH)
1583 throw new InvalidCipherTextException("no data in block");
1585 byte[] result = new byte[block.length - start];
1586 System.arraycopy(block, start, result, 0, result.length);