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* @author Alexander Y. Kleymenov
19*/
20
21package org.apache.harmony.security.tests.provider.cert;
22
23import java.io.*;
24import java.math.*;
25import java.util.*;
26import java.security.KeyPairGenerator;
27import java.security.Signature;
28import java.security.KeyPair;
29import java.security.PublicKey;
30import java.security.PrivateKey;
31import java.security.cert.CertificateFactory;
32import java.security.cert.CertificateExpiredException;
33import java.security.cert.CertificateNotYetValidException;
34import javax.security.auth.x500.X500Principal;
35
36import org.apache.harmony.security.asn1.ASN1Integer;
37import org.apache.harmony.security.asn1.ASN1Sequence;
38import org.apache.harmony.security.asn1.ASN1Type;
39import org.apache.harmony.security.asn1.BitString;
40import org.apache.harmony.security.asn1.ObjectIdentifier;
41
42import java.security.cert.CertificateEncodingException;
43import java.security.cert.X509Certificate;
44
45import org.apache.harmony.security.asn1.ASN1BitString;
46import org.apache.harmony.security.x501.Name;
47import org.apache.harmony.security.x509.*;
48
49import java.security.cert.CertificateParsingException;
50
51import junit.framework.Test;
52import junit.framework.TestCase;
53import junit.framework.TestSuite;
54
55/**
56 * X509CertFactoryPerfTest
57 */
58public class X509CertFactoryPerfTest extends TestCase {
59
60    //
61    // The values of certificate's fields:
62    //
63
64    static int         version         = 2; //v3
65    static BigInteger  serialNumber    = BigInteger.valueOf(555555555555555555L);
66
67    // Algorithm name and its OID (http://oid.elibel.tm.fr)
68    static String      algOID          = "1.2.840.10040.4.3";
69    static String      algName         = "SHA1withDSA";
70
71    // DER boolean false encoding (http://asn1.elibel.tm.fr)
72    // Makes no sense. For testing purposes we need just provide
73    // some ASN.1 structure:
74    static byte[]      algParams       = {1, 1, 0};
75    static String      issuerName      = "O=Certificate Issuer";
76    static long        notBefore       = 1000000000L;
77    static long        notAfter        = 2000000000L;
78    static String      subjectName     = "O=Subject Organization";
79
80    // keys are using to make signature and to verify it
81    static PublicKey   publicKey;
82    static PrivateKey  privateKey;
83    static byte[]      key             = new byte[] {1, 2, 3, 4, 5, 6, 7, 8}; // random value
84    static byte[]      keyEncoding     = null;
85    static boolean[]   issuerUniqueID  = new boolean[]
86                {true, false, true, false, true, false, true, false}; // random value
87    static boolean[]   subjectUniqueID = new boolean[]
88                {false, true, false, true, false, true, false, true}; // random value
89
90    // Extensions' values
91    static byte[]      extValEncoding  = new byte[] {1, 1, 1}; // random value
92    static boolean[]   extnKeyUsage    = new boolean[]
93                {true, false, true, false, true, false, true, false, true}; // random value
94    static List    extnExtendedKeyUsage = Arrays.asList(new int[][] {
95        // Extended key usage values as specified in rfc 3280:
96        // (http://www.ietf.org/rfc/rfc3280.txt)
97        ObjectIdentifier.toIntArray("2.5.29.37.0"),       // Any extended key usage
98        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.1"), // TLS Web server authentication
99        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.1"), // TLS Web server authentication
100        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.2"), // TLS Web client authentication
101        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.3"), // Code Signing
102        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.4"), // E-mail protection
103        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.5"), // IP security end system
104        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.6"), // IP security tunnel termination
105        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.7"), // IP security user
106        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.8"), // Timestamping
107        ObjectIdentifier.toIntArray("1.3.6.1.5.5.7.3.9"), // OCSP signing
108        ObjectIdentifier.toIntArray("1.3.6.1.5.5.8.2.2"), // iKEIntermediate
109        ObjectIdentifier.toIntArray("1.3.6.1.4.1.311.10.3.3"), // MS Server Gated Cryptography
110        ObjectIdentifier.toIntArray("2.16.840.1.113730.4.1"), // Netscape Server Gated Cryptography
111    });
112    static NameConstraints nameConstraints;
113    static int extnBCLen = 5;
114    static GeneralNames extnSANames;
115    static GeneralNames extnIANames;
116
117    static {
118        try {
119            extnSANames = new GeneralNames(
120                Arrays.asList(new GeneralName[] {
121                    new GeneralName(1, "rfc@822.Name"),
122                    new GeneralName(2, "dNSName"),
123                    new GeneralName(4, "O=Organization"),
124                    new GeneralName(6, "http://uniform.Resource.Id"),
125                    new GeneralName(7, "255.255.255.0"),
126                    new GeneralName(8, "1.2.3.4444.55555")
127            }));
128            GeneralSubtrees permittedNames = new GeneralSubtrees()
129                    .addSubtree(new GeneralSubtree(
130                            new GeneralName(1, "rfc@822.Name"), 1, 2))
131                    .addSubtree(new GeneralSubtree(
132                            new GeneralName(2, "dNSName")))
133                    .addSubtree(new GeneralSubtree(
134                            new GeneralName(8, "1.2.3.4444.55555"), 2));
135            GeneralSubtrees excludedNames = new GeneralSubtrees()
136                    .addSubtree(new GeneralSubtree(
137                            new GeneralName(1, "rfc@822.BadName"), 1, 2))
138                    .addSubtree(new GeneralSubtree(
139                            new GeneralName(2, "BadDNSName")))
140                    .addSubtree(new GeneralSubtree(
141                            new GeneralName(8, "2.3.4.4444.222"), 2));
142            nameConstraints =
143                new NameConstraints(permittedNames, excludedNames);
144        } catch (IOException e) {
145            // should not be thrown
146            e.printStackTrace();
147            extnSANames = new GeneralNames();
148            nameConstraints = new NameConstraints();
149        }
150        extnIANames = extnSANames;
151
152        try {
153            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
154            keyGen.initialize(1024);
155            KeyPair keyPair = keyGen.genKeyPair();
156            publicKey = keyPair.getPublic();
157            privateKey = keyPair.getPrivate();
158        } catch (Exception e) {
159            e.printStackTrace();
160        }
161    }
162
163    // Extensions
164    static Extension[] extensions      = new Extension[] {
165
166        // Supported critical extensions (as specified in rfc 3280
167        // http://www.ietf.org/rfc/rfc3280.txt):
168
169        // Key Usage
170        new Extension("2.5.29.15", true,
171                ASN1BitString.getInstance()
172                .encode(new BitString(extnKeyUsage))),
173        // Basic Constraints
174        new Extension("2.5.29.19", true, new BasicConstraints(true, extnBCLen)),
175        // Certificate Policies with ANY policy
176        new Extension("2.5.29.32", true,
177                new CertificatePolicies()
178                .addPolicyInformation(new PolicyInformation("2.5.29.32.0"))),
179        // Subject Alternative Name
180        new Extension("2.5.29.17", true,
181                new AlternativeName(AlternativeName.SUBJECT, extnSANames)),
182        // Name Constraints
183        new Extension("2.5.29.30", true, nameConstraints),
184        // Policy Constraints
185        new Extension("2.5.29.36", true, new PolicyConstraints(1, 2)),
186        // Extended Key Usage
187        new Extension("2.5.29.37", true, new ExtendedKeyUsage(extnExtendedKeyUsage)),
188        // Inhibit Any-Policy
189        new Extension("2.5.29.54", true, new InhibitAnyPolicy(1)),
190
191        // Unsupported critical extensions:
192        new Extension("1.2.77.777", true, extValEncoding),
193
194        // Non-critical extensions (as specified in rfc 3280
195        // http://www.ietf.org/rfc/rfc3280.txt):
196
197        // Issuer Alternative Name
198        new Extension("2.5.29.18", false,
199                new AlternativeName(AlternativeName.ISSUER, extnSANames)),
200        // CRL Distribution Points
201        new Extension("2.5.29.31", false,
202                new CRLDistributionPoints(Arrays.asList(new DistributionPoint[] {
203                    new DistributionPoint(
204                        new DistributionPointName(extnSANames),
205                        new ReasonFlags(extnKeyUsage),
206                        extnSANames
207                        ),
208                }))),
209        // Authority Key Identifier
210        new Extension("2.5.29.35", false,
211                new AuthorityKeyIdentifier(
212                    // random value for key identifier
213                    new byte[] {1, 2, 3, 4, 5}, extnSANames, serialNumber)),
214        // Subject Key Identifier
215        new Extension("2.5.29.14", false,
216                // random value for key identifier
217                new SubjectKeyIdentifier(new byte[] {1, 2, 3, 4, 5})),
218        // Policy Mappings
219        new Extension("2.5.29.33", false, extValEncoding),
220    };
221    static List allCritical = Arrays.asList(new String[] {"2.5.29.15", "2.5.29.19",
222        "2.5.29.32", "2.5.29.17", "2.5.29.30", "2.5.29.36", "2.5.29.37",
223        "2.5.29.54", "1.2.77.777"});
224    static List allNonCritical = Arrays.asList(new String[] {"2.5.29.18", "2.5.29.35",
225        "2.5.29.14", "2.5.29.33", "2.5.29.31"});
226
227    static X509Certificate certificate;
228    static TBSCertificate tbsCertificate;
229    static AlgorithmIdentifier signature;
230    static CertificateFactory factory;
231    static ByteArrayInputStream stream, streamCRL, stream_b64;
232    static byte[] tbsCertEncoding;
233    static byte[] signatureValue;
234    // to minimize efforts on signature generation the signature will be
235    // stored in this field
236    static byte[] signatureValueBytes;
237    static byte[] certEncoding, certEncoding_b64;
238
239    static {
240        try {
241            signature =
242                new AlgorithmIdentifier(algOID, algParams);
243            Name issuer = new Name(issuerName);
244            Name subject = new Name(subjectName);
245            Validity validity =
246                new Validity(new Date(notBefore), new Date(notAfter));
247
248            SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo)
249                SubjectPublicKeyInfo.ASN1.decode(publicKey.getEncoded());
250            keyEncoding = subjectPublicKeyInfo.getEncoded();
251
252            Extensions exts = new Extensions(Arrays.asList(extensions));
253
254            tbsCertificate =
255                new TBSCertificate(version, serialNumber,
256                    signature, issuer, validity, subject, subjectPublicKeyInfo,
257                    issuerUniqueID, subjectUniqueID, exts);
258            tbsCertEncoding = tbsCertificate.getEncoded();
259
260            try {
261                Signature sig= Signature.getInstance("DSA");
262                sig.initSign(privateKey);
263                sig.update(tbsCertEncoding, 0, tbsCertEncoding.length);
264                signatureValueBytes = sig.sign();
265            } catch (Exception e) {
266                e.printStackTrace();
267                signatureValueBytes = new byte[10];
268            }
269            factory = CertificateFactory.getInstance("X.509");
270        } catch (Exception e) {
271            e.printStackTrace();
272        }
273    }
274
275    // the testing data was generated by using of classes
276    // from org.apache.harmony.security.asn1 package encoded
277    // by org.apache.harmony.misc.Base64 class.
278
279    private static String base64certEncoding =
280        "-----BEGIN CERTIFICATE-----\n" +
281        "MIIC+jCCAragAwIBAgICAiswDAYHKoZIzjgEAwEBADAdMRswGQYDVQQKExJDZXJ0a" +
282        "WZpY2F0ZSBJc3N1ZXIwIhgPMTk3MDAxMTIxMzQ2NDBaGA8xOTcwMDEyNDAzMzMyMF" +
283        "owHzEdMBsGA1UEChMUU3ViamVjdCBPcmdhbml6YXRpb24wGTAMBgcqhkjOOAQDAQE" +
284        "AAwkAAQIDBAUGBwiBAgCqggIAVaOCAhQwggIQMA8GA1UdDwEB/wQFAwMBqoAwEgYD" +
285        "VR0TAQH/BAgwBgEB/wIBBTAUBgNVHSABAf8ECjAIMAYGBFUdIAAwZwYDVR0RAQH/B" +
286        "F0wW4EMcmZjQDgyMi5OYW1lggdkTlNOYW1lpBcxFTATBgNVBAoTDE9yZ2FuaXphdG" +
287        "lvboYaaHR0cDovL3VuaWZvcm0uUmVzb3VyY2UuSWSHBP///wCIByoDolyDsgMwDAY" +
288        "DVR0eAQH/BAIwADAMBgNVHSQBAf8EAjAAMIGZBgNVHSUBAf8EgY4wgYsGBFUdJQAG" +
289        "CCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDB" +
290        "AYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUHAwgGCCsGAQUFBw" +
291        "MJBggrBgEFBQgCAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GA1UdNgEB/wQDAgE" +
292        "BMA4GBCpNhgkBAf8EAwEBATBkBgNVHRIEXTBbgQxyZmNAODIyLk5hbWWCB2ROU05h" +
293        "bWWkFzEVMBMGA1UEChMMT3JnYW5pemF0aW9uhhpodHRwOi8vdW5pZm9ybS5SZXNvd" +
294        "XJjZS5JZIcE////AIgHKgOiXIOyAzAJBgNVHR8EAjAAMAoGA1UdIwQDAQEBMAoGA1" +
295        "UdDgQDAQEBMAoGA1UdIQQDAQEBMAwGByqGSM44BAMBAQADMAAwLQIUAL4QvoazNWP" +
296        "7jrj84/GZlhm09DsCFQCBKGKCGbrP64VtUt4JPmLjW1VxQA==\n" +
297        "-----END CERTIFICATE-----\n" +
298        "-----BEGIN CERTIFICATE-----\n" +
299        "MIIC+jCCAragAwIBAgICAiswDAYHKoZIzjgEAwEBADAdMRswGQYDVQQKExJDZXJ0a" +
300        "WZpY2F0ZSBJc3N1ZXIwIhgPMTk3MDAxMTIxMzQ2NDBaGA8xOTcwMDEyNDAzMzMyMF" +
301        "owHzEdMBsGA1UEChMUU3ViamVjdCBPcmdhbml6YXRpb24wGTAMBgcqhkjOOAQDAQE" +
302        "AAwkAAQIDBAUGBwiBAgCqggIAVaOCAhQwggIQMA8GA1UdDwEB/wQFAwMBqoAwEgYD" +
303        "VR0TAQH/BAgwBgEB/wIBBTAUBgNVHSABAf8ECjAIMAYGBFUdIAAwZwYDVR0RAQH/B" +
304        "F0wW4EMcmZjQDgyMi5OYW1lggdkTlNOYW1lpBcxFTATBgNVBAoTDE9yZ2FuaXphdG" +
305        "lvboYaaHR0cDovL3VuaWZvcm0uUmVzb3VyY2UuSWSHBP///wCIByoDolyDsgMwDAY" +
306        "DVR0eAQH/BAIwADAMBgNVHSQBAf8EAjAAMIGZBgNVHSUBAf8EgY4wgYsGBFUdJQAG" +
307        "CCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDB" +
308        "AYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUHAwgGCCsGAQUFBw" +
309        "MJBggrBgEFBQgCAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GA1UdNgEB/wQDAgE" +
310        "BMA4GBCpNhgkBAf8EAwEBATBkBgNVHRIEXTBbgQxyZmNAODIyLk5hbWWCB2ROU05h" +
311        "bWWkFzEVMBMGA1UEChMMT3JnYW5pemF0aW9uhhpodHRwOi8vdW5pZm9ybS5SZXNvd" +
312        "XJjZS5JZIcE////AIgHKgOiXIOyAzAJBgNVHR8EAjAAMAoGA1UdIwQDAQEBMAoGA1" +
313        "UdDgQDAQEBMAoGA1UdIQQDAQEBMAwGByqGSM44BAMBAQADMAAwLQIUAL4QvoazNWP" +
314        "7jrj84/GZlhm09DsCFQCBKGKCGbrP64VtUt4JPmLjW1VxQA==\n" +
315        "-----END CERTIFICATE-----\n";
316
317    static {
318        try {
319            certEncoding_b64 = base64certEncoding.getBytes("UTF-8");
320        } catch (UnsupportedEncodingException e) {
321            throw new RuntimeException(e.getMessage());
322        }
323        stream_b64 = new ByteArrayInputStream(certEncoding_b64);
324        stream_b64.mark(certEncoding_b64.length);
325    }
326
327    /**
328     * Creates the master certificate on the base of which
329     * all functionality will be tested.
330     * @return
331     * @throws java.lang.Exception
332     */
333    protected void setUp() throws java.lang.Exception {
334        if ("testVerify3".equals(getName())) {
335            signatureValue = new byte[signatureValueBytes.length];
336            // make incorrect signature value:
337            System.arraycopy(signatureValueBytes, 0,
338                    signatureValue, 0, signatureValueBytes.length);
339            signatureValue[20]++;
340        } else {
341            signatureValue = signatureValueBytes;
342        }
343        Certificate cert =
344            new Certificate(tbsCertificate, signature, signatureValue);
345
346        certEncoding = cert.getEncoded();
347        stream = new ByteArrayInputStream(certEncoding);
348        stream.mark(certEncoding.length);
349        certificate = (X509Certificate) factory.generateCertificate(stream);
350
351        streamCRL = new ByteArrayInputStream(certEncoding);
352        streamCRL.mark(certEncoding.length);
353        //System.out.println("\nUSING: "+certificate.getClass());
354    }
355
356    private static int XXX = 0, flag = 0;
357
358    public void testCreationCRL() throws Exception {
359        byte[] stamp = new byte[10];
360        if ((++flag)%2 != 0) {
361            XXX++;
362        }
363        byte tmp[] = BigInteger.valueOf(XXX).toByteArray();
364        System.arraycopy(tmp, 0, stamp, 0, tmp.length);
365        System.arraycopy(stamp, 0, certEncoding,
366                certEncoding.length-stamp.length, stamp.length);
367
368        stream.reset();
369        java.security.cert.Certificate c = factory.generateCertificate(stream);
370
371        byte[] enc = c.getEncoded();
372        byte[] stamp_chek = new byte[stamp.length];
373
374        System.arraycopy(enc, enc.length - stamp.length,
375                stamp_chek, 0, stamp.length);
376
377        if (!Arrays.equals(stamp, stamp_chek)) {
378            fail("Wrong encoding received.");
379        }
380    }
381
382    public void testCreation1() throws Exception {
383        byte[] stamp = new byte[10];
384        if ((++flag)%2 != 0) {
385            XXX++;
386        }
387        byte tmp[] = BigInteger.valueOf(XXX).toByteArray();
388        System.arraycopy(tmp, 0, stamp, 0, tmp.length);
389        System.arraycopy(stamp, 0, certEncoding,
390                certEncoding.length-stamp.length, stamp.length);
391
392        stream.reset();
393        java.security.cert.Certificate c = factory.generateCertificate(stream);
394
395        byte[] enc = c.getEncoded();
396        byte[] stamp_chek = new byte[stamp.length];
397
398        System.arraycopy(enc, enc.length - stamp.length,
399                stamp_chek, 0, stamp.length);
400
401        if (!Arrays.equals(stamp, stamp_chek)) {
402            fail("Wrong encoding received.");
403        }
404    }
405
406    public void testCreation2() throws Exception {
407        stream_b64.reset();
408        factory.generateCertificate(stream_b64);
409    }
410
411    /**
412     * checkValidity() method testing.
413     */
414    public void testCheckValidity1() {
415        try {
416            certificate.checkValidity();
417            fail("CertificateExpiredException should be thrown.");
418        } catch (CertificateNotYetValidException e) {
419            fail("Unexpected CertificateNotYetValidException was thrown.");
420        } catch (CertificateExpiredException e) {
421        }
422    }
423
424    /**
425     * checkValidity(Date date) method testing.
426     */
427    public void testCheckValidity2() {
428        try {
429            certificate.checkValidity(new Date(3000000000L));
430            fail("CertificateExpiredException should be thrown.");
431        } catch (CertificateNotYetValidException e) {
432            fail("Unexpected CertificateNotYetValidException was thrown.");
433        } catch (CertificateExpiredException e) {
434        }
435        try {
436            certificate.checkValidity(new Date(100000000L));
437            fail("CertificateNotYetValidException be thrown.");
438        } catch (CertificateExpiredException e) {
439            fail("Unexpected CertificateExpiredException was thrown.");
440        } catch (CertificateNotYetValidException e) {
441        }
442        try {
443            certificate.checkValidity(new Date(1000000000L));
444            certificate.checkValidity(new Date(1500000000L));
445            certificate.checkValidity(new Date(2000000000L));
446        } catch (CertificateExpiredException e) {
447            fail("Unexpected CertificateExpiredException was thrown.");
448        } catch (CertificateNotYetValidException e) {
449            fail("Unexpected CertificateNotYetValidException was thrown.");
450        }
451    }
452
453    /**
454     * getVersion() method testing.
455     */
456    public void testGetVersion() {
457        assertEquals("The version of the certificate should be 3",
458                3, certificate.getVersion());
459    }
460
461    /**
462     * getSerialNumber() method testing.
463     */
464    public void testGetSerialNumber() {
465        assertEquals("Incorrect value of version",
466                serialNumber, certificate.getSerialNumber());
467    }
468
469    /**
470     * getIssuerDN() method testing.
471     */
472    public void testGetIssuerDN() {
473        assertEquals("Incorrect issuer",
474                new X500Principal(issuerName).getName(),
475                certificate.getIssuerDN().getName());
476    }
477
478    /**
479     * getIssuerX500Principal() method testing.
480     */
481    public void testGetIssuerX500Principal() {
482        assertEquals("Incorrect issuer",
483                new X500Principal(issuerName),
484                certificate.getIssuerX500Principal());
485    }
486
487    /**
488     * getSubjectDN() method testing.
489     */
490    public void testGetSubjectDN() {
491        assertEquals("Incorrect subject",
492                new X500Principal(subjectName).getName(),
493                certificate.getSubjectDN().getName());
494    }
495
496    /**
497     * getSubjectX500Principal() method testing.
498     */
499    public void testGetSubjectX500Principal() {
500        assertEquals("Incorrect subject",
501                new X500Principal(subjectName),
502                certificate.getSubjectX500Principal());
503    }
504
505    /**
506     * getNotBefore() method testing.
507     */
508    public void testGetNotBefore() {
509        assertEquals("Incorrect notBefore date",
510                new Date(notBefore), certificate.getNotBefore());
511    }
512
513    /**
514     * getNotAfter() method testing.
515     */
516    public void testGetNotAfter() {
517        assertEquals("Incorrect notAfter date",
518                new Date(notAfter), certificate.getNotAfter());
519    }
520
521    public static void printAsHex(int perLine, String prefix,
522                                        String delimiter, byte[] data) {
523        for (int i=0; i<data.length; i++) {
524            String tail = Integer.toHexString(0x000000ff & data[i]);
525            if (tail.length() == 1) {
526                tail = "0" + tail;
527            }
528            System.out.print(prefix + "0x" + tail + delimiter);
529
530            if (((i+1)%perLine) == 0) {
531                System.out.println();
532            }
533        }
534        System.out.println();
535    }
536
537    /**
538     * getTBSCertificate() method testing.
539     */
540    public void testGetTBSCertificate() {
541        try {
542            if (!Arrays.equals(
543                        tbsCertEncoding, certificate.getTBSCertificate())) {
544                System.out.println("TBSCertificate encoding missmatch:");
545                System.out.println("Expected:");
546                printAsHex(20, "", " ", tbsCertEncoding);
547                System.out.println("Got:");
548                printAsHex(20, "", " ", certificate.getTBSCertificate());
549                fail("Incorrect encoding of TBSCertificate.");
550            }
551        } catch (CertificateEncodingException e) {
552            fail("Unexpected CertificateEncodingException was thrown.");
553        }
554    }
555
556    /**
557     * getSignature() method testing.
558     */
559    public void testGetSignature() {
560        if (!Arrays.equals(signatureValue, certificate.getSignature())) {
561            fail("Incorrect Signature value.");
562        }
563    }
564
565    /**
566     * getSigAlgName() method testing.
567     */
568    public void testGetSigAlgName() {
569        assertEquals("Incorrect value of signature algorithm name",
570                algName, certificate.getSigAlgName());
571    }
572
573    /**
574     * getSigAlgOID() method testing.
575     */
576    public void testGetSigAlgOID() {
577        assertEquals("Incorrect value of signature algorithm OID",
578                algOID, certificate.getSigAlgOID());
579    }
580
581    /**
582     * getSigAlgParams() method testing.
583     */
584    public void testGetSigAlgParams() {
585        if (!Arrays.equals(algParams, certificate.getSigAlgParams())) {
586            fail("Incorrect Signature value.");
587        }
588    }
589
590    /**
591     * getIssuerUniqueID() method testing.
592     */
593    public void testGetIssuerUniqueID() {
594        if (!Arrays.equals(issuerUniqueID, certificate.getIssuerUniqueID())) {
595            fail("Incorrect issuerUniqueID value.");
596        }
597    }
598
599    /**
600     * getSubjectUniqueID() method testing.
601     */
602    public void testGetSubjectUniqueID() {
603        if (!Arrays.equals(subjectUniqueID, certificate.getSubjectUniqueID())) {
604            fail("Incorrect subjectUniqueID value.");
605        }
606    }
607
608    /**
609     * getKeyUsage() method testing.
610     */
611    public void testGetKeyUsage() {
612        boolean[] ku = certificate.getKeyUsage();
613        if ((ku == null) || (ku.length < extnKeyUsage.length)) {
614            fail("Incorrect Key Usage value.");
615        }
616        for (int i=0; i<extnKeyUsage.length; i++) {
617            if (extnKeyUsage[i] != ku[i]) {
618                fail("Incorrect Key Usage value.");
619            }
620        }
621    }
622
623    /**
624     * getExtendedKeyUsage() method testing.
625     */
626    public void testGetExtendedKeyUsage() throws Exception {
627        List exku = certificate.getExtendedKeyUsage();
628        if ((exku == null)
629                || (exku.size() != extnExtendedKeyUsage.size())) {
630            fail("Incorrect Extended Key Usage value.");
631        }
632        for (int i=0; i<extnExtendedKeyUsage.size(); i++) {
633            String ku = ObjectIdentifier
634                    .toString((int[]) extnExtendedKeyUsage.get(i));
635            if (!exku.contains(ku)) {
636                fail("Missing value:" + ku);
637            }
638        }
639    }
640
641    /**
642     * getBasicConstraints() method testing.
643     */
644    public void testGetBasicConstraints() {
645        assertEquals(extnBCLen, certificate.getBasicConstraints());
646    }
647
648    /**
649     * getSubjectAlternativeNames() method testing.
650     */
651    public void testGetSubjectAlternativeNames() {
652        try {
653            Collection certSans = certificate.getSubjectAlternativeNames();
654            if (certSans == null) {
655                fail("Returned value should not be null.");
656            }
657            List sans = extnSANames.getPairsList();
658            if (sans.size() != certSans.size()) {
659                fail("Size of returned collection does not match to the actual");
660            }
661            Iterator it = certSans.iterator();
662            while (it.hasNext()) {
663                List extnSan = (List) it.next();
664                Integer tag = (Integer) extnSan.get(0);
665                for (int i=0; i< sans.size(); i++) {
666                    List san = (List) sans.get(i);
667                    if (tag.equals(san.get(0))) {
668                        assertEquals(
669                                "Incorrect value of Subject Alternative Name",
670                                extnSan.get(1), san.get(1));
671                    }
672                }
673            }
674        } catch (CertificateParsingException e) {
675            fail("Subject Alternative Name extension was incorrectly encoded.");
676        }
677    }
678
679    /**
680     * getIssuerAlternativeNames() method testing.
681     */
682    public void testGetIssuerAlternativeNames() {
683        try {
684            Collection certIans = certificate.getIssuerAlternativeNames();
685            if (certIans == null) {
686                fail("Returned value should not be null.");
687            }
688            List ians = extnSANames.getPairsList();
689            if (ians.size() != certIans.size()) {
690                fail("Size of returned collection does not match to the actual");
691            }
692            Iterator it = certIans.iterator();
693            while (it.hasNext()) {
694                List extnIan = (List) it.next();
695                Integer tag = (Integer) extnIan.get(0);
696                for (int i=0; i< ians.size(); i++) {
697                    List ian = (List) ians.get(i);
698                    if (tag.equals(ian.get(0))) {
699                        assertEquals(
700                                "Incorrect value of Issuer Alternative Name",
701                                extnIan.get(1), ian.get(1));
702                    }
703                }
704            }
705        } catch (CertificateParsingException e) {
706            fail("Issuer Alternative Name extension was incorrectly encoded.");
707        }
708    }
709
710    /**
711     * getEncoded() method testing.
712     */
713    public void testGetEncoded() {
714        try {
715            if (!Arrays.equals(certEncoding, certificate.getEncoded())) {
716                fail("Incorrect encoding of Certificate.");
717            }
718        } catch (CertificateEncodingException e) {
719            fail("Unexpected CertificateEncodingException was thrown.");
720        }
721    }
722
723    /**
724     * getPublicKey() method testing.
725     */
726    public void testGetPublicKey() {
727        if (!Arrays.equals(keyEncoding, certificate.getPublicKey().getEncoded())) {
728            fail("Incorrect Public Key.");
729        }
730    }
731
732    /**
733     * getExtensionValue(String oid) method testing.
734     */
735    public void testGetExtensionValue() {
736        for (int i=0; i<extensions.length; i++) {
737            String id = extensions[i].getExtnID();
738            byte[] certExtnValue = certificate.getExtensionValue(id);
739            byte[] certExtnValue2Check = extensions[i].getRawExtnValue();
740                certificate.getExtensionValue(id);
741            if (!Arrays.equals(certExtnValue2Check, certExtnValue)) {
742                System.out.println("Extension encoding mismatch for "+id);
743                System.out.println("Expected:");
744                printAsHex(20, "", " ", certExtnValue2Check);
745                System.out.println("But has been got:");
746                if (certExtnValue == null) {
747                    System.out.println("null");
748                } else {
749                    printAsHex(20, "", " ", certExtnValue);
750                }
751                //fail("The values for extension "+id+" differ.");
752            }
753        }
754    }
755
756    /**
757     * getCriticalExtensionOIDs() method testing.
758     */
759    public void testGetCriticalExtensionOIDs() {
760        Set certCEOids = certificate.getCriticalExtensionOIDs();
761        if (!(certCEOids.containsAll(allCritical)
762                    && allCritical.containsAll(certCEOids))) {
763            fail("Incorrect value of Critical Extension OIDs");
764        }
765    }
766
767    /**
768     * getNonCriticalExtensionOIDs() method testing.
769     */
770    public void testGetNonCriticalExtensionOIDs() {
771        Set certNCEOids = certificate.getNonCriticalExtensionOIDs();
772        if (!(certNCEOids.containsAll(allNonCritical)
773                    && allNonCritical.containsAll(certNCEOids))) {
774            fail("Incorrect value of Non Critical Extension OIDs");
775        }
776    }
777
778    /**
779     * hasUnsupportedCriticalExtension() method testing.
780     */
781    public void testHasUnsupportedCriticalExtension() {
782        assertTrue("Incorrect value of hasUnsupportedCriticalExtension",
783                certificate.hasUnsupportedCriticalExtension());
784
785        if (!certificate.hasUnsupportedCriticalExtension()) {
786            fail("Incorrect value of hasUnsupportedCriticalExtension");
787        }
788    }
789
790    /**
791     * toString() method testing.
792     */
793    public void testToString() {
794        assertNotNull("String representation should not be null",
795                certificate.toString());
796    }
797
798    /**
799     * TODO
800     * verify(PublicKey key) method testing.
801     */
802    public void testVerify1() throws Exception {
803        certificate.verify(publicKey);
804    }
805
806    /**
807     * TODO
808     * verify(PublicKey key, String sigProvider) method testing.
809     */
810    public void testVerify2() throws Exception {
811        certificate.verify(publicKey,
812               Signature.getInstance("SHA1withDSA")
813                               .getProvider().getName());
814    }
815
816    /**
817     * TODO
818     * verify(PublicKey key) method testing.
819     */
820    public void testVerify3() throws Exception {
821        try {
822            certificate.verify(publicKey);
823            fail("Incorrect signature successfully verified.");
824        } catch (Exception e) {
825        }
826    }
827
828    public static Test suite() {
829        return new TestSuite(X509CertFactoryPerfTest.class);
830    }
831
832}
833