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.
76 1.0 07-Dec-01 Initial Release
77 1.01 15-Mar-02 Added PKCS1 class to avoid dependancy on java.security.SecureRandom
81 public class TinySSL extends Socket {
83 // Simple Test //////////////////////////////////////////////
85 public static void main(String[] args) {
88 Socket s = new TinySSL("www.paypal.com", 443);
89 PrintWriter pw = new PrintWriter(s.getOutputStream());
90 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
91 pw.println("GET / HTTP/1.0");
96 String s2 = br.readLine();
97 if (s2 == null) return;
98 System.out.println(s2);
101 } catch (Exception e) {
106 // Static Data //////////////////////////////////////////////
108 public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
109 static SubjectPublicKeyInfo[] trusted_CA_public_keys;
110 public static byte[] pad1 = new byte[48];
111 public static byte[] pad2 = new byte[48];
112 public static byte[] pad1_sha = new byte[40];
113 public static byte[] pad2_sha = new byte[40];
114 static byte[] randpool;
115 static long randcnt = 0;
117 // Cipher State //////////////////////////////////////////////
119 public byte[] server_random = new byte[32];
120 public byte[] client_random = new byte[32];
121 public byte[] client_write_MAC_secret = new byte[16];
122 public byte[] server_write_MAC_secret = new byte[16];
123 public byte[] client_write_key = null;
124 public byte[] server_write_key = null;
125 public byte[] master_secret = null;
127 /** the bytes of the ServerKeyExchangeMessage, null if none recieved */
128 public byte[] serverKeyExchange = null;
130 /** true iff the server asked for a certificate */
131 public boolean cert_requested = false;
133 public X509CertificateStructure server_cert = null;
135 public SSLOutputStream os;
136 public SSLInputStream is;
140 /** the concatenation of all the bytes of all handshake messages sent or recieved */
141 public byte[] handshakes = new byte[] { };
143 /** true iff we're using SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
144 boolean export = false;
146 public InputStream getInputStream() { return is; }
147 public OutputStream getOutputStream() { return os; }
149 public TinySSL(String host, int port) throws IOException {
152 os = new SSLOutputStream(super.getOutputStream());
153 is = new SSLInputStream(super.getInputStream());
155 os.writeClientHello();
156 is.readServerHandshakes();
157 os.sendClientHandshakes();
158 is.readServerFinished();
161 class SSLInputStream extends InputStream {
163 /** the underlying inputstream */
166 /** the server's sequence number */
167 public int seq_num = 0;
169 /** the decryption engine */
170 public RC4Engine rc4 = null;
172 /** pending bytes -- decrypted, but not yet fed to consumer */
177 public void mark() { }
178 public void reset() { }
179 public boolean markSupported() { return false; }
180 public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
181 public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
182 public int available() throws IOException { return pendlen; }
184 public int read() throws IOException {
185 byte[] singlebyte = new byte[1];
186 int numread = read(singlebyte);
187 if (numread != 1) return -1;
188 return (int)singlebyte[0];
191 public int read(byte[] b, int off, int len) throws IOException {
193 pend = readRecord(false);
194 if (pend == null) return -1;
196 pendlen = pend.length;
198 int ret = Math.min(len, pendlen);
199 System.arraycopy(pend, pendstart, b, off, ret);
205 /** reads and decrypts exactly one record; blocks if unavailable */
206 public byte[] readRecord(boolean returnHandshakes) throws IOException {
208 // we only catch EOFException here, because anywhere else
209 // would be "unusual", and we *want* and EOFException in
212 try { type = raw.readByte(); } catch (EOFException e) { return null; }
214 byte ver_major = raw.readByte();
215 byte ver_minor = raw.readByte();
216 short len = raw.readShort();
217 if (Log.on) Log.log(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
219 byte[] ret = new byte[len];
222 // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours
223 if (type == 20) { seq_num = 0; return readRecord(returnHandshakes); }
225 byte[] decrypted_payload;
227 // if crypto hasn't been enabled yet; skip crypt and hash
228 if (rc4 == null) decrypted_payload = ret;
230 // decrypt the payload
231 decrypted_payload = new byte[len - 16];
232 rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
235 byte[] MAC = new byte[16];
236 rc4.processBytes(ret, len - 16, 16, MAC, 0);
237 byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
238 for(int i=0; i<MAC.length; i++)
239 if (MAC[i] != ourMAC[i])
240 throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
244 if (decrypted_payload[1] != 0)
245 throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
248 } else if (type == 22) {
249 if (!returnHandshakes) {
250 if (Log.on) Log.log(this, "after completion of handshake, server sent another handshake message!");
251 return readRecord(false);
254 } else if (type != 23) {
255 if (Log.on) Log.log(this, "unexpected record type: " + type + "; skipping");
256 return readRecord(returnHandshakes);
260 if (Log.on) Log.log(this, " returning " + decrypted_payload.length + " byte record payload");
261 return decrypted_payload;
264 /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */
265 public void readServerHandshakes() throws IOException {
267 byte[] rec = readRecord(true);
268 handshakes = concat(new byte[][] { handshakes, rec });
269 DataInputStream stream = new DataInputStream(new ByteArrayInputStream(rec, 4, rec.length - 4));
272 case 2: // ServerHello
273 byte ver_major = rec[4];
274 byte ver_minor = rec[5];
275 System.arraycopy(rec, 6, server_random, 0, server_random.length);
276 short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
277 short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
279 if (cipher_low == 0x04 || cipher_high != 0x00) {
281 if (Log.on) Log.log(this, "using SSL_RSA_WITH_RC4_128_MD5");
283 } else if (cipher_low == 0x03 || cipher_high != 0x00) {
285 if (Log.on) Log.log(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
287 } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
288 " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
289 "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
291 byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
292 if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
293 " but we don't support compression");
296 case 11: // Server's certificate(s)
297 int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
299 X509CertificateStructure last_cert = null;
300 X509CertificateStructure this_cert = null;
302 for(int i=0; i<numcertbytes;) {
303 int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
305 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
306 this_cert = new X509CertificateStructure((DERConstructedSequence)dIn.readObject());
307 } catch (Exception e) {
308 SSLException t = new SSLException("error decoding server certificate: " + e);
309 t.fillInStackTrace();
313 if (server_cert == null) {
314 server_cert = this_cert;
315 TBSCertificateStructure tbs = server_cert.getTBSCertificate();
316 X509Name subject = tbs.getSubject();
318 // gross hack to extract the Common Name so we can compare it to the server hostname
319 String CN = tbs.getSubject().toString() + " ";
320 boolean good = false;
321 for(int j=0; j<CN.length() - 3; j++)
322 if (CN.substring(j, j+3).equals("CN=")) {
324 CN = CN.substring(j+3, CN.indexOf(' ', j+3));
328 if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
329 if (!CN.equals(hostname))
330 throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
332 SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yy-HH-mm-ss-z");
334 // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
335 String s = tbs.getStartDate().getTime();
336 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
337 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
338 Date startDate = dateF.parse(s, new ParsePosition(0));
340 s = tbs.getEndDate().getTime();
341 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
342 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
343 Date endDate = dateF.parse(s, new ParsePosition(0));
345 Date now = new Date();
346 if (now.after(endDate)) throw new SSLException("server certificate expired on " + endDate);
347 if (now.before(startDate)) throw new SSLException("server certificate will not be valid until " + startDate);
349 Log.log(this, "server cert (name, validity dates) checks out okay");
351 } else if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
352 throw new SSLException("certificate chain discontinuity");
354 last_cert = this_cert;
358 if (Log.on) Log.log(this, " Certificate (" + numcerts + " certificates)");
360 boolean good = false;
361 for(int i=0; i<trusted_CA_public_keys.length; i++) {
362 if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
363 if (Log.on) Log.log(this, "server cert was signed by trusted CA " + i);
368 if (!good) throw new SSLException("server cert was not signed by a trusted CA");
372 serverKeyExchange = rec;
375 case 13: cert_requested = true; break;
376 case 14: if (Log.on) Log.log(this, " ServerHelloDone"); return;
377 default: throw new SSLException("unknown handshake of type " + rec[0]);
382 public void readServerFinished() throws IOException {
383 byte[] rec = readRecord(true);
384 if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
386 byte[] expectedFinished = concat(new byte[][] {
387 md5(new byte[][] { master_secret, pad2,
388 md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
389 master_secret, pad1 }) }),
390 sha(new byte[][] { master_secret, pad2_sha,
391 sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
392 master_secret, pad1_sha } ) } ) } );
394 for(int i=0; i<expectedFinished.length; i++)
395 if (expectedFinished[i] != rec[i + 4])
396 throw new SSLException("server Finished message mismatch!");
398 if (Log.on) Log.log(this, "server finished message checked out okay!");
403 class SSLOutputStream extends OutputStream {
405 /** the underlying outputstream */
406 DataOutputStream raw;
408 /** the sequence number for sending */
409 public long seq_num = 0;
411 /** the encryption engine for sending */
412 RC4Engine rc4 = null;
414 public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
415 public void flush() throws IOException { raw.flush(); }
416 public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
417 public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
418 public void close() throws IOException {
419 write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
423 /** writes a single SSL Record */
424 public void write(byte[] payload, int off, int len, byte type) throws IOException {
426 // largest permissible frame is 2^14 octets
428 write(payload, off, 1 << 14, type);
429 write(payload, off + 1 << 14, len - 1 << 14, type);
434 raw.writeShort(0x0300);
438 raw.write(payload, off, len);
441 byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
442 byte[] encryptedPayload = new byte[MAC.length + len];
443 rc4.processBytes(payload, off, len, encryptedPayload, 0);
444 rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
445 raw.writeShort(encryptedPayload.length);
446 raw.write(encryptedPayload);
453 /** tacks a handshake header onto payload before sending it */
454 public void writeHandshake(int type, byte[] payload) throws IOException {
455 byte[] real_payload = new byte[payload.length + 4];
456 System.arraycopy(payload, 0, real_payload, 4, payload.length);
457 real_payload[0] = (byte)(type & 0xFF);
458 intToBytes(payload.length, real_payload, 1, 3);
459 handshakes = concat(new byte[][] { handshakes, real_payload });
460 write(real_payload, 0, real_payload.length, (byte)22);
463 public void sendClientHandshakes() throws IOException {
465 if (Log.on) Log.log(this, "shaking hands");
466 if (cert_requested) {
467 if (Log.on) Log.log(this, "telling the server we have no certificates");
468 writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
471 // generate the premaster secret
472 byte[] pre_master_secret = new byte[48];
473 pre_master_secret[0] = 0x03; // first two bytes of premaster secret are our version number
474 pre_master_secret[1] = 0x00;
475 getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
477 // encrypt and send the pre_master_secret
479 byte[] encrypted_pre_master_secret;
481 SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
482 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERConstructedSequence)pki.getPublicKey());
483 BigInteger modulus = rsa_pks.getModulus();
484 BigInteger exponent = rsa_pks.getPublicExponent();
486 if (serverKeyExchange != null) {
488 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
489 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
491 int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
492 byte[] b_modulus = new byte[modulus_size];
493 System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
494 modulus = new BigInteger(1, b_modulus);
496 int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
497 byte[] b_exponent = new byte[exponent_size];
498 System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
499 exponent = new BigInteger(1, b_exponent);
501 byte[] server_params = new byte[modulus_size + exponent_size + 4];
502 System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
504 byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
505 sha(new byte[][] { client_random, server_random, server_params } ) } );
507 byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
508 serverKeyExchange.length - 6 - server_params.length);
510 for(int i=0; i<expectedSignature.length; i++)
511 if (expectedSignature[i] != recievedSignature[i])
512 throw new SSLException("ServerKeyExchange message had invalid signature " + i);
514 if (Log.on) Log.log(this, "ServerKeyExchange successfully processed");
517 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
518 rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
520 encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
521 writeHandshake(16, encrypted_pre_master_secret);
523 } catch (Exception e) {
524 SSLException t = new SSLException("exception encrypting premaster secret");
525 t.fillInStackTrace();
530 if (Log.on) Log.log(this, "Handshake complete; sending ChangeCipherSpec");
531 write(new byte[] { 0x01 }, 0, 1, (byte)20);
534 // compute master_secret
535 master_secret = concat(new byte[][] {
536 md5(new byte[][] { pre_master_secret,
537 sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
538 md5(new byte[][] { pre_master_secret,
539 sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
540 md5(new byte[][] { pre_master_secret,
541 sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
544 // construct the key material
545 byte[] key_material = new byte[] { };
546 for(int i=0; key_material.length < 72; i++) {
547 byte[] crap = new byte[i + 1];
548 for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
549 key_material = concat(new byte[][] { key_material,
550 md5(new byte[][] { master_secret,
551 sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
554 client_write_key = new byte[export ? 5 : 16];
555 server_write_key = new byte[export ? 5 : 16];
557 System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
558 System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
559 System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
560 System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
563 // see SSLv3 spec, 6.2.2 for explanation
564 byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
565 byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
566 client_write_key = new byte[16];
567 server_write_key = new byte[16];
568 System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
569 System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
572 rc4 = new RC4Engine();
573 rc4.init(true, new KeyParameter(client_write_key));
574 is.rc4 = new RC4Engine();
575 is.rc4.init(false, new KeyParameter(server_write_key));
578 writeHandshake(20, concat(new byte[][] {
579 md5(new byte[][] { master_secret, pad2,
580 md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
581 master_secret, pad1 }) }),
582 sha(new byte[][] { master_secret, pad2_sha,
583 sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
584 master_secret, pad1_sha } ) })
587 if (Log.on) Log.log(this, "wrote Finished message");
591 public void writeClientHello() throws IOException {
593 if (Log.on) Log.log(this, "sending ClientHello");
594 int unixtime = (int)(System.currentTimeMillis() / (long)1000);
596 byte[] out = new byte[] {
597 0x03, 0x00, // client version (SSLv3.0)
599 // space for random bytes
600 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
601 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
604 0x0, // empty vector for sessionid
605 0x0, 0x4, 0x0, 0x4, 0x0, 0x3, // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
606 0x1, 0x0 // we only support one compression method: none
609 // don't need to use secure random here since it's sent in the clear
610 Random rand = new Random(System.currentTimeMillis());
611 rand.nextBytes(client_random);
612 intToBytes(unixtime, client_random, 0, 4);
613 System.arraycopy(client_random, 0, out, 2, client_random.length);
615 writeHandshake(1, out);
620 // Static Helpers ////////////////////////////////////////////////////////////////////
622 /** copy the least significant num bytes of val into byte array b, startint at offset */
623 public static void intToBytes(long val, byte[] b, int offset, int num) {
624 for(int i=0; i<num; i++)
625 b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
628 /** fills b with random bytes */
629 public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
630 MD5Digest md5 = new MD5Digest();
631 byte[] b2 = new byte[16];
634 md5.update(randpool, 0, randpool.length);
635 intToBytes(randcnt++, b2, 0, 8);
636 md5.update(b2, 0, 8);
638 int n = len < 16 ? len : 16;
639 System.arraycopy(b2, 0, b, offset, n);
645 public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
646 byte[] MAC = new byte[16];
647 MD5Digest md5 = new MD5Digest();
648 md5.update(MAC_secret, 0, MAC_secret.length);
649 md5.update(pad1, 0, pad1.length);
651 byte[] b = new byte[11];
652 intToBytes(seq_num, b, 0, 8);
654 intToBytes(len, b, 9, 2);
655 md5.update(b, 0, b.length);
657 md5.update(payload, off, len);
660 md5.update(MAC_secret, 0, MAC_secret.length);
661 md5.update(pad2, 0, pad2.length);
662 md5.update(MAC, 0, MAC.length);
668 public static byte[] concat(byte[][] inputs) {
670 for(int i=0; i<inputs.length; i++) total += inputs[i].length;
671 byte[] ret = new byte[total];
673 for(int i=0; i<inputs.length; i++) {
674 System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
675 pos += inputs[i].length;
680 SHA1Digest master_sha1 = new SHA1Digest();
681 public byte[] sha(byte[][] inputs) {
683 for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
684 byte[] ret = new byte[master_sha1.getDigestSize()];
685 master_sha1.doFinal(ret, 0);
689 MD5Digest master_md5 = new MD5Digest();
690 public byte[] md5(byte[][] inputs) {
692 for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
693 byte[] ret = new byte[master_md5.getDigestSize()];
694 master_md5.doFinal(ret, 0);
698 // FEATURE: improve error reporting in here
699 /** returns true iff certificate "signee" is signed by public key "signer" */
700 public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
704 String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
705 if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
706 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
707 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
708 else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
711 // decrypt the signature using the signer's public key
712 byte[] ED = signee.getSignature().getBytes();
713 SubjectPublicKeyInfo pki = signer;
714 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERConstructedSequence)pki.getPublicKey());
715 BigInteger modulus = rsa_pks.getModulus();
716 BigInteger exponent = rsa_pks.getPublicExponent();
717 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
718 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
720 // Decode the embedded octet string
721 byte[] D = rsa.processBlock(ED, 0, ED.length);
722 BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
723 DERObject derob = beris.readObject();
724 DERConstructedSequence dercs = (DERConstructedSequence)derob;
725 DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
726 byte[] MD = deros.getOctets();
728 // generate our own hash
729 ByteArrayOutputStream baos = new ByteArrayOutputStream();
730 DEROutputStream dos = new DEROutputStream(baos);
731 dos.writeObject(signee.getTBSCertificate());
733 byte[] b = baos.toByteArray();
734 hash.update(b, 0, b.length);
735 byte[] md_out = new byte[MD.length];
736 hash.doFinal(md_out, 0);
738 // compare our hash to the signed hash
739 for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
742 } catch (Exception e) {
748 // Embedded Trusted Public Keys //////////////////////////////////////////////
750 /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
751 static String[] base64_encoded_trusted_CA_public_keys = new String[] {
753 // CN=ABA.ECOM Root CA
754 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
755 "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
756 "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
757 "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
758 "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
759 "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
762 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
763 "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
764 "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
767 // CN=Xcert EZ by DST
768 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
769 "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
770 "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
771 "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
772 "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
773 "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
775 // CN=Certiposte Classe A Personne
776 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
777 "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
778 "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
779 "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
780 "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
781 "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
783 // CN=Certiposte Serveur
784 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
785 "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
786 "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
787 "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
788 "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
789 "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
791 // OU=Certisign - Autoridade Certificadora - AC2
792 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
793 "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
794 "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
797 // OU=Certisign - Autoridade Certificadora - AC4
798 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
799 "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
800 "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
803 // OU=Certisign Autoridade Certificadora AC1S
804 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
805 "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
806 "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
809 // OU=Certisign Autoridade Certificadora AC3S
810 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
811 "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
812 "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
815 // O=Certplus, CN=Class 1 Primary CA
816 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
817 "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
818 "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
819 "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
820 "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
821 "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
823 // O=Certplus, CN=Class 2 Primary CA
824 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
825 "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
826 "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
827 "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
828 "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
829 "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
831 // O=Certplus, CN=Class 3 Primary CA
832 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
833 "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
834 "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
835 "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
836 "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
837 "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
839 // CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano
840 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
841 "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
842 "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
843 "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
844 "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
845 "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
847 // O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
848 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
849 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
850 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
853 // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
854 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
855 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
856 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
859 // C=FR, O=Certplus, CN=Class 3P Primary CA
860 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
861 "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
862 "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
863 "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
864 "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
865 "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
867 // C=FR, O=Certplus, CN=Class 3TS Primary CA
868 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
869 "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
870 "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
871 "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
872 "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
873 "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
875 // C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority
876 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
877 "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
878 "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
881 // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1
882 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
883 "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
884 "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
887 // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2
888 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
889 "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
890 "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
891 "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
892 "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
893 "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
895 // C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA
896 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
897 "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
898 "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
901 // OU=National Retail Federation, CN=DST (NRF) RootCA
902 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
903 "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
904 "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
905 "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
906 "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
907 "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
909 // OU=United Parcel Service, CN=DST (UPS) RootCA
910 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
911 "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
912 "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
913 "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
914 "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
915 "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
917 // CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana
918 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
919 "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
920 "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
921 "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
922 "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
923 "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
926 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
927 "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
928 "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
929 "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
930 "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
931 "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
933 // OU=DSTCA X2, CN=DST RootCA X2
934 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
935 "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
936 "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
937 "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
938 "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
939 "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
941 // C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA
942 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
943 "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
944 "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
947 // C=US, O=Digital Signature Trust Co., OU=DSTCA E1
948 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
949 "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
950 "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
953 // C=US, O=Digital Signature Trust Co., OU=DSTCA E2
954 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
955 "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
956 "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
959 // CN=Entrust.net Certification Authority (2048)
960 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
961 "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
962 "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
963 "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
964 "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
965 "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
967 // CN=Entrust.net Client Certification Authority
968 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
969 "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
970 "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
973 // CN=Entrust.net Secure Server Certification Authority
974 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
975 "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
976 "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
979 // C=US, O=Equifax, OU=Equifax Secure Certificate Authority
980 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
981 "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
982 "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
985 // C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1
986 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
987 "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
988 "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
991 // CN=Baltimore EZ by DST
992 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
993 "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
994 "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
995 "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
996 "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
997 "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
999 // C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2
1000 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
1001 "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
1002 "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
1005 // C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1
1006 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
1007 "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
1008 "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
1011 // O=EUnet International, CN=EUnet International Root CA
1012 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
1013 "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
1014 "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
1017 // CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org
1018 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
1019 "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
1020 "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
1023 // CN=FESTE, Verified Certs
1024 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
1025 "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
1026 "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
1029 // CN=First Data Digital Certificates Inc. Certification Authority
1030 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
1031 "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
1032 "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
1035 // C=ES, O=FNMT, OU=FNMT Clase 2 CA
1036 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
1037 "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
1038 "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
1041 // CN=Belgacom E-Trust Primary CA
1042 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
1043 "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
1044 "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
1047 // C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
1048 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
1049 "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
1050 "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
1051 "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
1052 "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
1053 "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
1055 // CN=GTE CyberTrust Global Root
1056 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
1057 "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
1058 "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
1061 // CN=GTE CyberTrust Root
1062 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
1063 "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
1064 "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
1067 // C=US, O=GTE Corporation, CN=GTE CyberTrust Root
1068 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
1069 "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
1070 "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
1073 // OU=ValiCert Class 3 Policy Validation Authority
1074 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
1075 "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
1076 "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
1079 // OU=ValiCert Class 1 Policy Validation Authority
1080 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
1081 "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
1082 "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
1085 // OU=ValiCert Class 2 Policy Validation Authority
1086 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
1087 "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
1088 "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
1091 // C=hk, O=C&W HKT SecureNet CA Class A
1092 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
1093 "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
1094 "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
1095 "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
1096 "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
1097 "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
1099 // CN=IPS SERVIDORES
1100 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
1101 "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
1102 "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
1105 // CN=Microsoft Root Authority
1106 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
1107 "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
1108 "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
1109 "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
1110 "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
1111 "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
1113 // CN=Microsoft Root Certificate Authority
1114 "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
1115 "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
1116 "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
1117 "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
1118 "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
1119 "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
1120 "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
1121 "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
1122 "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
1123 "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
1124 "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
1126 // CN=NetLock Expressz (Class C) Tanusitvanykiado
1127 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
1128 "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
1129 "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
1132 // CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado
1133 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
1134 "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
1135 "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
1136 "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
1137 "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
1138 "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
1140 // OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado
1141 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
1142 "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
1143 "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
1146 // CN=Post.Trust Root CA
1147 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
1148 "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
1149 "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
1150 "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
1151 "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
1152 "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
1154 // CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl
1155 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
1156 "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
1157 "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
1158 "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
1159 "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
1160 "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
1162 // CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi
1163 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
1164 "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
1165 "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
1166 "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
1167 "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
1168 "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
1170 // CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi
1171 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
1172 "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
1173 "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
1174 "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
1175 "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
1176 "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
1178 // C=hk, O=C&W HKT SecureNet CA Class B
1179 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
1180 "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
1181 "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
1182 "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
1183 "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
1184 "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
1186 // C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
1187 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
1188 "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
1189 "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
1192 // C=au, O=SecureNet CA Class A
1193 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
1194 "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
1195 "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
1196 "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
1197 "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
1198 "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
1200 // C=au, O=SecureNet CA Class B
1201 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
1202 "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
1203 "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
1204 "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
1205 "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
1206 "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
1208 // C=au, O=SecureNet CA Root
1209 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
1210 "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
1211 "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
1212 "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
1213 "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
1214 "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
1216 // C=au, O=SecureNet CA SGC Root
1217 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
1218 "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
1219 "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
1220 "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
1221 "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
1222 "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
1224 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
1225 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1226 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1227 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1228 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1229 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1230 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1232 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
1233 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1234 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1235 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1236 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1237 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1238 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1240 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2
1241 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1242 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1243 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1244 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1245 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1246 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1248 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2
1249 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1250 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1251 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1252 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1253 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1254 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1256 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3
1257 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1258 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1259 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1260 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1261 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1262 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1264 // C=hk, O=C&W HKT SecureNet CA Root
1265 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
1266 "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
1267 "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
1268 "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
1269 "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
1270 "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
1272 // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3
1273 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1274 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1275 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1276 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1277 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1278 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1280 // CN=SERVICIOS DE CERTIFICACION - A.N.C.
1281 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
1282 "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
1283 "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
1284 "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
1285 "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
1286 "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
1288 // CN=SIA Secure Client CA
1289 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
1290 "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
1291 "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
1294 // C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA
1295 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
1296 "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
1297 "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
1298 "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
1299 "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
1300 "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
1302 // OU=Public CA Services
1303 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
1304 "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
1305 "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
1306 "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
1307 "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
1308 "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
1310 // OU=TC TrustCenter Class 1 CA
1311 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
1312 "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
1313 "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
1316 // OU=TC TrustCenter Class 2 CA
1317 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
1318 "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
1319 "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
1322 // OU=TC TrustCenter Class 3 CA
1323 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
1324 "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
1325 "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
1328 // OU=TC TrustCenter Class 4 CA
1329 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
1330 "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
1331 "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
1334 // CN=Thawte Premium Server CA
1335 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
1336 "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
1337 "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
1340 // C=hk, O=C&W HKT SecureNet CA SGC Root
1341 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
1342 "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
1343 "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
1344 "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
1345 "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
1346 "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
1348 // CN=Thawte Server CA
1349 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
1350 "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
1351 "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
1354 // CN=UTN - DATACorp SGC
1355 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
1356 "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
1357 "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
1358 "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
1359 "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
1360 "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
1362 // CN=UTN-USERFirst-Hardware
1363 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
1364 "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
1365 "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
1366 "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
1367 "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
1368 "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
1370 // CN=UTN-USERFirst-Network Applications
1371 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
1372 "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
1373 "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
1374 "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
1375 "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
1376 "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
1378 // CN=VeriSign Class 3 Public Primary Certification Authority - G3
1379 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
1380 "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
1381 "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
1382 "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
1383 "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
1384 "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
1386 // CN=VeriSign Class 4 Public Primary Certification Authority - G3
1387 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
1388 "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
1389 "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
1390 "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
1391 "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
1392 "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
1394 // OU=VeriSign Trust Network
1395 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1396 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1397 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1400 // OU=VeriSign Trust Network
1401 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1402 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1403 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1406 // OU=VeriSign Trust Network
1407 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1408 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1409 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1412 // OU=VeriSign Trust Network
1413 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1414 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1415 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1420 static class entropySpinner extends Thread {
1421 volatile boolean stop = false;
1423 entropySpinner() { start(); }
1424 public void run() { while (!stop) counter++; }
1429 entropySpinner[] spinners = new entropySpinner[10];
1430 for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
1432 for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
1433 for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
1434 for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
1435 for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
1438 if (Log.on) Log.log(TinySSL.class, "reading in trusted root public keys...");
1439 trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length];
1440 for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i++) {
1441 byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i]);
1442 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
1443 trusted_CA_public_keys[i] = new SubjectPublicKeyInfo((DERConstructedSequence)dIn.readObject());
1446 } catch (Exception e) {
1447 if (Log.on) Log.log(TinySSL.class, e);
1450 randpool = new byte[10];
1451 try { Thread.sleep(100); } catch (Exception e) { }
1452 for(int i=0; i<spinners.length; i++) {
1453 spinners[i].stop = true;
1454 randpool[i] = spinners[i].counter;
1457 MD5Digest md5 = new MD5Digest();
1458 md5.update(randpool, 0, randpool.length);
1459 intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
1460 intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1461 intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1462 intToBytes(System.identityHashCode(TinySSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
1463 Properties p = System.getProperties();
1464 for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
1465 String s = (String)e.nextElement();
1466 byte[] b = s.getBytes();
1467 md5.update(b, 0, b.length);
1468 b = p.getProperty(s).getBytes();
1469 md5.update(b, 0, b.length);
1471 randpool = new byte[md5.getDigestSize()];
1472 md5.doFinal(randpool, 0);
1478 * A PKCS1 encoder which uses TinySSL's built-in PRNG instead of java.security.SecureRandom.
1479 * This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
1481 private static class PKCS1 implements AsymmetricBlockCipher {
1482 private static int HEADER_LENGTH = 10;
1483 private AsymmetricBlockCipher engine;
1484 private boolean forEncryption;
1485 private boolean forPrivateKey;
1487 public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
1488 public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
1490 public void init(boolean forEncryption, CipherParameters param) {
1491 engine.init(forEncryption, (AsymmetricKeyParameter)param);
1492 this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
1493 this.forEncryption = forEncryption;
1496 public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
1497 public int getOutputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
1499 public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1500 return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
1503 private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1504 byte[] block = new byte[engine.getInputBlockSize()];
1505 if (forPrivateKey) {
1506 block[0] = 0x01; // type code 1
1507 for (int i = 1; i != block.length - inLen - 1; i++)
1508 block[i] = (byte)0xFF;
1510 getRandomBytes(block, 0, block.length);
1511 block[0] = 0x02; // type code 2
1513 // a zero byte marks the end of the padding, so all
1514 // the pad bytes must be non-zero.
1515 for (int i = 1; i != block.length - inLen - 1; i++)
1516 while (block[i] == 0)
1517 getRandomBytes(block, i, 1);
1520 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
1521 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
1522 return engine.processBlock(block, 0, block.length);
1525 private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1526 byte[] block = engine.processBlock(in, inOff, inLen);
1527 if (block.length < getOutputBlockSize())
1528 throw new InvalidCipherTextException("block truncated");
1529 if (block[0] != 1 && block[0] != 2)
1530 throw new InvalidCipherTextException("unknown block type");
1532 // find and extract the message block.
1534 for (start = 1; start != block.length; start++)
1535 if (block[start] == 0)
1537 start++; // data should start at the next byte
1539 if (start >= block.length || start < HEADER_LENGTH)
1540 throw new InvalidCipherTextException("no data in block");
1542 byte[] result = new byte[block.length - start];
1543 System.arraycopy(block, start, result, 0, result.length);