1
2
3
4
5
6
7
8 package org.xwt;
9
10 import org.bouncycastle.crypto.AsymmetricBlockCipher;
11 import org.bouncycastle.crypto.Digest;
12 import org.bouncycastle.crypto.CipherParameters;
13 import org.bouncycastle.crypto.InvalidCipherTextException;
14 import org.bouncycastle.crypto.params.RSAKeyParameters;
15 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
16 import org.bouncycastle.crypto.params.KeyParameter;
17 import org.bouncycastle.crypto.digests.SHA1Digest;
18 import org.bouncycastle.crypto.digests.MD5Digest;
19 import org.bouncycastle.crypto.digests.MD2Digest;
20 import org.bouncycastle.crypto.engines.RSAEngine;
21 import org.bouncycastle.crypto.engines.RC4Engine;
22 import org.bouncycastle.util.encoders.Base64;
23 import org.bouncycastle.asn1.DERInputStream;
24 import org.bouncycastle.asn1.DEROutputStream;
25 import org.bouncycastle.asn1.DERSequence;
26 import org.bouncycastle.asn1.DERObject;
27 import org.bouncycastle.asn1.DEROctetString;
28 import org.bouncycastle.asn1.BERInputStream;
29 import org.bouncycastle.asn1.x509.X509CertificateStructure;
30 import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
31 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
32 import org.bouncycastle.asn1.x509.TBSCertificateStructure;
33 import org.bouncycastle.asn1.x509.X509Name;
34 import org.bouncycastle.asn1.x509.X509Extensions;
35 import org.bouncycastle.asn1.x509.X509Extension;
36 import org.bouncycastle.asn1.x509.BasicConstraints;
37 import org.xwt.util.Log;
38 import java.net.*;
39 import java.io.*;
40 import java.util.*;
41 import java.math.*;
42 import java.text.*;
43
44
91
92 public class TinySSL extends Socket {
93
94
95
96 public static void main(String[] args) {
97 Log.on = true;
98 try {
99 Socket s = new TinySSL("www.paypal.com", 443);
100 PrintWriter pw = new PrintWriter(s.getOutputStream());
101 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
102 pw.println("GET / HTTP/1.0");
103 pw.println("");
104 pw.flush();
105
106 while(true) {
107 String s2 = br.readLine();
108 if (s2 == null) return;
109 Log.log(TinySSL.class, s2);
110 }
111
112 } catch (Exception e) {
113 e.printStackTrace();
114 }
115 }
116
117
118
119 public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
120 static SubjectPublicKeyInfo[] trusted_CA_public_keys;
121 static String[] trusted_CA_public_key_identifiers;
122 public static byte[] pad1 = new byte[48];
123 public static byte[] pad2 = new byte[48];
124 public static byte[] pad1_sha = new byte[40];
125 public static byte[] pad2_sha = new byte[40];
126 static byte[] randpool;
127 static long randcnt = 0;
128
129
130
131 public byte[] server_random = new byte[32];
132 public byte[] client_random = new byte[32];
133 public byte[] client_write_MAC_secret = new byte[16];
134 public byte[] server_write_MAC_secret = new byte[16];
135 public byte[] client_write_key = null;
136 public byte[] server_write_key = null;
137 public byte[] master_secret = null;
138
139
140 public byte[] serverKeyExchange = null;
141
142
143 public boolean cert_requested = false;
144
145 public X509CertificateStructure server_cert = null;
146
147 public SSLOutputStream os = null;
148 public SSLInputStream is = null;
149
150 String hostname;
151
152
153 boolean ignoreUntrustedCert = false;
154
155
156 public byte[] handshakes = new byte[] { };
157
158
159 boolean export = false;
160
161 public InputStream getInputStream() throws IOException { return is != null ? is : super.getInputStream(); }
162 public OutputStream getOutputStream() throws IOException { return os != null ? os : super.getOutputStream(); }
163
164 public TinySSL(String host, int port) throws IOException { this(host, port, true, false); }
165 public TinySSL(String host, int port, boolean negotiateImmediately) throws IOException { this(host, port, negotiateImmediately, false); }
166 public TinySSL(String host, int port, boolean negotiateImmediately, boolean ignoreUntrustedCert) throws IOException {
167 super(host, port);
168 if (!initializationFinished) {
169 synchronized(TinySSL.class) {
170 while (!initializationFinished)
171 try { TinySSL.class.wait(); } catch (Exception e) { }
172 }
173 }
174 hostname = host;
175 this.ignoreUntrustedCert = ignoreUntrustedCert;
176 if (negotiateImmediately) negotiate();
177 }
178
179
180 public void negotiate() throws IOException {
181 os = new SSLOutputStream(super.getOutputStream());
182 is = new SSLInputStream(super.getInputStream());
183 os.writeClientHello();
184 is.readServerHandshakes();
185 os.sendClientHandshakes();
186 is.readServerFinished();
187 }
188
189 class SSLInputStream extends InputStream {
190
191
192 DataInputStream raw;
193
194
195 public int seq_num = 0;
196
197
198 public RC4Engine rc4 = null;
199
200
201 byte[] pend = null;
202 int pendstart = 0;
203 int pendlen = 0;
204
205 public void mark() { }
206 public void reset() { }
207 public boolean markSupported() { return false; }
208 public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
209 public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
210 public int available() throws IOException { return pendlen; }
211
212 public int read() throws IOException {
213 byte[] singlebyte = new byte[1];
214 int numread = read(singlebyte);
215 if (numread != 1) return -1;
216 return (int)singlebyte[0];
217 }
218
219 public int read(byte[] b, int off, int len) throws IOException {
220 if (pendlen == 0) {
221 pend = readRecord();
222 if (pend == null) return -1;
223 pendstart = 0;
224 pendlen = pend.length;
225 }
226 int ret = Math.min(len, pendlen);
227 System.arraycopy(pend, pendstart, b, off, ret);
228 pendlen -= ret;
229 pendstart += ret;
230 return ret;
231 }
232
233
234 public byte[] readRecord() throws IOException {
235
236
237
238
239 byte type;
240 try { type = raw.readByte();
241 } catch (EOFException e) {
242 if (Log.on) Log.log(this, "got EOFException reading packet type");
243 return null;
244 }
245
246 byte ver_major = raw.readByte();
247 byte ver_minor = raw.readByte();
248 short len = raw.readShort();
249 if (Log.on) Log.log(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
250
251 byte[] ret = new byte[len];
252 raw.readFully(ret);
253
254
255 if (type == 20) {
256 if (Log.on) Log.log(this, "got ChangeCipherSpec; ignoring");
257 seq_num = 0;
258 return readRecord();
259 }
260
261 byte[] decrypted_payload;
262
263
264 if (rc4 == null) decrypted_payload = ret;
265 else {
266
267 decrypted_payload = new byte[len - 16];
268 rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
269
270
271 byte[] MAC = new byte[16];
272 rc4.processBytes(ret, len - 16, 16, MAC, 0);
273 byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
274 for(int i=0; i<MAC.length; i++)
275 if (MAC[i] != ourMAC[i])
276 throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
277 }
278
279 if (type == 21) {
280 if (decrypted_payload[1] > 1) {
281 throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
282 } else if (decrypted_payload[1] == 0) {
283 if (Log.on) Log.log(this, "server requested connection closure; returning null");
284 return null;
285 } else {
286 if (Log.on) Log.log(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
287 return readRecord();
288 }
289
290 } else if (type == 22) {
291 if (Log.on) Log.log(this, "read a handshake");
292
293 } else if (type != 23) {
294 if (Log.on) Log.log(this, "unexpected record type: " + type + "; skipping");
295 return readRecord();
296
297 }
298
299 if (Log.on) Log.log(this, " returning " + decrypted_payload.length + " byte record payload");
300 return decrypted_payload;
301 }
302
303 private byte[] readHandshake() throws IOException {
304
305 byte type = (byte)read();
306 int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff);
307 byte[] rec = new byte[len + 4];
308 rec[0] = type;
309 rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff);
310 rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff);
311 rec[3] = (byte)((len & 0x000000ff) & 0xff);
312 if (len > 0) read(rec, 4, len);
313 return rec;
314 }
315
316
317 public void readServerHandshakes() throws IOException {
318 for(;;) {
319
320 byte[] rec = readHandshake();
321 handshakes = concat(new byte[][] { handshakes, rec });
322 DataInputStream stream = new DataInputStream(new ByteArrayInputStream(rec, 4, rec.length - 4));
323
324 switch(rec[0]) {
325 case 2:
326 if (Log.on) Log.log(this, "got ServerHello");
327 byte ver_major = rec[4];
328 byte ver_minor = rec[5];
329 System.arraycopy(rec, 6, server_random, 0, server_random.length);
330 short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
331 short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
332
333 if (cipher_low == 0x04 || cipher_high != 0x00) {
334 export = false;
335 if (Log.on) Log.log(this, "using SSL_RSA_WITH_RC4_128_MD5");
336
337 } else if (cipher_low == 0x03 || cipher_high != 0x00) {
338 export = true;
339 if (Log.on) Log.log(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
340
341 } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
342 " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
343 "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
344
345 byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
346 if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
347 " but we don't support compression");
348 break;
349
350 case 11:
351 if (Log.on) Log.log(this, "got Server Certificate(s)");
352 int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
353 int numcerts = 0;
354 X509CertificateStructure last_cert = null;
355 X509CertificateStructure this_cert = null;
356
357 for(int i=0; i<numcertbytes;) {
358 int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
359 try {
360 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
361 this_cert = new X509CertificateStructure((DERSequence)dIn.readObject());
362 } catch (Exception e) {
363 SSLException t = new SSLException("error decoding server certificate: " + e);
364 t.fillInStackTrace();
365 throw t;
366 }
367
368 if (server_cert == null) {
369 server_cert = this_cert;
370 TBSCertificateStructure tbs = server_cert.getTBSCertificate();
371 X509Name subject = tbs.getSubject();
372
373
374 String CN = tbs.getSubject().toString() + " ";
375 boolean good = false;
376 for(int j=0; j<CN.length() - 3; j++)
377 if (CN.substring(j, j+3).equals("CN=")) {
378 good = true;
379 CN = CN.substring(j+3, CN.indexOf(' ', j+3));
380 break;
381 }
382
383 if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
384 if (!ignoreUntrustedCert && !CN.equalsIgnoreCase(hostname))
385 throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
386
387 SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss-z");
388
389
390 String s = tbs.getStartDate().getTime();
391 s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8) + "-" +
392 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" +
393 s.substring(12, 14) + "-" + s.substring(14);
394
395 Date startDate = dateF.parse(s, new ParsePosition(0));
396
397 s = tbs.getEndDate().getTime();
398 s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
399 s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
400 Date endDate = dateF.parse(s, new ParsePosition(0));
401
402 Date now = new Date();
403 if (!ignoreUntrustedCert && now.after(endDate))
404 throw new SSLException("server certificate expired on " + endDate);
405 if (!ignoreUntrustedCert && now.before(startDate))
406 throw new SSLException("server certificate will not be valid until " + startDate);
407
408 Log.log(this, "server cert (name, validity dates) checks out okay");
409
410 } else {
411
412
413 if (certlen + 3 + i < numcertbytes) {
414
415 X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints);
416 if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block");
417 DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets()));
418 BasicConstraints bc = new BasicConstraints((DERSequence)dis.readObject());
419 if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing");
420 }
421
422 if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
423 throw new SSLException("the server sent a broken chain of certificates");
424 }
425
426 last_cert = this_cert;
427 i += certlen + 3;
428 numcerts++;
429 }
430 if (Log.on) Log.log(this, " Certificate (" + numcerts + " certificates)");
431
432 if (ignoreUntrustedCert) break;
433
434 boolean good = false;
435
436
437 String subject = this_cert.getSubject().toString();
438 for(int i=0; i<trusted_CA_public_keys.length; i++) {
439 if (subject.indexOf(trusted_CA_public_key_identifiers[i]) != -1 && isSignedBy(this_cert, trusted_CA_public_keys[i])) {
440 if (Log.on) Log.log(this, "pass 1: server cert was signed by trusted CA " + i);
441 good = true;
442 break;
443 }
444 }
445
446
447 if (!good)
448 for(int i=0; i<trusted_CA_public_keys.length; i++) {
449 if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
450 if (Log.on) Log.log(this, "pass 2: server cert was signed by trusted CA " + i);
451 good = true;
452 break;
453 }
454 }
455
456 if (!good) throw new SSLException("server cert was not signed by a trusted CA");
457 break;
458
459 case 12:
460 if (Log.on) Log.log(this, "got ServerKeyExchange");
461 serverKeyExchange = rec;
462 break;
463
464 case 13:
465 if (Log.on) Log.log(this, "got Request for Client Certificates");
466 cert_requested = true;
467 break;
468
469 case 14: if (Log.on) Log.log(this, " ServerHelloDone"); return;
470 default: throw new SSLException("unknown handshake of type " + rec[0]);
471 }
472 }
473 }
474
475 public void readServerFinished() throws IOException {
476
477 byte[] rec = readHandshake();
478 if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
479
480 byte[] expectedFinished = concat(new byte[][] {
481 md5(new byte[][] { master_secret, pad2,
482 md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
483 master_secret, pad1 }) }),
484 sha(new byte[][] { master_secret, pad2_sha,
485 sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
486 master_secret, pad1_sha } ) } ) } );
487
488 for(int i=0; i<expectedFinished.length; i++)
489 if (expectedFinished[i] != rec[i + 4])
490 throw new SSLException("server Finished message mismatch!");
491
492 if (Log.on) Log.log(this, "server finished message checked out okay!");
493 }
494
495 }
496
497 class SSLOutputStream extends OutputStream {
498
499
500 DataOutputStream raw;
501
502
503 public long seq_num = 0;
504
505
506 RC4Engine rc4 = null;
507
508 public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
509 public void flush() throws IOException { raw.flush(); }
510 public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
511 public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
512 public void close() throws IOException {
513 write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
514 raw.close();
515 }
516
517
518 public void write(byte[] payload, int off, int len, byte type) throws IOException {
519
520
521 if (len > 1 << 14) {
522 write(payload, off, 1 << 14, type);
523 write(payload, off + 1 << 14, len - 1 << 14, type);
524 return;
525 }
526
527 raw.writeByte(type);
528 raw.writeShort(0x0300);
529
530 if (rc4 == null) {
531 raw.writeShort(len);
532 raw.write(payload, off, len);
533
534 } else {
535 byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
536 byte[] encryptedPayload = new byte[MAC.length + len];
537 rc4.processBytes(payload, off, len, encryptedPayload, 0);
538 rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
539 raw.writeShort(encryptedPayload.length);
540 raw.write(encryptedPayload);
541
542 }
543
544 seq_num++;
545 }
546
547
548 public void writeHandshake(int type, byte[] payload) throws IOException {
549 byte[] real_payload = new byte[payload.length + 4];
550 System.arraycopy(payload, 0, real_payload, 4, payload.length);
551 real_payload[0] = (byte)(type & 0xFF);
552 intToBytes(payload.length, real_payload, 1, 3);
553 handshakes = concat(new byte[][] { handshakes, real_payload });
554 write(real_payload, 0, real_payload.length, (byte)22);
555 }
556
557 public void sendClientHandshakes() throws IOException {
558
559 if (Log.on) Log.log(this, "shaking hands");
560 if (cert_requested) {
561 if (Log.on) Log.log(this, "telling the server we have no certificates");
562 writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
563 }
564
565
566 byte[] pre_master_secret = new byte[48];
567 pre_master_secret[0] = 0x03;
568 pre_master_secret[1] = 0x00;
569 getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
570
571
572 try {
573 byte[] encrypted_pre_master_secret;
574
575 SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
576 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
577 BigInteger modulus = rsa_pks.getModulus();
578 BigInteger exponent = rsa_pks.getPublicExponent();
579
580 if (serverKeyExchange != null) {
581
582 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
583 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
584
585 int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
586 byte[] b_modulus = new byte[modulus_size];
587 System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
588 modulus = new BigInteger(1, b_modulus);
589
590 int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
591 byte[] b_exponent = new byte[exponent_size];
592 System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
593 exponent = new BigInteger(1, b_exponent);
594
595 byte[] server_params = new byte[modulus_size + exponent_size + 4];
596 System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
597
598 byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
599 sha(new byte[][] { client_random, server_random, server_params } ) } );
600
601 byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
602 serverKeyExchange.length - 6 - server_params.length);
603
604 for(int i=0; i<expectedSignature.length; i++)
605 if (expectedSignature[i] != recievedSignature[i])
606 throw new SSLException("ServerKeyExchange message had invalid signature " + i);
607
608 if (Log.on) Log.log(this, "ServerKeyExchange successfully processed");
609 }
610
611 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
612 rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
613
614 encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
615 writeHandshake(16, encrypted_pre_master_secret);
616
617 } catch (Exception e) {
618 SSLException t = new SSLException("exception encrypting premaster secret");
619 t.fillInStackTrace();
620 throw t;
621 }
622
623
624 if (Log.on) Log.log(this, "Handshake complete; sending ChangeCipherSpec");
625 write(new byte[] { 0x01 }, 0, 1, (byte)20);
626 seq_num = 0;
627
628
629 master_secret = concat(new byte[][] {
630 md5(new byte[][] { pre_master_secret,
631 sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
632 md5(new byte[][] { pre_master_secret,
633 sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
634 md5(new byte[][] { pre_master_secret,
635 sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
636 } );
637
638
639 byte[] key_material = new byte[] { };
640 for(int i=0; key_material.length < 72; i++) {
641 byte[] crap = new byte[i + 1];
642 for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
643 key_material = concat(new byte[][] { key_material,
644 md5(new byte[][] { master_secret,
645 sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
646 }
647
648 client_write_key = new byte[export ? 5 : 16];
649 server_write_key = new byte[export ? 5 : 16];
650
651 System.arraycopy(key_material, 0, client_write_MAC_secret, 0, 16);
652 System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
653 System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
654 System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
655
656 if (export) {
657
658 byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
659 byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
660 client_write_key = new byte[16];
661 server_write_key = new byte[16];
662 System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
663 System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
664 }
665
666 rc4 = new RC4Engine();
667 rc4.init(true, new KeyParameter(client_write_key));
668 is.rc4 = new RC4Engine();
669 is.rc4.init(false, new KeyParameter(server_write_key));
670
671
672 writeHandshake(20, concat(new byte[][] {
673 md5(new byte[][] { master_secret, pad2,
674 md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
675 master_secret, pad1 }) }),
676 sha(new byte[][] { master_secret, pad2_sha,
677 sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
678 master_secret, pad1_sha } ) })
679 }));
680 raw.flush();
681 if (Log.on) Log.log(this, "wrote Finished message");
682
683 }
684
685 public void writeClientHello() throws IOException {
686
687 if (Log.on) Log.log(this, "sending ClientHello");
688 int unixtime = (int)(System.currentTimeMillis() / (long)1000);
689
690 byte[] out = new byte[] {
691 0x03, 0x00,
692
693
694 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
695 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
696 0x0, 0x0, 0x0, 0x0,
697
698 0x0,
699 0x0, 0x4, 0x0, 0x4, 0x0, 0x3,
700 0x1, 0x0
701 };
702
703
704 Random rand = new Random(System.currentTimeMillis());
705 rand.nextBytes(client_random);
706 intToBytes(unixtime, client_random, 0, 4);
707 System.arraycopy(client_random, 0, out, 2, client_random.length);
708
709 writeHandshake(1, out);
710 flush();
711 }
712 }
713
714
715
716
717 public static void intToBytes(long val, byte[] b, int offset, int num) {
718 for(int i=0; i<num; i++)
719 b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
720 }
721
722
723 public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
724 MD5Digest md5 = new MD5Digest();
725 byte[] b2 = new byte[16];
726 while(len > 0) {
727 md5.reset();
728 md5.update(randpool, 0, randpool.length);
729 intToBytes(randcnt++, b2, 0, 8);
730 md5.update(b2, 0, 8);
731 md5.doFinal(b2, 0);
732 int n = len < 16 ? len : 16;
733 System.arraycopy(b2, 0, b, offset, n);
734 len -= n;
735 offset += n;
736 }
737 }
738
739 public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
740 byte[] MAC = new byte[16];
741 MD5Digest md5 = new MD5Digest();
742 md5.update(MAC_secret, 0, MAC_secret.length);
743 md5.update(pad1, 0, pad1.length);
744
745 byte[] b = new byte[11];
746 intToBytes(seq_num, b, 0, 8);
747 b[8] = type;
748 intToBytes(len, b, 9, 2);
749 md5.update(b, 0, b.length);
750
751 md5.update(payload, off, len);
752 md5.doFinal(MAC, 0);
753 md5.reset();
754 md5.update(MAC_secret, 0, MAC_secret.length);
755 md5.update(pad2, 0, pad2.length);
756 md5.update(MAC, 0, MAC.length);
757 md5.doFinal(MAC, 0);
758
759 return MAC;
760 }
761
762 public static byte[] concat(byte[][] inputs) {
763 int total = 0;
764 for(int i=0; i<inputs.length; i++) total += inputs[i].length;
765 byte[] ret = new byte[total];
766 int pos = 0;
767 for(int i=0; i<inputs.length; i++) {
768 System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
769 pos += inputs[i].length;
770 }
771 return ret;
772 }
773
774 SHA1Digest master_sha1 = new SHA1Digest();
775 public byte[] sha(byte[][] inputs) {
776 master_sha1.reset();
777 for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
778 byte[] ret = new byte[master_sha1.getDigestSize()];
779 master_sha1.doFinal(ret, 0);
780 return ret;
781 }
782
783 MD5Digest master_md5 = new MD5Digest();
784 public byte[] md5(byte[][] inputs) {
785 master_md5.reset();
786 for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
787 byte[] ret = new byte[master_md5.getDigestSize()];
788 master_md5.doFinal(ret, 0);
789 return ret;
790 }
791
792
793
794 public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
795
796 Digest hash = null;
797
798 String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
799 if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
800 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
801 else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
802 else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
803
804 try {
805
806 byte[] ED = signee.getSignature().getBytes();
807 SubjectPublicKeyInfo pki = signer;
808 RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
809 BigInteger modulus = rsa_pks.getModulus();
810 BigInteger exponent = rsa_pks.getPublicExponent();
811 AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
812 rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
813
814
815 byte[] D = rsa.processBlock(ED, 0, ED.length);
816 BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
817 DERObject derob = beris.readObject();
818 DERSequence dercs = (DERSequence)derob;
819 DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
820 byte[] MD = deros.getOctets();
821
822
823 ByteArrayOutputStream baos = new ByteArrayOutputStream();
824 DEROutputStream dos = new DEROutputStream(baos);
825 dos.writeObject(signee.getTBSCertificate());
826 dos.flush();
827 byte[] b = baos.toByteArray();
828 hash.update(b, 0, b.length);
829 byte[] md_out = new byte[MD.length];
830 hash.doFinal(md_out, 0);
831
832
833 for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
834 return true;
835
836 } catch (Exception e) {
837 return false;
838
839 }
840 }
841
842
843
844
845 static String[] base64_encoded_trusted_CA_public_keys = new String[] {
846
847 "CN=ABA.ECOM Root CA",
848 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
849 "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
850 "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
851 "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
852 "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
853 "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
854
855 "O=ViaCode",
856 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
857 "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
858 "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
859 "IBAw==",
860
861 "CN=Xcert EZ by DST",
862 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
863 "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
864 "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
865 "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
866 "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
867 "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
868
869 "CN=Certiposte Classe A Personne",
870 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
871 "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
872 "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
873 "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
874 "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
875 "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
876
877 "CN=Certiposte Serveur",
878 "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
879 "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
880 "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
881 "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
882 "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
883 "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
884
885 "OU=Certisign - Autoridade Certificadora - AC2",
886 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
887 "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
888 "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
889 "IDAQAB",
890
891 "OU=Certisign - Autoridade Certificadora - AC4",
892 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
893 "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
894 "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
895 "IDAQAB",
896
897 "OU=Certisign Autoridade Certificadora AC1S",
898 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
899 "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
900 "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
901 "IDAQAB",
902
903 "OU=Certisign Autoridade Certificadora AC3S",
904 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
905 "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
906 "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
907 "IDAQAB",
908
909 "O=Certplus, CN=Class 1 Primary CA",
910 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
911 "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
912 "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
913 "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
914 "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
915 "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
916
917 "O=Certplus, CN=Class 2 Primary CA",
918 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
919 "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
920 "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
921 "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
922 "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
923 "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
924
925 "O=Certplus, CN=Class 3 Primary CA",
926 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
927 "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
928 "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
929 "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
930 "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
931 "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
932
933 "CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano",
934 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
935 "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
936 "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
937 "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
938 "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
939 "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
940
941 "O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
942 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
943 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
944 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
945 "IDAQAB",
946
947 "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
948 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
949 "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
950 "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
951 "IDAQAB",
952
953 "C=FR, O=Certplus, CN=Class 3P Primary CA",
954 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
955 "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
956 "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
957 "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
958 "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
959 "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
960
961 "C=FR, O=Certplus, CN=Class 3TS Primary CA",
962 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
963 "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
964 "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
965 "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
966 "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
967 "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
968
969 "C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority",
970 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
971 "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
972 "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
973 "E=",
974
975 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1",
976 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
977 "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
978 "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
979 "IDAQAB",
980
981 "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2",
982 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
983 "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
984 "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
985 "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
986 "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
987 "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
988
989 "C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA",
990 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
991 "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
992 "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
993 "IBAw==",
994
995 "OU=National Retail Federation, CN=DST (NRF) RootCA",
996 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
997 "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
998 "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
999 "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
1000 "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
1001 "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
1002
1003 "OU=United Parcel Service, CN=DST (UPS) RootCA",
1004 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
1005 "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
1006 "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
1007 "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
1008 "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
1009 "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
1010
1011 "CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana",
1012 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
1013 "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
1014 "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
1015 "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
1016 "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
1017 "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
1018
1019 "CN=DST RootCA X1",
1020 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
1021 "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
1022 "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
1023 "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
1024 "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
1025 "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
1026
1027 "OU=DSTCA X2, CN=DST RootCA X2",
1028 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
1029 "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
1030 "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
1031 "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
1032 "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
1033 "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
1034
1035 "C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA",
1036 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
1037 "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
1038 "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
1039 "IBAw==",
1040
1041 "C=US, O=Digital Signature Trust Co., OU=DSTCA E1",
1042 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
1043 "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
1044 "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
1045 "IBAw==",
1046
1047 "C=US, O=Digital Signature Trust Co., OU=DSTCA E2",
1048 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
1049 "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
1050 "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
1051 "IBAw==",
1052
1053 "CN=Entrust.net Certification Authority (2048)",
1054 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
1055 "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
1056 "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
1057 "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
1058 "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
1059 "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
1060
1061 "CN=Entrust.net Client Certification Authority",
1062 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
1063 "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
1064 "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
1065 "IBAw==",
1066
1067 "CN=Entrust.net Secure Server Certification Authority",
1068 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
1069 "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
1070 "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
1071 "IBAw==",
1072
1073 "C=US, O=Equifax, OU=Equifax Secure Certificate Authority",
1074 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
1075 "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
1076 "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
1077 "IDAQAB",
1078
1079 "C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1",
1080 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
1081 "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
1082 "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
1083 "IDAQAB",
1084
1085 "CN=Baltimore EZ by DST",
1086 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
1087 "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
1088 "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
1089 "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
1090 "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
1091 "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
1092
1093 "C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2",
1094 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
1095 "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
1096 "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
1097 "IDAQAB",
1098
1099 "C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1",
1100 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
1101 "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
1102 "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
1103 "IDAQAB",
1104
1105 "O=EUnet International, CN=EUnet International Root CA",
1106 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
1107 "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
1108 "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
1109 "IDAQAB",
1110
1111 "CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org",
1112 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
1113 "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
1114 "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
1115 "IDAQAB",
1116
1117 "CN=FESTE, Verified Certs",
1118 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
1119 "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
1120 "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
1121 "IDAQAB",
1122
1123 "CN=First Data Digital Certificates Inc. Certification Authority",
1124 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
1125 "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
1126 "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
1127 "IBAw==",
1128
1129 "C=ES, O=FNMT, OU=FNMT Clase 2 CA",
1130 "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
1131 "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
1132 "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
1133 "IBAw==",
1134
1135 "CN=Belgacom E-Trust Primary CA",
1136 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
1137 "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
1138 "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
1139 "IDAQAB",
1140
1141 "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA",
1142 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
1143 "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
1144 "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
1145 "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
1146 "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
1147 "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
1148
1149 "CN=GTE CyberTrust Global Root",
1150 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
1151 "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
1152 "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
1153 "IDAQAB",
1154
1155 "CN=GTE CyberTrust Root",
1156 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
1157 "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
1158 "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
1159 "IDAQAB",
1160
1161 "C=US, O=GTE Corporation, CN=GTE CyberTrust Root",
1162 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
1163 "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
1164 "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
1165 "IDAQAB",
1166
1167 "OU=ValiCert Class 3 Policy Validation Authority",
1168 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
1169 "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
1170 "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
1171 "IDAQAB",
1172
1173 "OU=ValiCert Class 1 Policy Validation Authority",
1174 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
1175 "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
1176 "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
1177 "IDAQAB",
1178
1179 "OU=ValiCert Class 2 Policy Validation Authority",
1180 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
1181 "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
1182 "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
1183 "IDAQAB",
1184
1185 "C=hk, O=C&W HKT SecureNet CA Class A",
1186 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
1187 "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
1188 "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
1189 "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
1190 "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
1191 "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
1192
1193 "CN=IPS SERVIDORES",
1194 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
1195 "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
1196 "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
1197 "IDAQAB",
1198
1199 "CN=Microsoft Root Authority",
1200 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
1201 "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
1202 "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
1203 "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
1204 "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
1205 "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
1206
1207 "CN=Microsoft Root Certificate Authority",
1208 "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
1209 "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
1210 "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
1211 "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
1212 "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
1213 "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
1214 "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
1215 "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
1216 "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
1217 "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
1218 "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
1219
1220 "CN=NetLock Expressz (Class C) Tanusitvanykiado",
1221 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
1222 "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
1223 "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
1224 "IDAQAB",
1225
1226 "CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado",
1227 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
1228 "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
1229 "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
1230 "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
1231 "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
1232 "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
1233
1234 "OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado",
1235 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
1236 "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
1237 "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
1238 "IDAQAB",
1239
1240 "CN=Post.Trust Root CA",
1241 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
1242 "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
1243 "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
1244 "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
1245 "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
1246 "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
1247
1248 "CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl",
1249 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
1250 "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
1251 "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
1252 "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
1253 "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
1254 "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
1255
1256 "CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi",
1257 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
1258 "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
1259 "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
1260 "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
1261 "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
1262 "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
1263
1264 "CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi",
1265 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
1266 "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
1267 "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
1268 "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
1269 "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
1270 "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
1271
1272 "C=hk, O=C&W HKT SecureNet CA Class B",
1273 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
1274 "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
1275 "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
1276 "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
1277 "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
1278 "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
1279
1280 "C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
1281 "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
1282 "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
1283 "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
1284 "E=",
1285
1286 "C=au, O=SecureNet CA Class A",
1287 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
1288 "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
1289 "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
1290 "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
1291 "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
1292 "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
1293
1294 "C=au, O=SecureNet CA Class B",
1295 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
1296 "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
1297 "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
1298 "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
1299 "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
1300 "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
1301
1302 "C=au, O=SecureNet CA Root",
1303 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
1304 "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
1305 "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
1306 "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
1307 "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
1308 "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
1309
1310 "C=au, O=SecureNet CA SGC Root",
1311 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
1312 "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
1313 "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
1314 "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
1315 "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
1316 "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
1317
1318 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1319 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1320 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1321 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1322 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1323 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1324 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1325
1326 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
1327 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
1328 "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
1329 "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
1330 "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
1331 "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
1332 "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
1333
1334 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1335 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1336 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1337 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1338 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1339 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1340 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1341
1342 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
1343 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
1344 "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
1345 "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
1346 "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
1347 "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
1348 "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
1349
1350 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1351 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1352 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1353 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1354 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1355 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1356 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1357
1358 "C=hk, O=C&W HKT SecureNet CA Root",
1359 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
1360 "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
1361 "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
1362 "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
1363 "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
1364 "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
1365
1366 "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
1367 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
1368 "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
1369 "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
1370 "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
1371 "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
1372 "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
1373
1374 "CN=SERVICIOS DE CERTIFICACION - A.N.C.",
1375 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
1376 "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
1377 "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
1378 "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
1379 "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
1380 "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
1381
1382 "CN=SIA Secure Client CA",
1383 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
1384 "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
1385 "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
1386 "IDAQAB",
1387
1388 "C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA",
1389 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
1390 "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
1391 "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
1392 "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
1393 "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
1394 "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
1395
1396 "OU=Public CA Services",
1397 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
1398 "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
1399 "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
1400 "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
1401 "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
1402 "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
1403
1404 "OU=TC TrustCenter Class 1 CA",
1405 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
1406 "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
1407 "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
1408 "IDAQAB",
1409
1410 "OU=TC TrustCenter Class 2 CA",
1411 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
1412 "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
1413 "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
1414 "IDAQAB",
1415
1416 "OU=TC TrustCenter Class 3 CA",
1417 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
1418 "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
1419 "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
1420 "IDAQAB",
1421
1422 "OU=TC TrustCenter Class 4 CA",
1423 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
1424 "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
1425 "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
1426 "IDAQAB",
1427
1428 "CN=Thawte Premium Server CA",
1429 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
1430 "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
1431 "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
1432 "IDAQAB",
1433
1434 "C=hk, O=C&W HKT SecureNet CA SGC Root",
1435 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
1436 "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
1437 "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
1438 "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
1439 "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
1440 "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
1441
1442 "CN=Thawte Server CA",
1443 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
1444 "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
1445 "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
1446 "IDAQAB",
1447
1448 "CN=UTN - DATACorp SGC",
1449 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
1450 "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
1451 "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
1452 "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
1453 "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
1454 "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
1455
1456 "CN=UTN-USERFirst-Hardware",
1457 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
1458 "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
1459 "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
1460 "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
1461 "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
1462 "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
1463
1464 "CN=UTN-USERFirst-Network Applications",
1465 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
1466 "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
1467 "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
1468 "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
1469 "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
1470 "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
1471
1472 "CN=VeriSign Class 3 Public Primary Certification Authority - G3",
1473 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
1474 "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
1475 "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
1476 "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
1477 "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
1478 "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
1479
1480 "CN=VeriSign Class 4 Public Primary Certification Authority - G3",
1481 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
1482 "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
1483 "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
1484 "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
1485 "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
1486 "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
1487
1488 "OU=VeriSign Trust Network",
1489 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1490 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1491 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1492 "IDAQAB",
1493
1494 "OU=VeriSign Trust Network",
1495 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
1496 "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
1497 "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
1498 "IDAQAB",
1499
1500 "OU=VeriSign Trust Network",
1501 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1502 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1503 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1504 "IDAQAB",
1505
1506 "OU=VeriSign Trust Network",
1507 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
1508 "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
1509 "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
1510 "IDAQAB"
1511 };
1512
1513 public static boolean alwaysFalse = false;
1514
1515 static class entropySpinner extends Thread {
1516 volatile boolean stop = false;
1517 byte counter = 0;
1518 entropySpinner() { start(); }
1519 public void run() {
1520 while (true) {
1521 counter++;
1522
1523
1524 if (alwaysFalse) stop = true;
1525
1526 if (stop) return;
1527 }
1528 }
1529 }
1530
1531 private static volatile boolean initializationFinished = false;
1532 static {
1533 entropySpinner[] spinners = new entropySpinner[10];
1534 for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
1535
1536 for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
1537 for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
1538 for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
1539 for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
1540
1541 try {
1542 if (Log.on) Log.log(TinySSL.class, "reading in trusted root public keys...");
1543 trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length / 2];
1544 trusted_CA_public_key_identifiers = new String[base64_encoded_trusted_CA_public_keys.length / 2];
1545 for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i+=2) {
1546 trusted_CA_public_key_identifiers[i/2] = base64_encoded_trusted_CA_public_keys[i];
1547 byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i+1]);
1548 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b));
1549 trusted_CA_public_keys[i/2] = new SubjectPublicKeyInfo((DERSequence)dIn.readObject());
1550 }
1551
1552 } catch (Exception e) {
1553 if (Log.on) Log.log(TinySSL.class, e);
1554 }
1555
1556 if (Log.on) Log.log(TinySSL.class, "generating entropy...");
1557 randpool = new byte[10];
1558 try { Thread.sleep(100); } catch (Exception e) { }
1559 for(int i=0; i<spinners.length; i++) {
1560 spinners[i].stop = true;
1561 randpool[i] = spinners[i].counter;
1562 }
1563
1564 MD5Digest md5 = new MD5Digest();
1565 md5.update(randpool, 0, randpool.length);
1566 intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
1567 intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1568 intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
1569 intToBytes(System.identityHashCode(TinySSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
1570 Properties p = System.getProperties();
1571 for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
1572 String s = (String)e.nextElement();
1573 byte[] b = s.getBytes();
1574 md5.update(b, 0, b.length);
1575 b = p.getProperty(s).getBytes();
1576 md5.update(b, 0, b.length);
1577 }
1578 randpool = new byte[md5.getDigestSize()];
1579 md5.doFinal(randpool, 0);
1580
1581 if (Log.on) Log.log(TinySSL.class, "TinySSL is initialized.");
1582 initializationFinished = true;
1583 TinySSL.class.notifyAll();
1584 }
1585
1586
1587
1591 private static class PKCS1 implements AsymmetricBlockCipher {
1592 private static int HEADER_LENGTH = 10;
1593 private AsymmetricBlockCipher engine;
1594 private boolean forEncryption;
1595 private boolean forPrivateKey;
1596
1597 public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }
1598 public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
1599
1600 public void init(boolean forEncryption, CipherParameters param) {
1601 engine.init(forEncryption, (AsymmetricKeyParameter)param);
1602 this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
1603 this.forEncryption = forEncryption;
1604 }
1605
1606 public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
1607 public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
1608
1609 public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1610 return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
1611 }
1612
1613 private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1614 byte[] block = new byte[engine.getInputBlockSize()];
1615 if (forPrivateKey) {
1616 block[0] = 0x01;
1617 for (int i = 1; i != block.length - inLen - 1; i++)
1618 block[i] = (byte)0xFF;
1619 } else {
1620 getRandomBytes(block, 0, block.length);
1621 block[0] = 0x02;
1622
1623
1624
1625 for (int i = 1; i != block.length - inLen - 1; i++)
1626 while (block[i] == 0)
1627 getRandomBytes(block, i, 1);
1628 }
1629
1630 block[block.length - inLen - 1] = 0x00;
1631 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
1632 return engine.processBlock(block, 0, block.length);
1633 }
1634
1635 private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
1636 byte[] block = engine.processBlock(in, inOff, inLen);
1637 if (block.length < getOutputBlockSize())
1638 throw new InvalidCipherTextException("block truncated");
1639 if (block[0] != 1 && block[0] != 2)
1640 throw new InvalidCipherTextException("unknown block type");
1641
1642
1643 int start;
1644 for (start = 1; start != block.length; start++)
1645 if (block[start] == 0)
1646 break;
1647 start++;
1648
1649 if (start >= block.length || start < HEADER_LENGTH)
1650 throw new InvalidCipherTextException("no data in block");
1651
1652 byte[] result = new byte[block.length - start];
1653 System.arraycopy(block, start, result, 0, result.length);
1654 return result;
1655 }
1656 }
1657
1658 }
1659
1660