1cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom/*
2cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * Copyright (C) 2010 The Android Open Source Project
3cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom *
4cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * you may not use this file except in compliance with the License.
6cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * You may obtain a copy of the License at
7cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom *
8cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom *
10cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * Unless required by applicable law or agreed to in writing, software
11cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * See the License for the specific language governing permissions and
14cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom * limitations under the License.
15cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom */
16cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
17cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrompackage libcore.java.security.cert;
18cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
1934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport com.android.org.bouncycastle.asn1.x509.BasicConstraints;
2034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport com.android.org.bouncycastle.asn1.x509.X509Extensions;
2134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
2234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport com.android.org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
2334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport com.android.org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
2434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
25cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstromimport java.io.ByteArrayInputStream;
2634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.io.ByteArrayOutputStream;
27bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Rootimport java.io.IOException;
28bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Rootimport java.io.InputStream;
2934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.io.ObjectInputStream;
3034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.io.ObjectOutputStream;
3134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.io.OptionalDataException;
3234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.io.StreamCorruptedException;
3334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.math.BigInteger;
3434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.KeyPair;
3534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.KeyPairGenerator;
3634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.PrivateKey;
37bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Rootimport java.security.Provider;
38bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Rootimport java.security.Security;
3934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.cert.CertPath;
40cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstromimport java.security.cert.Certificate;
4134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.cert.CertificateEncodingException;
42cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstromimport java.security.cert.CertificateException;
43cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstromimport java.security.cert.CertificateFactory;
4434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.security.cert.X509Certificate;
4534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.ArrayList;
4634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.Arrays;
4734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.Date;
4834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.GregorianCalendar;
4934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.Iterator;
5034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.List;
5134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport java.util.TimeZone;
5234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
5334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport javax.security.auth.x500.X500Principal;
5434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
55cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstromimport junit.framework.TestCase;
5634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Rootimport libcore.java.security.StandardNames;
57cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
58cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrompublic class CertificateFactoryTest extends TestCase {
59cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
60cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    private static final String VALID_CERTIFICATE_PEM =
61cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            "-----BEGIN CERTIFICATE-----\n"
62cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM\n"
63cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg\n"
64cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x\n"
65cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh\n"
66cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw\n"
67cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC\n"
68cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN\n"
69cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L\n"
70cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM\n"
71cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl\n"
72cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF\n"
73cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw\n"
74cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0\n"
75cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF\n"
76cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5\n"
77cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6\n"
78cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==\n"
79cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "-----END CERTIFICATE-----\n";
80cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
81e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private static final String VALID_CERTIFICATE_PEM_CRLF =
82e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            "-----BEGIN CERTIFICATE-----\r\n"
83e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM\r\n"
84e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg\r\n"
85e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x\r\n"
86e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh\r\n"
87e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw\r\n"
88e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC\r\n"
89e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN\r\n"
90e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L\r\n"
91e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM\r\n"
92e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl\r\n"
93e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF\r\n"
94e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw\r\n"
95e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0\r\n"
96e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF\r\n"
97e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5\r\n"
98e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6\r\n"
99e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==\r\n"
100e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "-----END CERTIFICATE-----\r\n";
101e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
102e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private static final byte[] VALID_CERTIFICATE_PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"
103e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            .getBytes();
104e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
105e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private static final byte[] VALID_CERTIFICATE_PEM_DATA =
106e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root             ("MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM"
107e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg"
108e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x"
109e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh"
110e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw"
111e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC"
112e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN"
113e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L"
114e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM"
115e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl"
116e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF"
117e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw"
118e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0"
119e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF"
120e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5"
121e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6"
122e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            + "z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==").getBytes();
123e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
124e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private static final byte[] VALID_CERTIFICATE_PEM_FOOTER = "\n-----END CERTIFICATE-----\n"
125e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            .getBytes();
126e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
127cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    private static final String INVALID_CERTIFICATE_PEM =
128cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            "-----BEGIN CERTIFICATE-----\n"
129cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
130cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
131cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
132cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
133cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
134cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
135cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
136cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
137cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
138cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
139cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
140cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
141cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
142cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
143cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
144cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
145cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
146cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
147cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
148cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
149cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
150cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
151cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
152cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
153cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
154cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
155cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
156cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
157cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
158cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
159cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
160cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
161cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
162cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "AAAAAAAA\n"
163cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            + "-----END CERTIFICATE-----";
164cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
165cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    public void test_generateCertificate() throws Exception {
166bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        Provider[] providers = Security.getProviders("CertificateFactory.X509");
167bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        for (Provider p : providers) {
168bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            CertificateFactory cf = CertificateFactory.getInstance("X509", p);
169bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            try {
170bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root                test_generateCertificate(cf);
171fd30c751591675c253613373bcc133ca2c53d74fKenny Root                test_generateCertificate_InputStream_Offset_Correct(cf);
172fd30c751591675c253613373bcc133ca2c53d74fKenny Root                test_generateCertificate_InputStream_Empty(cf);
173e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                test_generateCertificate_InputStream_InvalidStart_Failure(cf);
174e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                test_generateCertificate_AnyLineLength_Success(cf);
175e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            } catch (Throwable e) {
176bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root                throw new Exception("Problem testing " + p.getName(), e);
177bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            }
178bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
179cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    }
180bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
181cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    private void test_generateCertificate(CertificateFactory cf) throws Exception {
182e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        {
183e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            byte[] valid = VALID_CERTIFICATE_PEM.getBytes();
184e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            Certificate c = cf.generateCertificate(new ByteArrayInputStream(valid));
185e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            assertNotNull(c);
186e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        }
187e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
188e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        {
189e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            byte[] valid = VALID_CERTIFICATE_PEM_CRLF.getBytes();
190e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            Certificate c = cf.generateCertificate(new ByteArrayInputStream(valid));
191e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            assertNotNull(c);
192e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        }
193cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
194cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom        try {
195cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            byte[] invalid = INVALID_CERTIFICATE_PEM.getBytes();
196cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            cf.generateCertificate(new ByteArrayInputStream(invalid));
197cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom            fail();
198cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom        } catch (CertificateException expected) {
199cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom        }
200cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom    }
201cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom
202e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    /*
203e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root     * Checks all possible line lengths for PEM input data.
204e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root     */
205e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private void test_generateCertificate_AnyLineLength_Success(CertificateFactory cf)
206e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            throws Exception {
207e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        // RI barfs on this
208e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        if (StandardNames.IS_RI) {
209e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            return;
210e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        }
211e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
212e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        int lineLength = 1;
213e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        int maxLineLength = VALID_CERTIFICATE_PEM_DATA.length;
214e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
215e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        ByteArrayOutputStream baos = new ByteArrayOutputStream();
216e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        baos.write(VALID_CERTIFICATE_PEM_HEADER);
217e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        int offset = 0;
218e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        while (lineLength < (maxLineLength - 4)) {
219e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            int end = offset + lineLength;
220e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            if (end > VALID_CERTIFICATE_PEM_DATA.length) {
221e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                end = VALID_CERTIFICATE_PEM_DATA.length;
222e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            }
223e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            baos.write(Arrays.copyOfRange(VALID_CERTIFICATE_PEM_DATA, offset, end));
224e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            baos.write('\n');
225e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            offset += lineLength;
226e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            if (offset >= maxLineLength) {
227e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                baos.write(VALID_CERTIFICATE_PEM_FOOTER);
228e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                try {
229e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                    Certificate c =
230e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                            cf.generateCertificate(new ByteArrayInputStream(baos.toByteArray()));
231e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                    assertNotNull(c);
232e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                } catch (Exception e) {
233e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                    throw new Exception("Fail at line length " + lineLength, e);
234e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                }
235e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                baos.reset();
236e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                baos.write(VALID_CERTIFICATE_PEM_HEADER);
237e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                offset = 0;
238e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            } else {
239e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                lineLength++;
240e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            }
241e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        }
242e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
243e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    }
244e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
245fd30c751591675c253613373bcc133ca2c53d74fKenny Root    private void test_generateCertificate_InputStream_Empty(CertificateFactory cf) throws Exception {
246fd30c751591675c253613373bcc133ca2c53d74fKenny Root        try {
247fd30c751591675c253613373bcc133ca2c53d74fKenny Root            Certificate c = cf.generateCertificate(new ByteArrayInputStream(new byte[0]));
248fd30c751591675c253613373bcc133ca2c53d74fKenny Root            if (!"BC".equals(cf.getProvider().getName())) {
249fd30c751591675c253613373bcc133ca2c53d74fKenny Root                fail("should throw CertificateException: " + cf.getProvider().getName());
250fd30c751591675c253613373bcc133ca2c53d74fKenny Root            }
251fd30c751591675c253613373bcc133ca2c53d74fKenny Root            assertNull(c);
252fd30c751591675c253613373bcc133ca2c53d74fKenny Root        } catch (CertificateException e) {
253fd30c751591675c253613373bcc133ca2c53d74fKenny Root            if ("BC".equals(cf.getProvider().getName())) {
254fd30c751591675c253613373bcc133ca2c53d74fKenny Root                fail("should return null: " + cf.getProvider().getName());
255fd30c751591675c253613373bcc133ca2c53d74fKenny Root            }
256fd30c751591675c253613373bcc133ca2c53d74fKenny Root        }
257fd30c751591675c253613373bcc133ca2c53d74fKenny Root    }
258fd30c751591675c253613373bcc133ca2c53d74fKenny Root
259e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    private void test_generateCertificate_InputStream_InvalidStart_Failure(CertificateFactory cf)
260e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            throws Exception {
261e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        try {
262e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            Certificate c = cf.generateCertificate(new ByteArrayInputStream(
263e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                    "-----BEGIN CERTIFICATE-----".getBytes()));
264e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            if (!"BC".equals(cf.getProvider().getName())) {
265e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                fail("should throw CertificateException: " + cf.getProvider().getName());
266e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            }
267e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            assertNull(c);
268e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        } catch (CertificateException expected) {
269e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            if ("BC".equals(cf.getProvider().getName())) {
270e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root                fail("should return null: " + cf.getProvider().getName());
271e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root            }
272e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root        }
273e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root    }
274e21b3caf3fb4e3e3d9244a000669a547621c16bdKenny Root
275fd30c751591675c253613373bcc133ca2c53d74fKenny Root    private void test_generateCertificate_InputStream_Offset_Correct(CertificateFactory cf)
276bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            throws Exception {
277bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        byte[] valid = VALID_CERTIFICATE_PEM.getBytes();
278bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
279bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        byte[] doubleCertificateData = new byte[valid.length * 2];
280bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        System.arraycopy(valid, 0, doubleCertificateData, 0, valid.length);
281bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        System.arraycopy(valid, 0, doubleCertificateData, valid.length, valid.length);
282bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        MeasuredInputStream certStream = new MeasuredInputStream(new ByteArrayInputStream(
283bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root                doubleCertificateData));
284bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        Certificate certificate = cf.generateCertificate(certStream);
285bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        assertNotNull(certificate);
286bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        assertEquals(valid.length, certStream.getCount());
287bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root    }
288bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
289bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root    /**
290bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root     * Proxy that counts the number of bytes read from an InputStream.
291bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root     */
292bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root    private static class MeasuredInputStream extends InputStream {
293bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        private long mCount = 0;
294bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
295bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        private long mMarked = 0;
296bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
297bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        private InputStream mStream;
298bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
299bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public MeasuredInputStream(InputStream is) {
300bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mStream = is;
301bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
302bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
303bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public long getCount() {
304bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return mCount;
305bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
306bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
307bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
308bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public int read() throws IOException {
309bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            int nextByte = mStream.read();
310bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mCount++;
311bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return nextByte;
312bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
313bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
314bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
315bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public int read(byte[] buffer) throws IOException {
316bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            int count = mStream.read(buffer);
317bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mCount += count;
318bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return count;
319bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
320bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
321bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
322bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public int read(byte[] buffer, int offset, int length) throws IOException {
323bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            int count = mStream.read(buffer, offset, length);
324bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mCount += count;
325bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return count;
326bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
327bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
328bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
329bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public long skip(long byteCount) throws IOException {
330bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            long count = mStream.skip(byteCount);
331bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mCount += count;
332bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return count;
333bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
334bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
335bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
336bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public int available() throws IOException {
337bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return mStream.available();
338bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
339bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
340bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
341bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public void close() throws IOException {
342bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mStream.close();
343bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
344bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
345bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
346bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public void mark(int readlimit) {
347bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mMarked = mCount;
348bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mStream.mark(readlimit);
349bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
350bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
351bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
352bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public boolean markSupported() {
353bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            return mStream.markSupported();
354bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
355bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root
356bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        @Override
357bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        public synchronized void reset() throws IOException {
358bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mCount = mMarked;
359bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root            mStream.reset();
360bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root        }
361bcd731fc88df3806f963b2c6e19b83de5aba8d35Kenny Root    }
36234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
36334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    /* CertPath tests */
36434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    public void testGenerateCertPath() throws Exception {
36534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyHolder ca = generateCertificate(true, null);
36634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyHolder cert1 = generateCertificate(true, ca);
36734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyHolder cert2 = generateCertificate(false, cert1);
36834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyHolder cert3 = generateCertificate(false, cert2);
36934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
37034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        List<X509Certificate> certs = new ArrayList<X509Certificate>();
37134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certs.add(cert3.certificate);
37234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certs.add(cert2.certificate);
37334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certs.add(cert1.certificate);
37434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
37534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        List<X509Certificate> duplicatedCerts = new ArrayList<X509Certificate>(certs);
37634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        duplicatedCerts.add(cert2.certificate);
37734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
37834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        Provider[] providers = Security.getProviders("CertificateFactory.X509");
37934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        for (Provider p : providers) {
38034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            final CertificateFactory cf = CertificateFactory.getInstance("X.509", p);
38134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
38234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            // Duplicate certificates can cause an exception.
38334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            {
38434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                final CertPath duplicatedPath = cf.generateCertPath(duplicatedCerts);
38534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                try {
38634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    duplicatedPath.getEncoded();
38734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    if (StandardNames.IS_RI) {
38834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                        fail("duplicate certificates should cause failure: " + p.getName());
38934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    }
39034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                } catch (CertificateEncodingException expected) {
39134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    if (!StandardNames.IS_RI) {
39234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                        fail("duplicate certificates should pass: " + p.getName());
39334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    }
39434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                }
39534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            }
39634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
39734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            testCertPathEncoding(cf, certs, null);
39834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
39934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            /* Make sure all encoding entries are the same. */
40034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            final Iterator<String> it1 = cf.getCertPathEncodings();
40134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            final Iterator<String> it2 = cf.generateCertPath(certs).getEncodings();
40234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            for (;;) {
40334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                assertEquals(p.getName(), it1.hasNext(), it2.hasNext());
40434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                if (!it1.hasNext()) {
40534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    break;
40634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                }
40734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
40834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                String encoding = it1.next();
40934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                assertEquals(p.getName(), encoding, it2.next());
41034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
41134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                try {
41234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    it1.remove();
41334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    fail("Should not be able to remove from iterator");
41434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                } catch (UnsupportedOperationException expected) {
41534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                }
41634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
41734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                try {
41834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    it2.remove();
41934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    fail("Should not be able to remove from iterator");
42034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                } catch (UnsupportedOperationException expected) {
42134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                }
42234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
42334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                /* Now test using this encoding. */
42434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                testCertPathEncoding(cf, certs, encoding);
42534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            }
42634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
42734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    }
42834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
42934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    private void testCertPathEncoding(CertificateFactory cf, List<X509Certificate> expectedCerts,
43034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            String encoding) throws Exception {
43134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final String providerName = cf.getProvider().getName() + "[" + encoding + "]";
43234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
43334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final CertPath pathFromList = cf.generateCertPath(expectedCerts);
43434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
43534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        // Create a copy we can modify and discard.
43634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final byte[] encodedCopy;
43734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (encoding == null) {
43834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            encodedCopy = pathFromList.getEncoded();
43934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertNotNull(providerName, encodedCopy);
44034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
44134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            // check idempotence
44234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertEquals(providerName, Arrays.toString(pathFromList.getEncoded()),
44334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    Arrays.toString(encodedCopy));
44434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
44534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            encodedCopy = pathFromList.getEncoded(encoding);
44634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertNotNull(providerName, encodedCopy);
44734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
44834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            // check idempotence
44934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertEquals(providerName, Arrays.toString(pathFromList.getEncoded(encoding)),
45034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    Arrays.toString(encodedCopy));
45134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
45234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
45334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        // Try to modify byte array.
45434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        encodedCopy[0] ^= (byte) 0xFF;
45534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
45634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        // Get a real copy we will use if the test proceeds.
45734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final byte[] encoded;
45834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (encoding == null) {
45934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            encoded = pathFromList.getEncoded();
46034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertNotNull(providerName, encodedCopy);
46134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
46234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            // check idempotence
46334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertEquals(providerName, Arrays.toString(pathFromList.getEncoded()),
46434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    Arrays.toString(encoded));
46534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
46634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            encoded = pathFromList.getEncoded(encoding);
46734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertNotNull(providerName, encodedCopy);
46834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
46934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            // check idempotence
47034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertEquals(providerName, Arrays.toString(pathFromList.getEncoded(encoding)),
47134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    Arrays.toString(encoded));
47234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
47334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        assertFalse(providerName, Arrays.toString(encoded).equals(Arrays.toString(encodedCopy)));
47434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
47534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        encodedCopy[0] ^= (byte) 0xFF;
47634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        assertEquals(providerName, Arrays.toString(encoded), Arrays.toString(encodedCopy));
47734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
47834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final CertPath actualPath;
47934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (encoding == null) {
48034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            actualPath = cf.generateCertPath(new ByteArrayInputStream(encoded));
48134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
48234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            actualPath = cf.generateCertPath(new ByteArrayInputStream(encoded), encoding);
48334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
48434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
48534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        // PKCS7 certificate bags are not guaranteed to be in order.
48634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        final List<? extends Certificate> actualCerts;
48734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (!"PKCS7".equals(encoding)) {
48834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            actualCerts = actualPath.getCertificates();
48934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            assertEquals(providerName, expectedCerts, actualCerts);
49034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
49134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            actualCerts = pathFromList.getCertificates();
49234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
49334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
49434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        try {
49534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            actualCerts.remove(0);
49634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            fail("List of certificate should be immutable");
49734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } catch (UnsupportedOperationException expected) {
49834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
49934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
50034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        ByteArrayOutputStream baos = new ByteArrayOutputStream();
50134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        ObjectOutputStream oos = new ObjectOutputStream(baos);
50234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        oos.writeObject(actualPath);
50334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        oos.close();
50434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
50534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        byte[] serialized = baos.toByteArray();
50634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
50734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        ObjectInputStream ois = new ObjectInputStream(bais);
50834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        Object output = ois.readObject();
50934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        assertTrue(providerName, output instanceof CertPath);
51034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
51134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        assertEquals(providerName, actualPath, (CertPath) output);
51234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    }
51334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
51434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    public static class KeyHolder {
51534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        public X509Certificate certificate;
51634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
51734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        public PrivateKey privateKey;
51834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    }
51934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
52034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    @SuppressWarnings("deprecation")
52134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    private static KeyHolder generateCertificate(boolean isCa, KeyHolder issuer) throws Exception {
52234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        Date startDate = new Date();
52334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
52434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        GregorianCalendar cal = new GregorianCalendar();
52534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        cal.setTimeZone(TimeZone.getTimeZone("UTC"));
52634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        cal.set(2100, 0, 1, 0, 0, 0); // Jan 1, 2100 UTC
52734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        Date expiryDate = cal.getTime();
52834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
52934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
53034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyPair keyPair = kpg.generateKeyPair();
53134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
53234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        BigInteger serial;
53334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        X500Principal issuerPrincipal;
53434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        X500Principal subjectPrincipal;
53534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        PrivateKey caKey;
53634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (issuer != null) {
53734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            serial = issuer.certificate.getSerialNumber().add(BigInteger.ONE);
53834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            subjectPrincipal = new X500Principal("CN=Test Certificate Serial #" + serial.toString());
53934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            issuerPrincipal = issuer.certificate.getSubjectX500Principal();
54034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            caKey = issuer.privateKey;
54134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
54234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            serial = BigInteger.ONE;
54334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            subjectPrincipal = new X500Principal("CN=Test CA, O=Tests, C=US");
54434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            issuerPrincipal = subjectPrincipal;
54534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            caKey = keyPair.getPrivate();
54634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
54734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
54834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        BasicConstraints basicConstraints;
54934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (isCa) {
55034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            basicConstraints = new BasicConstraints(10 - serial.intValue());
55134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
55234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            basicConstraints = new BasicConstraints(false);
55334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
55434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
55534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
55634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
55734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setSerialNumber(serial);
55834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setIssuerDN(issuerPrincipal);
55934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setNotBefore(startDate);
56034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setNotAfter(expiryDate);
56134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setSubjectDN(subjectPrincipal);
56234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setPublicKey(keyPair.getPublic());
56334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.setSignatureAlgorithm("SHA1withRSA");
56434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
56534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        if (issuer != null) {
56634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
56734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    new AuthorityKeyIdentifierStructure(issuer.certificate));
56834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        } else {
56934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root            certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
57034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                    new AuthorityKeyIdentifierStructure(keyPair.getPublic()));
57134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        }
57234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
57334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
57434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root                new SubjectKeyIdentifierStructure(keyPair.getPublic()));
57534acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        certGen.addExtension(X509Extensions.BasicConstraints, true, basicConstraints);
57634acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
57734acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        X509Certificate cert = certGen.generate(caKey);
57834acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
57934acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        KeyHolder holder = new KeyHolder();
58034acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        holder.certificate = cert;
58134acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        holder.privateKey = keyPair.getPrivate();
58234acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root
58334acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root        return holder;
58434acecb989e8cecfe10027d3a2c6e6b8a54d970fKenny Root    }
585cdeb809350d8c1a14a96924bf01febfa82a8b5b6Brian Carlstrom}
586