1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19 * @author Alexander Y. Kleymenov
20 */
21
22package org.apache.harmony.security.tests.java.security.cert;
23
24import java.io.ByteArrayInputStream;
25import java.security.KeyFactory;
26import java.security.NoSuchAlgorithmException;
27import java.security.PublicKey;
28import java.security.cert.CertPath;
29import java.security.cert.CertificateFactory;
30import java.security.cert.X509CRL;
31import java.security.cert.X509Certificate;
32import java.security.spec.X509EncodedKeySpec;
33import java.util.Collection;
34import java.util.Iterator;
35import java.util.List;
36import org.apache.harmony.luni.util.Base64;
37
38import junit.framework.TestCase;
39
40/**
41 * X.509 CertificateFactory provider implementation test.<br>
42 * See RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt) for
43 * more information on X.509, and
44 * http://www.ietf.org/rfc/rfc2315.txt
45 * for more information on PKCS #7.
46 * The testing data was generated by use of classes from
47 * org.apache.harmony.security.x509 package.
48 */
49public class CertificateFactory_ImplTest extends TestCase {
50
51    /**
52     * Base64 encoded PKCS7 SignedObject containing two X.509
53     * Certificates and CRLs.
54     */
55    private static String pkcs7so =
56            "MIIHDwYJKoZIhvcNAQcCoIIHADCCBvwCAQExADALBgkqhkiG9w0BBwGg"
57                    + "ggUuMIICkzCCAlOgAwIBAgICAiswCQYHKoZIzjgEAzAdMRswGQYDVQQK"
58                    + "ExJDZXJ0aWZpY2F0ZSBJc3N1ZXIwIxcNMDYwOTA1MDk1MzA2WhgSMjMz"
59                    + "NjEwMTMwMjUxMjcuODFaMB0xGzAZBgNVBAoTEkNlcnRpZmljYXRlIElz"
60                    + "c3VlcjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu"
61                    + "7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeB"
62                    + "O4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD"
63                    + "9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM"
64                    + "spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX"
65                    + "TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqL"
66                    + "VHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4Vrl"
67                    + "nwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDyCA7AK6Kep2soxt8tIsWW"
68                    + "kafbYdueAkeBNnm46H0OteFa80HMuJjKJ0LjlPrdjFMARKyW/GATtQhg"
69                    + "hY/MrINAHmKcX5QjL1DkuJKDNggLHqj5D6efsWmLKwLvmviWLzWtjh7Y"
70                    + "GBZeLt0ezu2q49aKcOzkkDsCSsMz09u9284L6qMeMBwwGgYDVR0RAQH/"
71                    + "BBAwDoEMcmZjQDgyMi5OYW1lMAkGByqGSM44BAMDLwAwLAIUWo0C+R8P"
72                    + "J8LGSLsCRqJ8SOOO0SoCFGvO6mpNdzOKiwlYwfpF/Xyi7s3vMIICkzCC"
73                    + "AlOgAwIBAgICAiswCQYHKoZIzjgEAzAdMRswGQYDVQQKExJDZXJ0aWZp"
74                    + "Y2F0ZSBJc3N1ZXIwIxcNMDYwOTA1MDk1MzA2WhgSMjMzNjEwMTMwMjUx"
75                    + "MjcuODFaMB0xGzAZBgNVBAoTEkNlcnRpZmljYXRlIElzc3VlcjCCAbgw"
76                    + "ggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3Ujzv"
77                    + "RADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3"
78                    + "a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQT"
79                    + "WhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvw"
80                    + "WBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlX"
81                    + "jrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4r"
82                    + "s6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtV"
83                    + "JWQBTDv+z0kqA4GFAAKBgQDyCA7AK6Kep2soxt8tIsWWkafbYdueAkeB"
84                    + "Nnm46H0OteFa80HMuJjKJ0LjlPrdjFMARKyW/GATtQhghY/MrINAHmKc"
85                    + "X5QjL1DkuJKDNggLHqj5D6efsWmLKwLvmviWLzWtjh7YGBZeLt0ezu2q"
86                    + "49aKcOzkkDsCSsMz09u9284L6qMeMBwwGgYDVR0RAQH/BBAwDoEMcmZj"
87                    + "QDgyMi5OYW1lMAkGByqGSM44BAMDLwAwLAIUWo0C+R8PJ8LGSLsCRqJ8"
88                    + "SOOO0SoCFGvO6mpNdzOKiwlYwfpF/Xyi7s3voYIBsjCB1jCBlwIBATAJ"
89                    + "BgcqhkjOOAQDMBUxEzARBgNVBAoTCkNSTCBJc3N1ZXIXDTA2MDkwNTA5"
90                    + "NTMwN1oXDTA2MDkwNTA5NTQ0N1owQTA/AgICKxcNMDYwOTA1MDk1MzA4"
91                    + "WjAqMAoGA1UdFQQDCgEBMBwGA1UdGAQVGBMyMDA2MDkwNTA5NTMwNy43"
92                    + "MThaoA8wDTALBgNVHRQEBAICEVwwCQYHKoZIzjgEAwMvADAsAhR/l5kI"
93                    + "bTkuJe9HjcpZ4Ff4Ifv9xwIUIXBlDKsNFlgYdWWTxzrrJOHyMuUwgdYw"
94                    + "gZcCAQEwCQYHKoZIzjgEAzAVMRMwEQYDVQQKEwpDUkwgSXNzdWVyFw0w"
95                    + "NjA5MDUwOTUzMDdaFw0wNjA5MDUwOTU0NDdaMEEwPwICAisXDTA2MDkw"
96                    + "NTA5NTMwOFowKjAKBgNVHRUEAwoBATAcBgNVHRgEFRgTMjAwNjA5MDUw"
97                    + "OTUzMDcuNzE4WqAPMA0wCwYDVR0UBAQCAhFcMAkGByqGSM44BAMDLwAw"
98                    + "LAIUf5eZCG05LiXvR43KWeBX+CH7/ccCFCFwZQyrDRZYGHVlk8c66yTh"
99                    + "8jLlMQA=";
100
101    /**
102     * Base64 encoded PkiPath object containing 2 X.509 certificates.
103     */
104    private static String pkiPath =
105            "MIIFMDCCApQwggJToAMCAQICAgIrMAkGByqGSM44BAMwHTEbMBkGA1UE"
106                    + "ChMSQ2VydGlmaWNhdGUgSXNzdWVyMCMXDTA2MDkwNTExMDAyM1oYEjIz"
107                    + "MzYxMDEzMTQwNDE4LjEyWjAdMRswGQYDVQQKExJDZXJ0aWZpY2F0ZSBJ"
108                    + "c3N1ZXIwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qc"
109                    + "Luzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzX"
110                    + "gTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7"
111                    + "g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML"
112                    + "zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5"
113                    + "V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6"
114                    + "i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa"
115                    + "5Z8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEA8ggOwCuinqdrKMbfLSLF"
116                    + "lpGn22HbngJHgTZ5uOh9DrXhWvNBzLiYyidC45T63YxTAESslvxgE7UI"
117                    + "YIWPzKyDQB5inF+UIy9Q5LiSgzYICx6o+Q+nn7FpiysC75r4li81rY4e"
118                    + "2BgWXi7dHs7tquPWinDs5JA7AkrDM9PbvdvOC+qjHjAcMBoGA1UdEQEB"
119                    + "/wQQMA6BDHJmY0A4MjIuTmFtZTAJBgcqhkjOOAQDAzAAMC0CFQCAUA72"
120                    + "3BIXNluugYcScXeb9vx5vAIUYreCA5ljANvzSsD0ofI+xph4//IwggKU"
121                    + "MIICU6ADAgECAgICKzAJBgcqhkjOOAQDMB0xGzAZBgNVBAoTEkNlcnRp"
122                    + "ZmljYXRlIElzc3VlcjAjFw0wNjA5MDUxMTAwMjNaGBIyMzM2MTAxMzE0"
123                    + "MDQxOC4xMlowHTEbMBkGA1UEChMSQ2VydGlmaWNhdGUgSXNzdWVyMIIB"
124                    + "uDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdS"
125                    + "PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/Jm"
126                    + "YLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1"
127                    + "VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE"
128                    + "C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdR"
129                    + "WVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOu"
130                    + "HiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6A"
131                    + "e1UlZAFMO/7PSSoDgYUAAoGBAPIIDsArop6nayjG3y0ixZaRp9th254C"
132                    + "R4E2ebjofQ614VrzQcy4mMonQuOU+t2MUwBErJb8YBO1CGCFj8ysg0Ae"
133                    + "YpxflCMvUOS4koM2CAseqPkPp5+xaYsrAu+a+JYvNa2OHtgYFl4u3R7O"
134                    + "7arj1opw7OSQOwJKwzPT273bzgvqox4wHDAaBgNVHREBAf8EEDAOgQxy"
135                    + "ZmNAODIyLk5hbWUwCQYHKoZIzjgEAwMwADAtAhUAgFAO9twSFzZbroGH"
136                    + "EnF3m/b8ebwCFGK3ggOZYwDb80rA9KHyPsaYeP/y";
137
138    /**
139     * Base64 encoded X.509 CRL.
140     */
141    private static String x509crl =
142            "MIHWMIGWAgEBMAkGByqGSM44BAMwFTETMBEGA1UEChMKQ1JMIElzc3Vl"
143                    + "chcNMDYwOTA1MDk1MzA4WhcNMDYwOTA1MDk1NDQ4WjBAMD4CAgIrFw0w"
144                    + "NjA5MDUwOTUzMDhaMCkwCgYDVR0VBAMKAQEwGwYDVR0YBBQYEjIwMDYw"
145                    + "OTA1MDk1MzA4Ljg5WqAPMA0wCwYDVR0UBAQCAhFcMAkGByqGSM44BAMD"
146                    + "MAAwLQIUJ1KAJumw8mOpGXT/FS5K9WwOBRICFQCR+ez59x9GH3sKoByC"
147                    + "IooeR20Q3Q==";
148
149    /**
150     * Base64 encoded X.509 Certificate.
151     */
152    private static String x509cert =
153            "MIICkzCCAlOgAwIBAgICAiswCQYHKoZIzjgEAzAdMRswGQYDVQQKExJD"
154                    + "ZXJ0aWZpY2F0ZSBJc3N1ZXIwIxcNMDYwOTA4MDU1NzUxWhgSMjMzNjEx"
155                    + "MTAxMTM4NTUuNjJaMB0xGzAZBgNVBAoTEkNlcnRpZmljYXRlIElzc3Vl"
156                    + "cjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn"
157                    + "9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4Ad"
158                    + "NG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPF"
159                    + "HsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5"
160                    + "gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9"
161                    + "B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyN"
162                    + "KOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaS"
163                    + "i2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDyCA7AK6Kep2soxt8tIsWWkafb"
164                    + "YdueAkeBNnm46H0OteFa80HMuJjKJ0LjlPrdjFMARKyW/GATtQhghY/M"
165                    + "rINAHmKcX5QjL1DkuJKDNggLHqj5D6efsWmLKwLvmviWLzWtjh7YGBZe"
166                    + "Lt0ezu2q49aKcOzkkDsCSsMz09u9284L6qMeMBwwGgYDVR0RAQH/BBAw"
167                    + "DoEMcmZjQDgyMi5OYW1lMAkGByqGSM44BAMDLwAwLAIUO+JWKWai/8Si"
168                    + "2oEfhKSobLttYeYCFFO5YVDvtnmVVnvQTtUvrPpsaxJR";
169
170    /**
171     * Base64 encoded Private Key used for data signing.
172     * This data is not directly used in the test, but it could be
173     * useful in future in case of implementation of additional
174     * testing data structures.
175     */
176    private static String b64PrivateKeySpec =
177            "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s"
178                    + "5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7"
179                    + "gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P2"
180                    + "08UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yy"
181                    + "krmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdM"
182                    + "Cz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotU"
183                    + "fI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWf"
184                    + "BpKLZl6Ae1UlZAFMO/7PSSoEFgIUS24w346zv1ic3wsLOHzxQnf9aX0=";
185
186    /**
187     * Base64 encoded Public Key for signature verification.
188     */
189    private static String b64PublicKeySpec =
190            "MIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2"
191                    + "EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00"
192                    + "b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue"
193                    + "wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC"
194                    + "ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0H"
195                    + "gmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o"
196                    + "4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKL"
197                    + "Zl6Ae1UlZAFMO/7PSSoDgYUAAoGBAPIIDsArop6nayjG3y0ixZaRp9th"
198                    + "254CR4E2ebjofQ614VrzQcy4mMonQuOU+t2MUwBErJb8YBO1CGCFj8ys"
199                    + "g0AeYpxflCMvUOS4koM2CAseqPkPp5+xaYsrAu+a+JYvNa2OHtgYFl4u"
200                    + "3R7O7arj1opw7OSQOwJKwzPT273bzgvq";
201
202    /**
203     * The name of the algorithm used for Certificate/CRL signing.
204     */
205    private static String publicKeyAlgorithm = "DSA";
206
207    /**
208     * The public key to verify generated Certificates and CRLs.
209     */
210    private static PublicKey publicKey;
211
212    static {
213        try {
214            X509EncodedKeySpec publicKeySpec =
215                    new X509EncodedKeySpec(
216                            Base64.decode(b64PublicKeySpec.getBytes("UTF-8")));
217            KeyFactory keyFactory =
218                    KeyFactory.getInstance(publicKeyAlgorithm);
219            publicKey = keyFactory.generatePublic(publicKeySpec);
220        } catch (NoSuchAlgorithmException e) {
221            // provider is not installed, will not verify the generated data
222            publicKey = null;
223        } catch (Exception e) {
224            // problems with a representation of the key
225            e.printStackTrace();
226            publicKey = null;
227        }
228    }
229
230    // array contains allowed PEM delimiters
231    private static String[][] good = {
232            { "-----BEGIN\n", "\n-----END" },
233            { "-----BEGIN-----\n", "\n-----END-----" },
234            { "-----BEGIN PEM ENCODED DATA STRUCTURE-----\n", "\n-----END-----" },
235            { "-----BEGIN MEANINGLESS SEPARATOR\n", "\n-----END PEM" },
236    };
237
238    // array contains not allowed PEM delimiters
239    private static String[][] bad = {
240            { "----BEGI\n", "\n-----END" },
241            { "-----BEGI\n", "\n----END" },
242            { "-----BEGI\n", "\n-----END" },
243            { "-----BEGIN\n", "\n-----EN" },
244            { "-----BEGIN", "\n-----END" },
245            { "-----BEGIN\n", "-----END" },
246    };
247
248    // array contains bad PEM encoded content.
249    private static String[] bad_content = {
250            "MIIHDwYJ", "ABCD", "\r\n\r\n", "\n\r", ""
251    };
252
253    /**
254     * generateCRLs method testing.
255     * Generates CRLs on the base of PKCS7 SignedData Object
256     */
257    public void testGenerateCRLs() throws Exception {
258        CertificateFactory factory = CertificateFactory.getInstance("X.509");
259
260        // Testing the CRLs generation on the base of PKCS7 SignedData object
261        ByteArrayInputStream bais = new ByteArrayInputStream(
262                Base64.decode(pkcs7so.getBytes("UTF-8")));
263
264        Collection crls = factory.generateCRLs(bais);
265        assertNotNull("Factory returned null on correct PKCS7 data", crls);
266        assertEquals("The size of collection differs from expected",
267                2, crls.size());
268
269        if (publicKey != null) {
270            // verify the signatures
271            for (Iterator i = crls.iterator(); i.hasNext(); ) {
272                ((X509CRL) i.next()).verify(publicKey);
273            }
274        }
275    }
276
277    /**
278     * generateCRL/generateCertificate method testing.
279     * Tries to generates single CRL/Certificate
280     * on the base of PKCS7 SignedData Object.
281     */
282    public void testGenerateCRL() throws Exception {
283        CertificateFactory factory = CertificateFactory.getInstance("X.509");
284
285        ByteArrayInputStream bais = new ByteArrayInputStream(
286                Base64.decode(pkcs7so.getBytes("UTF-8")));
287        try {
288            factory.generateCRL(bais);
289            fail("Expected exception was not thrown");
290        } catch (Exception e) {
291        }
292        bais = new ByteArrayInputStream(Base64.decode(pkcs7so.getBytes("UTF-8")));
293        try {
294            factory.generateCertificate(bais);
295            fail("Expected exception was not thrown");
296        } catch (Exception e) {
297        }
298    }
299
300    /**
301     * Generates CRLs on the base of PEM encoding.
302     */
303    public void testGenerateBase64CRL() throws Exception {
304        CertificateFactory factory = CertificateFactory.getInstance("X.509");
305        ByteArrayInputStream bais;
306
307        for (int i = 0; i < good.length; i++) {
308            bais = new ByteArrayInputStream(
309                    (good[i][0] + x509crl + good[i][1]).getBytes("UTF-8"));
310
311            X509CRL crl = (X509CRL) factory.generateCRL(bais);
312            assertNotNull("Factory returned null on correct data", crl);
313
314            if (publicKey != null) {
315                // verify the signatures
316                crl.verify(publicKey);
317            }
318        }
319
320        for (int i = 0; i < bad_content.length; i++) {
321            bais = new ByteArrayInputStream(
322                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
323            try {
324                factory.generateCRL(bais);
325                fail("Expected exception was not thrown");
326            } catch (Exception e) {
327                // e.printStackTrace();
328            }
329        }
330
331        for (int i = 0; i < bad.length; i++) {
332            bais = new ByteArrayInputStream(
333                    (bad[i][0] + x509crl + bad[i][1]).getBytes("UTF-8"));
334            try {
335                factory.generateCRL(bais);
336                fail("Expected exception was not thrown");
337            } catch (Exception e) {
338            }
339        }
340    }
341
342    private void verifyCRLs(Collection crls) throws Exception {
343        if (publicKey != null) {
344            // verify the signatures
345            for (Iterator it = crls.iterator(); it.hasNext(); ) {
346                ((X509CRL) it.next()).verify(publicKey);
347            }
348        }
349    }
350
351    ;
352
353    private void verifyCertificates(Collection certs) throws Exception {
354        if (publicKey != null) {
355            // verify the signatures
356            for (Iterator it = certs.iterator(); it.hasNext(); ) {
357                ((X509Certificate) it.next()).verify(publicKey);
358            }
359        }
360    }
361
362    ;
363
364    /**
365     * generateCRLs method testing.
366     * Generates CRLs on the base of consequent
367     * PEM X.509(ASN.1)/X.509(ASN.1)/PKCS7 forms.
368     */
369    public void testGenerateBase64CRLs() throws Exception {
370        CertificateFactory factory = CertificateFactory.getInstance("X.509");
371
372        // ------------------------ Test Data -----------------------------
373        // encoding describing codes
374        int pem_x509 = 0, asn_x509 = 1, pem_pkcs = 2, asn_pkcs = 3,
375                bad = 4, npe_bad = 5, npe_bad2 = 6, num_of_variants = 7;
376        // error code, marks sequences as throwing exceptions
377        int error = 999;
378        // test sequences
379        int[][] sequences = {
380                { pem_x509, pem_x509 },
381                { pem_x509, asn_x509 },
382                { pem_x509, asn_x509, pem_x509 },
383                { asn_x509, asn_x509 },
384                { asn_x509, pem_x509 },
385                { asn_x509, pem_x509, asn_x509 },
386                // -1 means that only 1 (-(-1)) CRL will be generated
387                // on the base of this encodings sequence
388                { -1, pem_x509, pem_pkcs },
389                { -1, pem_x509, bad },
390                // {-1/*-error*/, pem_x509, npe_bad2},
391                // {-1/*-error*/, pem_x509, npe_bad},
392                { -2, pem_pkcs, pem_x509 }, // 2 CRLs are expected
393                { -2, pem_pkcs, bad },
394                { -2, pem_pkcs, npe_bad },
395                { -2, pem_pkcs, npe_bad2 },
396                { -1, asn_x509, pem_pkcs },
397                { -1, asn_x509, bad },
398                // {-1/*-error*/, asn_x509, npe_bad},
399                // {-1/*-error*/, asn_x509, npe_bad2},
400                // exception is expected
401                { -error, bad },
402                { -error, bad, asn_x509 },
403                { -error, npe_bad },
404                { -error, npe_bad2 },
405        };
406        // actual encodings
407        byte[][] data = new byte[num_of_variants][];
408        data[pem_x509] = (good[0][0] + x509crl + good[0][1] + "\n").getBytes("UTF-8");
409        data[asn_x509] = Base64.decode(x509crl.getBytes("UTF-8"));
410        data[pem_pkcs] = (good[0][0] + pkcs7so + good[0][1] + "\n").getBytes("UTF-8");
411        data[asn_pkcs] = Base64.decode(pkcs7so.getBytes("UTF-8"));
412        data[bad] = new byte[] { 0, 1, 1, 1, 1, 1, 0, 1 };
413        data[npe_bad] = new byte[] { 0, 1, 1, 1, 1, 1, 1, 0 };
414        data[npe_bad2] = new byte[] { 48, 0, 3, 4, 5, 6, 7 };
415
416        // -------------------------- Test --------------------------------
417        // Tests CRL generation on the base of sequences of heterogeneous
418        // data format
419        for (int i = 0; i < sequences.length; i++) { // for each of the sequences..
420            // expected size og generated CRL collection
421            int expected_size = (sequences[i][0] < 0)
422                    ? -sequences[i][0]
423                    : sequences[i].length;
424            // compute the size of the encoding described by sequence
425            int encoding_size = 0;
426            //System.out.print("Sequence:");
427            for (int j = 0; j < sequences[i].length; j++) {
428                //System.out.print(" "+sequences[i][j]);
429                if (sequences[i][j] >= 0) {
430                    encoding_size += data[sequences[i][j]].length;
431                }
432            }
433            //System.out.println("");
434            // create the encoding of described sequence
435            byte[] encoding = new byte[encoding_size];
436            int position = 0;
437            for (int j = 0; j < sequences[i].length; j++) {
438                if (sequences[i][j] >= 0) {
439                    System.arraycopy(
440                            data[sequences[i][j]], 0, // from
441                            encoding, position, // to
442                            data[sequences[i][j]].length); // length
443                    position += data[sequences[i][j]].length;
444                }
445            }
446
447            if (expected_size == error) { // exception throwing test
448                try {
449                    factory.generateCRLs(new ByteArrayInputStream(encoding));
450                    fail("Expected exception was not thrown");
451                } catch (Exception e) {
452                }
453            } else {
454                Collection crls =
455                        factory.generateCRLs(new ByteArrayInputStream(encoding));
456                assertNotNull("Factory returned null on correct data", crls);
457                assertEquals("The size of collection differs from expected",
458                        expected_size, crls.size());
459                verifyCRLs(crls);
460            }
461        }
462    }
463
464    /**
465     * generateCertificates method testing.
466     * Generates Certificates on the base of consequent
467     * PEM X.509(ASN.1)/X.509(ASN.1)/PKCS7 forms.
468     */
469    public void testGenerateBase64Certificates() throws Exception {
470        CertificateFactory factory = CertificateFactory.getInstance("X.509");
471
472        // ------------------------ Test Data -----------------------------
473        // encoding describing codes
474        int pem_x509 = 0, asn_x509 = 1, pem_pkcs = 2, asn_pkcs = 3,
475                bad = 4, bad1 = 5, bad2 = 6, num_of_variants = 7;
476        // error code, marks sequences as throwing exceptions
477        int error = 999;
478        // test sequences
479        int[][] sequences = {
480                { pem_x509, pem_x509 },
481                { pem_x509, asn_x509 },
482                { pem_x509, asn_x509, pem_x509 },
483                { asn_x509, asn_x509 },
484                { asn_x509, pem_x509 },
485                { asn_x509, pem_x509, asn_x509 },
486                // -1 means that only 1 (-(-1)) Certificate will be generated
487                // on the base of this encodings sequence
488                // {-1/*-error*/, pem_x509, pem_pkcs},
489                // {-1/*-error*/, pem_x509, bad},
490                { -2, pem_pkcs, pem_x509 }, // 2 Certificates are expected
491                { -2, pem_pkcs, bad },
492                { -2, pem_pkcs, bad1 },
493                { -2, pem_pkcs, bad2 },
494                // {-1/*-error*/, asn_x509, pem_pkcs},
495                // {-1/*-error*/, asn_x509, bad},
496                // {-1/*-error*/, asn_x509, bad1},
497                // {-1/*-error*/, pem_x509, bad1},
498                // {-1/*-error*/, asn_x509, bad2},
499                // {-1/*-error*/, pem_x509, bad2},
500                // exception is expected
501                { -error, bad },
502                { -error, bad, asn_x509 },
503                { -error, bad1 },
504                { -error, bad2 },
505        };
506        // actual encodings
507        byte[][] data = new byte[num_of_variants][];
508        data[pem_x509] = (good[0][0] + x509cert + good[0][1] + "\n").getBytes("UTF-8");
509        data[asn_x509] = Base64.decode(x509cert.getBytes("UTF-8"));
510        data[pem_pkcs] = (good[0][0] + pkcs7so + good[0][1] + "\n").getBytes("UTF-8");
511        data[asn_pkcs] = Base64.decode(pkcs7so.getBytes("UTF-8"));
512        data[bad] = new byte[] { 0, 1, 1, 1, 1, 1, 0, 1 };
513        data[bad1] = new byte[] { 0, 1, 1, 1, 1, 1, 1, 0 };
514        data[bad2] = new byte[] { 48, 0, 3, 4, 5, 6, 7 };
515
516        // -------------------------- Test --------------------------------
517        // Tests Certificate generation on the base of sequences of heterogeneous
518        // data format
519        for (int i = 0; i < sequences.length; i++) { // for each of the sequences..
520            // expected size og generated Certificate collection
521            int expected_size = (sequences[i][0] < 0)
522                    ? -sequences[i][0]
523                    : sequences[i].length;
524            // compute the size of the encoding described by sequence
525            int encoding_size = 0;
526            //System.out.print("Sequence:");
527            for (int j = 0; j < sequences[i].length; j++) {
528                //System.out.print(" "+sequences[i][j]);
529                if (sequences[i][j] >= 0) {
530                    encoding_size += data[sequences[i][j]].length;
531                }
532            }
533            //System.out.println("");
534            // create the encoding of described sequence
535            byte[] encoding = new byte[encoding_size];
536            int position = 0;
537            for (int j = 0; j < sequences[i].length; j++) {
538                if (sequences[i][j] >= 0) {
539                    System.arraycopy(
540                            data[sequences[i][j]], 0, // from
541                            encoding, position, // to
542                            data[sequences[i][j]].length); // length
543                    position += data[sequences[i][j]].length;
544                }
545            }
546
547            if (expected_size == error) { // exception throwing test
548                try {
549                    factory.generateCertificates(new ByteArrayInputStream(encoding));
550                    fail("Expected exception was not thrown");
551                } catch (Exception e) {
552                }
553            } else {
554                Collection certs =
555                        factory.generateCertificates(new ByteArrayInputStream(encoding));
556                assertNotNull("Factory returned null on correct data", certs);
557                assertEquals("The size of collection differs from expected",
558                        expected_size, certs.size());
559                verifyCertificates(certs);
560            }
561        }
562    }
563
564    /**
565     * Generates CRLs/Certificates on the base of PEM PKCS7 encoding.
566     */
567    public void testGenerateBase64PKCS7() throws Exception {
568        CertificateFactory factory = CertificateFactory.getInstance("X.509");
569
570        ByteArrayInputStream bais;
571        for (int i = 0; i < good.length; i++) {
572            bais = new ByteArrayInputStream(
573                    (good[i][0] + pkcs7so + good[i][1]).getBytes("UTF-8"));
574            Collection crls = factory.generateCRLs(bais);
575            assertNotNull("Factory returned null on correct PKCS7 data", crls);
576            assertEquals("The size of collection differs from expected",
577                    2, crls.size());
578            if (publicKey != null) {
579                // verify the signatures
580                for (Iterator it = crls.iterator(); it.hasNext(); ) {
581                    ((X509CRL) it.next()).verify(publicKey);
582                }
583            }
584            bais = new ByteArrayInputStream(
585                    (good[i][0] + pkcs7so + good[i][1]).getBytes("UTF-8"));
586            Collection certs = factory.generateCertificates(bais);
587            assertNotNull("Factory returned null on correct PKCS7 data", certs);
588            assertEquals("The size of collection differs from expected",
589                    2, certs.size());
590            if (publicKey != null) {
591                // verify the signatures
592                for (Iterator it = certs.iterator(); it.hasNext(); ) {
593                    ((X509Certificate) it.next()).verify(publicKey);
594                }
595            }
596        }
597
598        for (int i = 0; i < bad_content.length; i++) {
599            bais = new ByteArrayInputStream(
600                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
601            try {
602                factory.generateCertificates(bais);
603                fail("Expected exception was not thrown");
604            } catch (Exception e) {
605            }
606            bais = new ByteArrayInputStream(
607                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
608            try {
609                factory.generateCRLs(bais);
610                fail("Expected exception was not thrown");
611            } catch (Exception e) {
612            }
613        }
614
615        for (int i = 0; i < bad.length; i++) {
616            bais = new ByteArrayInputStream(
617                    (bad[i][0] + pkcs7so + bad[i][1]).getBytes("UTF-8"));
618            try {
619                factory.generateCRLs(bais);
620                fail("Expected exception was not thrown");
621            } catch (Exception e) {
622            }
623            bais = new ByteArrayInputStream(
624                    (bad[i][0] + pkcs7so + bad[i][1]).getBytes("UTF-8"));
625            try {
626                factory.generateCertificates(bais);
627                fail("Expected exception was not thrown");
628            } catch (Exception e) {
629            }
630        }
631    }
632
633    /**
634     * Generates CertPaths on the base of PEM PkiPath/PKCS7 encoding.
635     */
636    public void testGenerateBase64CertPath() throws Exception {
637        CertificateFactory factory = CertificateFactory.getInstance("X.509");
638
639        ByteArrayInputStream bais;
640        List certificates;
641        for (int i = 0; i < good.length; i++) {
642            bais = new ByteArrayInputStream(
643                    (good[i][0] + pkiPath + good[i][1]).getBytes("UTF-8"));
644
645            certificates = factory.generateCertPath(bais).getCertificates();
646            assertEquals("The size of the list differs from expected",
647                    2, certificates.size());
648
649            if (publicKey != null) {
650                // verify the signatures
651                for (Iterator it = certificates.iterator(); it.hasNext(); ) {
652                    ((X509Certificate) it.next()).verify(publicKey);
653                }
654            }
655
656            bais = new ByteArrayInputStream(
657                    (good[i][0] + pkiPath + good[i][1]).getBytes("UTF-8"));
658
659            certificates =
660                    factory.generateCertPath(bais, "PkiPath").getCertificates();
661            assertEquals("The size of the list differs from expected",
662                    2, certificates.size());
663
664            if (publicKey != null) {
665                // verify the signatures
666                for (Iterator it = certificates.iterator(); it.hasNext(); ) {
667                    ((X509Certificate) it.next()).verify(publicKey);
668                }
669            }
670
671            bais = new ByteArrayInputStream(
672                    (good[i][0] + pkcs7so + good[i][1]).getBytes("UTF-8"));
673
674            certificates =
675                    factory.generateCertPath(bais, "PKCS7").getCertificates();
676            assertEquals("The size of the list differs from expected",
677                    2, certificates.size());
678
679            if (publicKey != null) {
680                // verify the signatures
681                for (Iterator it = certificates.iterator(); it.hasNext(); ) {
682                    ((X509Certificate) it.next()).verify(publicKey);
683                }
684            }
685        }
686
687        // testing empty PkiPath structure (ASN.1 such as 0x30, 0x00)
688        bais = new ByteArrayInputStream(
689                (good[0][0] + "MAB=" + good[0][1]).getBytes("UTF-8")); // "MABCDEFG"
690        assertEquals("The size of the list differs from expected",
691                0, factory.generateCertPath(bais, "PkiPath")
692                .getCertificates().size());
693
694        // testing with bad PEM content
695        for (int i = 0; i < bad_content.length; i++) {
696            bais = new ByteArrayInputStream(
697                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
698            try {
699                factory.generateCertPath(bais);
700                fail("Expected exception was not thrown");
701            } catch (Exception e) {
702            }
703            bais = new ByteArrayInputStream(
704                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
705            try {
706                factory.generateCertPath(bais, "PkiPath");
707                fail("Expected exception was not thrown");
708            } catch (Exception e) {
709            }
710            bais = new ByteArrayInputStream(
711                    (good[0][0] + bad_content[i] + good[0][1]).getBytes("UTF-8"));
712            try {
713                factory.generateCertPath(bais, "PKCS7");
714                fail("Expected exception was not thrown");
715            } catch (Exception e) {
716            }
717        }
718
719        for (int i = 0; i < bad.length; i++) {
720            bais = new ByteArrayInputStream(
721                    (bad[i][0] + pkiPath + bad[i][1]).getBytes("UTF-8"));
722            try {
723                factory.generateCertPath(bais);
724                fail("Expected exception was not thrown");
725            } catch (Exception e) {
726            }
727            bais = new ByteArrayInputStream(
728                    (bad[i][0] + pkiPath + bad[i][1]).getBytes("UTF-8"));
729            try {
730                factory.generateCertPath(bais, "PkiPath");
731                fail("Expected exception was not thrown");
732            } catch (Exception e) {
733            }
734            bais = new ByteArrayInputStream(
735                    (bad[i][0] + pkcs7so + bad[i][1]).getBytes("UTF-8"));
736            try {
737                factory.generateCertPath(bais, "PKCS7");
738                fail("Expected exception was not thrown");
739            } catch (Exception e) {
740            }
741        }
742    }
743
744    /**
745     * generateCertificates method testing.
746     */
747    public void testGenerateCertificates() throws Exception {
748        CertificateFactory factory = CertificateFactory.getInstance("X.509");
749
750        // Testing the Certificates generation
751        // on the base of PKCS7 SignedData object
752        ByteArrayInputStream bais = new ByteArrayInputStream(
753                Base64.decode(pkcs7so.getBytes("UTF-8")));
754
755        Collection certs = factory.generateCertificates(bais);
756        assertNotNull("Factory returned null on correct PKCS7 data", certs);
757        assertEquals("The size of collection differs from expected",
758                2, certs.size());
759
760        if (publicKey != null) {
761            // verify the signatures
762            for (Iterator i = certs.iterator(); i.hasNext(); ) {
763                ((X509Certificate) i.next()).verify(publicKey);
764            }
765        }
766    }
767
768    /**
769     * generateCertificates method testing.
770     */
771    public void testGenerateCertPath() throws Exception {
772        CertificateFactory factory = CertificateFactory.getInstance("X.509");
773
774        // Testing the CertPath generation
775        // on the base of PKCS7 SignedData object
776        ByteArrayInputStream bais = new ByteArrayInputStream(
777                Base64.decode(pkcs7so.getBytes("UTF-8")));
778
779        Collection certPath =
780                factory.generateCertPath(bais, "PKCS7").getCertificates();
781        assertEquals("The size of collection differs from expected",
782                2, certPath.size());
783
784        if (publicKey != null) {
785            // verify the signatures
786            for (Iterator i = certPath.iterator(); i.hasNext(); ) {
787                ((X509Certificate) i.next()).verify(publicKey);
788            }
789        }
790
791        // testing empty PkiPath structure (ASN.1 such as 0x30, 0x00)
792        bais = new ByteArrayInputStream(new byte[] { (byte) 0x30, 0x00 });
793        assertEquals("The size of the list differs from expected",
794                0, factory.generateCertPath(bais, "PkiPath")
795                .getCertificates().size());
796    }
797
798}
799