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