001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexander Y. Kleymenov
019: * @version $Revision$
020: */package org.apache.harmony.security.tests.provider.cert;
021:
022: import java.io.ByteArrayInputStream;
023: import java.io.IOException;
024: import java.math.BigInteger;
025: import java.security.KeyPair;
026: import java.security.KeyPairGenerator;
027: import java.security.PrivateKey;
028: import java.security.PublicKey;
029: import java.security.Signature;
030: import java.security.cert.CRLException;
031: import java.security.cert.CertificateFactory;
032: import java.util.Arrays;
033: import java.util.Date;
034: import java.util.List;
035: import java.util.Set;
036:
037: import javax.security.auth.x500.X500Principal;
038:
039: import junit.framework.Test;
040: import junit.framework.TestCase;
041: import junit.framework.TestSuite;
042:
043: import org.apache.harmony.security.provider.cert.X509CRLImpl;
044: import org.apache.harmony.security.provider.cert.X509CertImpl;
045: import org.apache.harmony.security.x501.Name;
046: import org.apache.harmony.security.x509.AlgorithmIdentifier;
047: import org.apache.harmony.security.x509.AuthorityKeyIdentifier;
048: import org.apache.harmony.security.x509.CRLNumber;
049: import org.apache.harmony.security.x509.Certificate;
050: import org.apache.harmony.security.x509.CertificateIssuer;
051: import org.apache.harmony.security.x509.CertificateList;
052: import org.apache.harmony.security.x509.DistributionPointName;
053: import org.apache.harmony.security.x509.Extension;
054: import org.apache.harmony.security.x509.Extensions;
055: import org.apache.harmony.security.x509.GeneralName;
056: import org.apache.harmony.security.x509.GeneralNames;
057: import org.apache.harmony.security.x509.InvalidityDate;
058: import org.apache.harmony.security.x509.IssuingDistributionPoint;
059: import org.apache.harmony.security.x509.ReasonCode;
060: import org.apache.harmony.security.x509.ReasonFlags;
061: import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
062: import org.apache.harmony.security.x509.TBSCertList;
063: import org.apache.harmony.security.x509.TBSCertificate;
064: import org.apache.harmony.security.x509.Validity;
065:
066: /**
067: * X509CRLImplTest
068: */
069: public class X509CRLImplTest extends TestCase {
070:
071: // Algorithm name and its OID (http://oid.elibel.tm.fr)
072: private static String algOID = "1.2.840.10040.4.3";
073: private static String algName = "SHA1withDSA";
074: // DER boolean false encoding (http://asn1.elibel.tm.fr)
075: // Makes no sense. For testing purposes we need just provide
076: // some ASN.1 structure:
077: private static byte[] algParams = { 1, 1, 0 };
078: private static AlgorithmIdentifier signature;
079: private static byte[] signatureValue;
080: static {
081: signature = new AlgorithmIdentifier(algOID, algParams);
082: }
083: private static String issuerName = "O=CRL Issuer";
084: private static String certIssuerName = "O=Certificate Issuer";
085:
086: private static BigInteger certSerialNumber1 = BigInteger
087: .valueOf(555);
088: private static BigInteger certSerialNumber2 = BigInteger
089: .valueOf(567);
090: private static BigInteger certSerialNumber3 = BigInteger
091: .valueOf(777);
092:
093: private static Date this Update = new Date();
094: private static Date nextUpdate;
095: static {
096: nextUpdate = new Date(this Update.getTime() + 100000);
097: }
098: private static Extensions crlEntryExtensions = new Extensions();
099: static {
100: // Reason Code
101: crlEntryExtensions.addExtension(new Extension("2.5.29.21",
102: Extension.NON_CRITICAL, new ReasonCode(
103: ReasonCode.KEY_COMPROMISE)));
104: // Invalidity Date Extension
105: crlEntryExtensions
106: .addExtension(new Extension("2.5.29.24",
107: Extension.NON_CRITICAL, new InvalidityDate(
108: new Date())));
109: // add the Certificate Issuer Extension to check if implementation
110: // support indirect CRLs. As says rfc 3280 (p.62):
111: // "If used by conforming CRL issuers, this extension MUST always be
112: // critical. If an implementation ignored this extension it could not
113: // correctly attribute CRL entries to certificates. This specification
114: // RECOMMENDS that implementations recognize this extension."
115: try {
116: crlEntryExtensions.addExtension(new Extension("2.5.29.29",
117: true, new CertificateIssuer(new GeneralName(
118: new Name(certIssuerName)))));
119: } catch (Exception e) {
120: e.printStackTrace();
121: }
122: }
123: private static Date revocationDate = new Date();
124: private static List revokedCertificates = Arrays
125: .asList(new TBSCertList.RevokedCertificate[] {
126: new TBSCertList.RevokedCertificate(
127: certSerialNumber1, revocationDate, null),
128: // the item for certificate issued by other authority
129: new TBSCertList.RevokedCertificate(
130: certSerialNumber2, revocationDate,
131: crlEntryExtensions),
132: new TBSCertList.RevokedCertificate(
133: certSerialNumber3, revocationDate, null), });
134: private static Extensions crlExtensions;
135: static {
136: try {
137: crlExtensions = new Extensions(
138: Arrays
139: .asList(new Extension[] {
140: // CRL Number Extension
141: new Extension("2.5.29.20",
142: Extension.NON_CRITICAL,
143: new CRLNumber(BigInteger
144: .valueOf(4444))),
145: // Authority Key Identifier
146: new Extension(
147: "2.5.29.35",
148: false,
149: new AuthorityKeyIdentifier(
150: // keyIdentifier (random value)
151: new byte[] { 1, 2,
152: 3, 4, 5 },
153: // authorityCertIssuer
154: new GeneralNames(
155: Arrays
156: .asList(new GeneralName[] { new GeneralName(
157: new Name(
158: certIssuerName)) })),
159: // authorityCertSerialNumber
160: certSerialNumber2)),
161: // Issuing Distribution Point
162: new Extension(
163: "2.5.29.28",
164: Extension.CRITICAL,
165: new IssuingDistributionPoint(
166: new DistributionPointName(
167: new GeneralNames(
168: Arrays
169: .asList(new GeneralName[] {
170: new GeneralName(
171: 1,
172: "rfc@822.Name"),
173: new GeneralName(
174: 2,
175: "dNSName"),
176: new GeneralName(
177: 4,
178: "O=Organization"),
179: new GeneralName(
180: 6,
181: "http://uniform.Resource.Id"),
182: new GeneralName(
183: 7,
184: "255.255.255.0"),
185: new GeneralName(
186: 8,
187: "1.2.3.4444.55555") }))),
188: new ReasonFlags(
189: new boolean[] {
190: true,
191: true,
192: false,
193: false,
194: true,
195: true }))), }));
196: } catch (Exception e) {
197: e.printStackTrace();
198: }
199: }
200:
201: // keys are using to make signature and to verify it
202: private static PublicKey publicKey;
203: private static PrivateKey privateKey;
204: private static byte[] signatureValueBytes;
205: static {
206: try {
207: KeyPairGenerator keyGen = KeyPairGenerator
208: .getInstance("DSA");
209: keyGen.initialize(1024);
210: KeyPair keyPair = keyGen.genKeyPair();
211: publicKey = keyPair.getPublic();
212: privateKey = keyPair.getPrivate();
213: } catch (Exception e) {
214: e.printStackTrace();
215: }
216: }
217:
218: private static X509CRLImpl crl;
219: private static CertificateList certificateList;
220: private static TBSCertList tbscertlist;
221: private static byte[] encoding;
222: private static byte[] tbsEncoding;
223: static CertificateFactory factory;
224:
225: static {
226: try {
227: Name issuer = new Name(issuerName);
228:
229: tbscertlist = new TBSCertList(2, signature, issuer,
230: this Update, nextUpdate, revokedCertificates,
231: crlExtensions);
232:
233: tbsEncoding = tbscertlist.getEncoded();
234:
235: try {
236: Signature sig = Signature.getInstance("DSA");
237: sig.initSign(privateKey);
238: sig.update(tbsEncoding, 0, tbsEncoding.length);
239: signatureValueBytes = sig.sign();
240: } catch (Exception e) {
241: e.printStackTrace();
242: fail("Unexpected exception was thrown: "
243: + e.getMessage());
244: }
245: factory = CertificateFactory.getInstance("X.509");
246: } catch (Exception e) {
247: e.printStackTrace();
248: fail("Unexpected Exception was thrown: " + e.getMessage());
249: }
250: }
251:
252: ByteArrayInputStream stream;
253:
254: protected void setUp() throws java.lang.Exception {
255: if ("testVerify3".equals(getName())) {
256: signatureValue = new byte[signatureValueBytes.length];
257: // make incorrect signature value:
258: System.arraycopy(signatureValueBytes, 0, signatureValue, 0,
259: signatureValueBytes.length);
260: signatureValue[20]++;
261: } else {
262: signatureValue = signatureValueBytes;
263: }
264: certificateList = new CertificateList(tbscertlist, signature,
265: signatureValue);
266:
267: encoding = CertificateList.ASN1.encode(certificateList);
268: stream = new ByteArrayInputStream(encoding);
269:
270: crl = new X509CRLImpl(certificateList);
271: }
272:
273: private static int XXX = 0, counter = 0;
274:
275: public void testCreationCRL() throws Exception {
276: byte[] stamp = new byte[10];
277: if ((++counter) % 10 != 0) {
278: XXX++;
279: }
280: byte tmp[] = BigInteger.valueOf(XXX).toByteArray();
281: System.arraycopy(tmp, 0, stamp, 0, tmp.length);
282: System.arraycopy(stamp, 0, encoding, encoding.length
283: - stamp.length, stamp.length);
284:
285: stream.reset();
286: java.security.cert.X509CRL c = (java.security.cert.X509CRL) factory
287: .generateCRL(stream);
288:
289: if (counter == 1) {
290: System.out.println("\nUSING: " + c.getClass());
291: }
292:
293: byte[] enc = c.getEncoded();
294: byte[] stamp_chek = new byte[stamp.length];
295:
296: System.arraycopy(enc, enc.length - stamp.length, stamp_chek, 0,
297: stamp.length);
298:
299: if (!Arrays.equals(stamp, stamp_chek)) {
300: fail("Wrong encoding received.");
301: }
302: }
303:
304: /**
305: * X509CRLImpl(CertificateList crl) method testing.
306: * Tested during setup.
307: */
308: public void testX509CRLImpl() {
309: try {
310: new X509CRLImpl((CertificateList) CertificateList.ASN1
311: .decode(encoding));
312: } catch (IOException e) {
313: fail("Unexpected exception was thrown");
314: }
315: }
316:
317: /**
318: * getEncoded() method testing.
319: */
320: public void testGetEncoded() {
321: try {
322: if (!Arrays.equals(encoding, crl.getEncoded())) {
323: fail("Incorrect encoding of CRL.");
324: }
325: } catch (CRLException e) {
326: fail("Unexpected CRLException was thrown.");
327: }
328: }
329:
330: /**
331: * getVersion() method testing.
332: */
333: public void testGetVersion() {
334: assertEquals("Incorrect version value", 2, crl.getVersion());
335: }
336:
337: /**
338: * getIssuerDN() method testing.
339: */
340: public void testGetIssuerDN() {
341: assertEquals("Incorrect issuer value", new X500Principal(
342: issuerName), crl.getIssuerDN());
343: }
344:
345: /**
346: * getIssuerX500Principal() method testing.
347: */
348: public void testGetIssuerX500Principal() {
349: assertEquals("Incorrect issuer value", new X500Principal(
350: issuerName), crl.getIssuerDN());
351: }
352:
353: /**
354: * getThisUpdate() method testing.
355: */
356: public void testGetThisUpdate() {
357: assertTrue("Incorrect thisUpdate value",
358: this Update.getTime() / 1000 == crl.getThisUpdate()
359: .getTime() / 1000);
360: }
361:
362: /**
363: * getNextUpdate() method testing.
364: */
365: public void testGetNextUpdate() {
366: assertTrue("Incorrect nextUpdate value",
367: nextUpdate.getTime() / 1000 == crl.getNextUpdate()
368: .getTime() / 1000);
369: }
370:
371: /**
372: * getRevokedCertificate(X509Certificate certificate) method testing.
373: */
374: public void testGetRevokedCertificate1() {
375: try {
376: X509CertImpl cert1 = new X509CertImpl(new Certificate(
377: new TBSCertificate(2, certSerialNumber1, signature,
378: new Name(certIssuerName), new Validity(
379: new Date(), new Date()), new Name(
380: certIssuerName),
381: new SubjectPublicKeyInfo(signature,
382: new byte[10]), null, null, null),
383: signature, new byte[10]));
384: X509CertImpl cert2 = new X509CertImpl(new Certificate(
385: new TBSCertificate(2, certSerialNumber2, signature,
386: new Name(certIssuerName), new Validity(
387: new Date(), new Date()), new Name(
388: certIssuerName),
389: new SubjectPublicKeyInfo(signature,
390: new byte[10]), null, null, null),
391: signature, new byte[10]));
392: X509CertImpl cert3 = new X509CertImpl(new Certificate(
393: new TBSCertificate(2, certSerialNumber3, signature,
394: new Name("O=Another Cert Issuer"),
395: new Validity(new Date(), new Date()),
396: new Name(certIssuerName),
397: new SubjectPublicKeyInfo(signature,
398: new byte[10]), null, null, null),
399: signature, new byte[10]));
400: assertNull("Certificate should not be presented in CRL "
401: + "because issuer is not the same as CRL issuer",
402: crl.getRevokedCertificate(cert1));
403: assertNotNull("Certificate should be presented in CRL", crl
404: .getRevokedCertificate(cert2));
405: assertNull("Certificate should not be presented in CRL "
406: + "because issuer is not the same as CRL issuer",
407: crl.getRevokedCertificate(cert3));
408: } catch (IOException e) {
409: // should never happen;
410: e.printStackTrace();
411: fail("Unexpected IOException was thrown:" + e.getMessage());
412: }
413: }
414:
415: /**
416: * getRevokedCertificate(BigInteger serialNumber) method testing.
417: */
418: public void testGetRevokedCertificate2() {
419: assertNotNull(
420: "The revoked certificate with the serial number '"
421: + certSerialNumber1
422: + "' should be presented in CRL.", crl
423: .getRevokedCertificate(certSerialNumber1));
424: assertNull("The revoked certificate with the serial number '"
425: + certSerialNumber2
426: + "' should not be presented in CRL.", crl
427: .getRevokedCertificate(certSerialNumber2));
428: assertNull("The revoked certificate with the serial number '"
429: + certSerialNumber3
430: + "' should not be presented in CRL.", crl
431: .getRevokedCertificate(certSerialNumber3));
432: }
433:
434: /**
435: * getRevokedCertificates() method testing.
436: */
437: public void testGetRevokedCertificates() {
438: Set rcerts = crl.getRevokedCertificates();
439: assertNotNull("The set should not be null", rcerts);
440: assertTrue("The size of returned set is incorrect", rcerts
441: .size() == revokedCertificates.size());
442: }
443:
444: /**
445: * getTBSCertList() method testing.
446: */
447: public void testGetTBSCertList() {
448: try {
449: assertTrue(
450: "Retrieved tbsCertList encoding does not equal to expected",
451: Arrays.equals(tbscertlist.getEncoded(), crl
452: .getTBSCertList()));
453: } catch (CRLException e) {
454: e.printStackTrace();
455: fail("Unexpected CRLException was thrown: "
456: + e.getMessage());
457: }
458: }
459:
460: /**
461: * getSignature() method testing.
462: */
463: public void testGetSignature() {
464: if (!Arrays.equals(signatureValueBytes, crl.getSignature())) {
465: fail("Incorrect Signature value.");
466: }
467: }
468:
469: /**
470: * getSigAlgName() method testing.
471: */
472: public void testGetSigAlgName() {
473: assertEquals("Incorrect value of signature algorithm name",
474: algName, crl.getSigAlgName());
475: }
476:
477: /**
478: * getSigAlgOID() method testing.
479: */
480: public void testGetSigAlgOID() {
481: assertEquals("Incorrect value of signature algorithm OID",
482: algOID, crl.getSigAlgOID());
483: }
484:
485: /**
486: * getSigAlgParams() method testing.
487: */
488: public void testGetSigAlgParams() {
489: if (!Arrays.equals(algParams, crl.getSigAlgParams())) {
490: fail("Incorrect SigAlgParams value.");
491: }
492: }
493:
494: /**
495: * verify(PublicKey key) method testing.
496: */
497: public void testVerify1() throws Exception {
498: crl.verify(publicKey);
499: }
500:
501: /**
502: * verify(PublicKey key, String sigProvider) method testing.
503: */
504: public void testVerify2() throws Exception {
505: crl.verify(publicKey, Signature.getInstance("SHA1withDSA")
506: .getProvider().getName());
507: }
508:
509: /**
510: * verify(PublicKey key) method testing.
511: */
512: public void testVerify3() throws Exception {
513: try {
514: crl.verify(publicKey);
515: fail("Incorrect signature successfully verified.");
516: } catch (Exception e) {
517: }
518: }
519:
520: /**
521: * isRevoked(Certificate cert) method testing.
522: */
523: public void testIsRevoked() {
524: try {
525: X509CertImpl cert1 = new X509CertImpl(new Certificate(
526: new TBSCertificate(2, certSerialNumber1, signature,
527: new Name(certIssuerName), new Validity(
528: new Date(), new Date()), new Name(
529: certIssuerName),
530: new SubjectPublicKeyInfo(signature,
531: new byte[10]), null, null, null),
532: signature, new byte[10]));
533: X509CertImpl cert2 = new X509CertImpl(new Certificate(
534: new TBSCertificate(2, certSerialNumber2, signature,
535: new Name(certIssuerName), new Validity(
536: new Date(), new Date()), new Name(
537: certIssuerName),
538: new SubjectPublicKeyInfo(signature,
539: new byte[10]), null, null, null),
540: signature, new byte[10]));
541: X509CertImpl cert3 = new X509CertImpl(new Certificate(
542: new TBSCertificate(2, certSerialNumber3, signature,
543: new Name("O=Another Cert Issuer"),
544: new Validity(new Date(), new Date()),
545: new Name(certIssuerName),
546: new SubjectPublicKeyInfo(signature,
547: new byte[10]), null, null, null),
548: signature, new byte[10]));
549: assertFalse("Certificate should not be presented in CRL "
550: + "because issuer is not the same as CRL issuer",
551: crl.isRevoked(cert1));
552: assertTrue("Certificate should be presented in CRL", crl
553: .isRevoked(cert2));
554: assertFalse("Certificate should not be presented in CRL "
555: + "because issuer is not the same as CRL issuer",
556: crl.isRevoked(cert3));
557: } catch (IOException e) {
558: // should never happen;
559: e.printStackTrace();
560: fail("Unexpected IOException was thrown:" + e.getMessage());
561: }
562: }
563:
564: /**
565: * toString() method testing.
566: */
567: public void testToString() {
568: assertNotNull("The string representation should not be null",
569: crl.toString());
570: }
571:
572: // the following implementations are tested in X509CertImplTest:
573:
574: /**
575: * getNonCriticalExtensionOIDs() method testing.
576: */
577: public void testGetNonCriticalExtensionOIDs() {
578: System.out.println("getNonCriticalExtensionOIDs: "
579: + crl.getNonCriticalExtensionOIDs());
580: }
581:
582: /**
583: * getCriticalExtensionOIDs() method testing.
584: */
585: public void testGetCriticalExtensionOIDs() {
586: System.out.println("getCriticalExtensionOIDs: "
587: + crl.getCriticalExtensionOIDs());
588: }
589:
590: /**
591: * getExtensionValue(String oid) method testing.
592: */
593: public void testGetExtensionValue() throws Exception {
594: assertNotNull(crl.getExtensionValue("2.5.29.20"));
595: assertNull("Null value should be returned in the case of "
596: + "nonexisting extension", crl
597: .getExtensionValue("1.1.1.1"));
598: }
599:
600: /**
601: * hasUnsupportedCriticalExtension() method testing.
602: */
603: public void testHasUnsupportedCriticalExtension() {
604: System.out.println("hasUnsupportedCriticalExtension: "
605: + crl.hasUnsupportedCriticalExtension());
606: }
607:
608: public static Test suite() {
609: return new TestSuite(X509CRLImplTest.class);
610: }
611:
612: public static void main(String[] args) throws Exception {
613: /*
614: X509CRLImplTest test = new X509CRLImplTest();
615: test.setUp();
616: long startTime = System.currentTimeMillis();
617: for (int i=0; i<100000; i++) {
618: test.testCreationCRL();
619: }
620: System.out.println("time: "+(System.currentTimeMillis() - startTime));
621: /*/
622: junit.textui.TestRunner.run(suite());
623: }
624: }
|