You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sm...@apache.org on 2006/06/06 06:49:58 UTC

svn commit: r412002 - in /incubator/harmony/enhanced/classlib/trunk/modules/security/src: main/java/common/org/apache/harmony/security/asn1/ main/java/common/org/apache/harmony/security/pkcs7/ main/java/common/org/apache/harmony/security/provider/cert/...

Author: smishura
Date: Mon Jun  5 21:49:57 2006
New Revision: 412002

URL: http://svn.apache.org/viewvc?rev=412002&view=rev
Log:
Apply patch for HARMONY-537 ([classlib] X.509 CertificateFactory implementation does not support PKCS7 Data)

Added:
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java   (with props)
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/BerInputStream.java
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/DerInputStream.java
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/pkcs7/SignedData.java
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
    incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertPathImpl.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/BerInputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/BerInputStream.java?rev=412002&r1=412001&r2=412002&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/BerInputStream.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/BerInputStream.java Mon Jun  5 21:49:57 2006
@@ -185,7 +185,7 @@
      * @return next decoded tag
      * @throws IOException - if error occured
      */
-    protected int next() throws IOException {
+    public int next() throws IOException {
 
         tagOffset = offset;
 

Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/DerInputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/DerInputStream.java?rev=412002&r1=412001&r2=412002&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/DerInputStream.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/asn1/DerInputStream.java Mon Jun  5 21:49:57 2006
@@ -48,7 +48,7 @@
     /**
      * @see org.apache.harmony.security.asn1.BerInputStream#next()
      */
-    protected final int next() throws IOException {
+    public final int next() throws IOException {
 
         int tag = super.next();
 

Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/pkcs7/SignedData.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/pkcs7/SignedData.java?rev=412002&r1=412001&r2=412002&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/pkcs7/SignedData.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/pkcs7/SignedData.java Mon Jun  5 21:49:57 2006
@@ -31,6 +31,7 @@
 import org.apache.harmony.security.asn1.BerInputStream;
 import org.apache.harmony.security.x509.AlgorithmIdentifier;
 import org.apache.harmony.security.x509.Certificate;
+import org.apache.harmony.security.x509.CertificateList;
 
 
 /**
@@ -73,6 +74,10 @@
         return certificates;
     }
 
+    public List getCRLs() {
+        return crls;
+    }
+
     public List getSignerInfos() {
         return signerInfos;
     }
@@ -105,7 +110,7 @@
             new ASN1SetOf(AlgorithmIdentifier.ASN1),
             ContentInfo.ASN1,
             new ASN1Implicit(0, new ASN1SetOf(Certificate.ASN1)),
-            new ASN1Implicit(1, new ASN1SetOf(ASN1Any.getInstance())),
+            new ASN1Implicit(1, new ASN1SetOf(CertificateList.ASN1)),
             new ASN1SetOf(SignerInfo.ASN1) 
 			}) {
         {
@@ -113,6 +118,16 @@
             setOptional(4); // crls is optional
         }
 
+        protected void getValues(Object object, Object[] values) {
+            SignedData sd = (SignedData) object;
+            values[0] = new byte[] {(byte)sd.version};
+            values[1] = sd.digestAlgorithms;
+            values[2] = sd.contentInfo;
+            values[3] = sd.certificates;
+            values[4] = sd.crls;
+            values[5] = sd.signerInfos;
+        }
+
         protected Object getDecodedObject(BerInputStream in) {
             Object[] values = (Object[]) in.content;
             return new SignedData(
@@ -126,4 +141,4 @@
         }
     };
 
-}
\ No newline at end of file
+}

Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java?rev=412002&r1=412001&r2=412002&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java Mon Jun  5 21:49:57 2006
@@ -37,7 +37,11 @@
 import java.util.List;
 
 import org.apache.harmony.luni.util.Base64;
+import org.apache.harmony.security.asn1.ASN1Constants;
 import org.apache.harmony.security.asn1.BerInputStream;
+import org.apache.harmony.security.pkcs7.ContentInfo;
+import org.apache.harmony.security.pkcs7.SignedData;
+import org.apache.harmony.security.x509.CertificateList;
 
 /**
  * X509 Certificate Factory Service Provider Interface Implementation.
@@ -95,64 +99,18 @@
             }
             // check whether the provided certificate is in PEM encoded form
             if ("-----BEGIN CERTIFICATE-----".equals(new String(buff, 0, 27))) {
-                // read PEM encoded form
-                int size = inStream.available();
-                if (size == 0) {
-                    size = 2048;
-                }
-                buff = new byte[size];
-                int index=0, ch;
-                // read the Base64 encoded certificate into the buffer
-                // expect "-----END CERTIFICATE-----" at the end
-                while ((ch = inStream.read()) != '-') {
-                    if (ch == -1) {
-                        throw new CertificateException(
-                                "Incorrect Base64 encoding: unexpected EOF.");
-                    }
-                    buff[index++] = (byte) ch;
-                    // enlarge the buffer if needed
-                    if (index == size) {
-                        byte[] newbuff = new byte[size+1024];
-                        System.arraycopy(buff, 0, newbuff, 0, size);
-                        buff = newbuff;
-                    }
-                }
-                byte[] tmp = new byte[25];
-                inStream.read(tmp);
-                // check the trailing sequence
-                if (!new String(tmp).startsWith("----END CERTIFICATE-----")) {
-                    throw new CertificateException(
-                    "Incorrect Base64 encoding: 'END CERTIFICATE' expected.");
-                }
-                // skip new line: set the position to the next certificate:
-                inStream.mark(1);
-                while (((ch = inStream.read()) != -1) 
-                        && (ch == '\n' || ch == '\r')) {
-                    inStream.mark(1);
-                }
-                inStream.reset();
-                // retrieve the ASN.1 DER encoded form
-                buff = Base64.decode(buff, index);
-                if (buff == null) {
-                    throw new CertificateException(
-                            "Incorrect Base64 encoding.");
-                }
-                // check whether certificate has already been generated and
-                // stored in the cache
-                long hash = CERT_CASHE.getHash(buff);
+                byte[] encoding = decodePEM(inStream, "CERTIFICATE");
+                
+                long hash = CERT_CASHE.getHash(encoding);
                 if (CERT_CASHE.contains(hash)) {
-                    // preliminary check is successful, do more accurate check
-                    Certificate res = (Certificate) CERT_CASHE.get(hash, buff);
+                    Certificate res = 
+                        (Certificate) CERT_CASHE.get(hash, encoding);
                     if (res != null) {
-                        // found in the cache
                         return res;
                     }
                 }
-                // there is no generated certificate in the cache,
-                // so generate it
-                Certificate res = new X509CertImpl(buff);
-                // put newly generated certificate in the cache
-                CERT_CASHE.put(hash, buff, res);
+                Certificate res = new X509CertImpl(encoding);
+                CERT_CASHE.put(hash, encoding, res);
                 return res;
             } else {
                 // read ASN.1 DER encoded form
@@ -207,13 +165,60 @@
                 // create the mark supporting wrapper
                 inStream = new RestoringInputStream(inStream);
             }
-            inStream.mark(1);
-            // until the end of the stream is not reached ..
-            while (inStream.read() != -1) {
+            boolean isPKCS7 = false;
+            boolean isPEM = false;
+            // check whether it is a PKCS7 structure
+            inStream.mark(33);
+            if (inStream.read() == '-') { // it is Base64 encoded form
+                // check the boundary delimiter
+                byte[] delimiter = new byte[20];
+                inStream.read(delimiter);
+                if (new String(delimiter).startsWith("----BEGIN PKCS7-----")) {
+                    // this is PEM encoded PKCS7 structure
+                    isPKCS7 = true;
+                    isPEM = true;
+                } else {
+                    inStream.reset();
+                }
+            } else {
+                // it is plain ASN.1 DER encoded form, 
+                // so reset the stream and check the structure
+                inStream.reset();
+                BerInputStream in = new BerInputStream(inStream);
+                if (in.next() == ASN1Constants.TAG_OID) { 
+                    // this is PKCS7 structure
+                    isPKCS7 = true;
+                }
                 inStream.reset();
-                // .. generate the certificate and add it to the resulting list
-                result.add(engineGenerateCertificate(inStream));
+            }
+            if (isPKCS7) {
+                ContentInfo info;
+                if (isPEM) {
+                    info = (ContentInfo) 
+                        ContentInfo.ASN1.decode(decodePEM(inStream, "PKCS7"));
+                } else {
+                    info = (ContentInfo) ContentInfo.ASN1.decode(inStream);
+                }
+                SignedData data = info.getSignedData();
+                if (data == null) {
+                    throw new CertificateException("Invalid PKCS7 data provided");
+                }
+                List certificates = data.getCertificates();
+                if (certificates != null) {
+                    for (int i = 0; i < certificates.size(); i++) {
+                        result.add(new X509CertImpl(
+                            (org.apache.harmony.security.x509.Certificate)
+                            certificates.get(i)));
+                    }
+                }
+                return result;
+            } else {
                 inStream.mark(1);
+                while (inStream.read() != -1) {
+                    inStream.reset();
+                    result.add(engineGenerateCertificate(inStream));
+                    inStream.mark(1);
+                }
             }
         } catch (IOException e) {
             throw new CertificateException(e);
@@ -243,52 +248,16 @@
             }
             // check whether the provided crl is in PEM encoded form
             if ("-----BEGIN X509 CRL-----".equals(new String(buff, 0, 24))) {
-                // read PEM encoded form
-                int size = inStream.available();
-                if (size == 0) {
-                    size = 1024;
-                }
-                buff = new byte[size];
-                int index=0, ch;
-                // read the Base64 encoded crl into the buffer
-                while ((ch = inStream.read()) != '-') {
-                    if (ch == -1) {
-                        throw new CRLException(
-                                "Incorrect Base64 encoding: unexpected EOF.");
-                    }
-                    buff[index++] = (byte) ch;
-                    // enlarge the buffer if needed
-                    if (index == size) {
-                        byte[] newbuff = new byte[size+1024];
-                        System.arraycopy(buff, 0, newbuff, 0, size);
-                        buff = newbuff;
-                    }
-                }
-                byte[] tmp = new byte[21];
-                inStream.read(tmp);
-                if (!new String(tmp).startsWith("----END X509 CRL-----")) {
-                    throw new CRLException(
-                    "Incorrect Base64 encoding: 'END X509 CRL' expected.");
-                }
-                // skip new line: set the position to the next certificate:
-                inStream.mark(1);
-                while (((ch = inStream.read()) != -1) && (ch == '\n' || ch == '\r')) {
-                    inStream.mark(1);
-                }
-                inStream.reset();
-                buff = Base64.decode(buff, index);
-                if (buff == null) {
-                    throw new CRLException("Incorrect Base64 encoding.");
-                }
-                long hash = CRL_CASHE.getHash(buff);
+                byte[] encoding = decodePEM(inStream, "X509 CRL");
+                long hash = CRL_CASHE.getHash(encoding);
                 if (CRL_CASHE.contains(hash)) {
-                    X509CRL res = (X509CRL) CRL_CASHE.get(hash, buff);
+                    X509CRL res = (X509CRL) CRL_CASHE.get(hash, encoding);
                     if (res != null) {
                         return res;
                     }
                 }
-                X509CRL res = new X509CRLImpl(buff);
-                CRL_CASHE.put(hash, buff, res);
+                X509CRL res = new X509CRLImpl(encoding);
+                CRL_CASHE.put(hash, encoding, res);
                 return res;
             } else {
                 inStream.reset();
@@ -329,15 +298,63 @@
             if (!inStream.markSupported()) {
                 inStream = new RestoringInputStream(inStream);
             }
-            inStream.mark(1);
-            // FIXME: Check if it is a PKCS7 structure, if not, do following:
-            while (inStream.read() != -1) {
+            boolean isPKCS7 = false;
+            boolean isPEM = false;
+            // check whether it is a PKCS7 structure
+            inStream.mark(33);
+            if (inStream.read() == '-') { // it is Base64 encoded form
+                // check the boundary delimiter
+                byte[] delimiter = new byte[20];
+                inStream.read(delimiter);
+                if (new String(delimiter).startsWith("----BEGIN PKCS7-----")) {
+                    // this is PEM encoded PKCS7 structure
+                    isPKCS7 = true;
+                    isPEM = true;
+                } else {
+                    inStream.reset();
+                }
+            } else {
+                // it is plain ASN.1 DER encoded form, 
+                // so reset the stream and check the structure
                 inStream.reset();
-                result.add(engineGenerateCRL(inStream));
+                BerInputStream in = new BerInputStream(inStream);
+                if (in.next() == ASN1Constants.TAG_OID) { 
+                    // this is PKCS7 structure
+                    isPKCS7 = true;
+                }
+                inStream.reset();
+            }
+            if (isPKCS7) {
+                // decode ContentInfo structure
+                ContentInfo info;
+                if (isPEM) {
+                    info = (ContentInfo) 
+                        ContentInfo.ASN1.decode(decodePEM(inStream, "PKCS7"));
+                } else {
+                    info = (ContentInfo) ContentInfo.ASN1.decode(inStream);
+                }
+                // retrieve SignedData
+                SignedData data = info.getSignedData();
+                if (data == null) {
+                    throw new CRLException("Invalid PKCS7 data provided");
+                }
+                List crls = data.getCRLs();
+                if (crls != null) {
+                    for (int i = 0; i < crls.size(); i++) {
+                        result.add(new X509CRLImpl(
+                            (CertificateList) crls.get(i)));
+                    }
+                }
+                return result;
+            } else {
                 inStream.mark(1);
+                while (inStream.read() != -1) {
+                    inStream.reset();
+                    result.add(engineGenerateCRL(inStream));
+                    inStream.mark(1);
+                }
             }
         } catch (IOException e) {
-            e.printStackTrace();
             throw new CRLException(e);
         }
         return result;
@@ -378,6 +395,53 @@
         return X509CertPathImpl.encodings.iterator();
     }
 
+    // Method retirieves the PEM encoded data from the stream 
+    // and returns its decoded representation.
+    // It is supposed that the data is bounded by
+    // "-----END" + boundary_mark + "-----" at the end.
+    private byte[] decodePEM(InputStream inStream, String boundary_mark) 
+                                                        throws IOException {
+        int size = 1024; // the size of the buffer containing Base64 data
+        byte[] buff = new byte[size];
+        int index=0, ch;
+        // read bytes while boundary delimiter is not reached
+        while ((ch = inStream.read()) != '-') {
+            if (ch == -1) {
+                throw new IOException(
+                        "Incorrect Base64 encoding: unexpected EOF.");
+            }
+            buff[index++] = (byte) ch;
+            if (index == size) {
+                // enlarge the buffer
+                byte[] newbuff = new byte[size+1024];
+                System.arraycopy(buff, 0, newbuff, 0, size);
+                buff = newbuff;
+                size += 1024;
+            }
+        }
+        // Check the boundary delimiter 
+        // one '-' has been already read
+        String boundary_delimiter = "----END " + boundary_mark + "-----";
+        byte[] tmp = new byte[boundary_delimiter.length()];
+        inStream.read(tmp);
+        if (!new String(tmp).startsWith(boundary_delimiter)) {
+            throw new IOException(
+                "Incorrect Base64 encoding: boundary delimiter expected '"
+                + boundary_delimiter + "'");
+        }
+        // skip trailing line breaks
+        inStream.mark(1);
+        while (((ch = inStream.read()) != -1) && (ch == '\n' || ch == '\r')) {
+            inStream.mark(1);
+        }
+        inStream.reset();
+        buff = Base64.decode(buff, index);
+        if (buff == null) {
+            throw new IOException("Incorrect Base64 encoding.");
+        }
+        return buff;
+    };
+    
     /*
      * This class extends any existing input stream with
      * mark functionality. It acts as a wrapper over the

Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertPathImpl.java?rev=412002&r1=412001&r2=412002&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertPathImpl.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertPathImpl.java Mon Jun  5 21:49:57 2006
@@ -176,7 +176,11 @@
                     // empty chain of certificates
                     certs = new ArrayList();
                 }
-                return new X509CertPathImpl(certs, PKCS7, ci.getEncoded());
+                List result = new ArrayList();
+                for (int i=0; i<certs.size(); i++) {
+                    result.add(new X509CertImpl((Certificate) certs.get(i)));
+                }
+                return new X509CertPathImpl(result, PKCS7, ci.getEncoded());
             }
         } catch (IOException e) {
             throw new CertificateException("Incorrect encoded form: "
@@ -229,7 +233,11 @@
                 if (certs == null) {
                     certs = new ArrayList();
                 }
-                return new X509CertPathImpl(certs, PKCS7, ci.getEncoded());
+                List result = new ArrayList();
+                for (int i=0; i<certs.size(); i++) {
+                    result.add(new X509CertImpl((Certificate) certs.get(i)));
+                }
+                return new X509CertPathImpl(result, PKCS7, ci.getEncoded());
             }
         } catch (IOException e) {
             throw new CertificateException("Incorrect encoded form: "

Added: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java?rev=412002&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java Mon Jun  5 21:49:57 2006
@@ -0,0 +1,222 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.tests.java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Collection;
+import java.util.Iterator;
+import org.apache.harmony.luni.util.Base64;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * X.509 CertificateFactory provider implementation test.<br>
+ * See RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt) for
+ * more information on X.509, and
+ * http://www.rsasecurity.com/rsalabs/node.asp?id=2129
+ * for more information on PKCS #7.
+ * The testing data was generated by use of classes from
+ * org.apache.harmony.security.x509 package.
+ */
+public class CertificateFactoryTest extends TestCase {
+
+    /**
+     * Base64 encoded PKCS7 SignedObject containing two X.509 CRLs.
+     */
+    private static String pkcs7so =
+          "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";
+
+    /**
+     * Base64 encoded Public Key for signature verification.
+     * Key corresponds to the CRLs and Certificates in PKCS7 SignedObject.
+     */
+    private static String b64PublicKeySpec =
+          "MIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2"
+        + "EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00"
+        + "b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue"
+        + "wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC"
+        + "ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0H"
+        + "gmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o"
+        + "4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKL"
+        + "Zl6Ae1UlZAFMO/7PSSoDgYUAAoGBAPBBWamz9YtVRtOOQz1/oJQMZzrN"
+        + "wjyol/b56lmw4eBFQDR4AqvX8LLhTKHTtTk3NLQOwmN/OjyShqaXBC5b"
+        + "2n6D8OkLKefffNBO5sGunXk5ncHY1x/bj+/54meIVQPsR4hV5eKCXq6K"
+        + "v/6XDTgo6O2bo2HPeeJA4slLBgbD9Lmn";
+
+    /**
+     * The name of the algorithm used for Certificate/CRL signing.
+     */
+    private static String publicKeyAlgorithm = "DSA";
+
+    /**
+     * The public key to verify generated Certificates and CRLs.
+     */
+    private static PublicKey publicKey;
+
+    static {
+        try {
+            X509EncodedKeySpec publicKeySpec =
+                new X509EncodedKeySpec(
+                        Base64.decode(b64PublicKeySpec.getBytes()));
+            KeyFactory keyFactory =
+                KeyFactory.getInstance(publicKeyAlgorithm);
+            publicKey = keyFactory.generatePublic(publicKeySpec);
+        } catch (NoSuchAlgorithmException e) {
+            // provider is not installed, will not verify the generated data
+            publicKey = null;
+        } catch (Exception e) {
+            // problems with a representation of the key
+            e.printStackTrace();
+            publicKey = null;
+        }
+    }
+
+    /**
+     * generateCRLs method testing.
+     */
+    public void testGenerateCRLs() throws Exception {
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+
+        // Testing the CRLs generation on the base of PKCS7 SignedData object
+        ByteArrayInputStream bais = new ByteArrayInputStream(
+                Base64.decode(pkcs7so.getBytes()));
+
+        Collection crls = factory.generateCRLs(bais);
+        assertNotNull("Factory returned null on correct PKCS7 data", crls);
+        assertEquals("The size of collection differs from expected",
+                2, crls.size());
+
+        if (publicKey != null) {
+            // verify the signatures
+            for (Iterator i = crls.iterator(); i.hasNext();) {
+                ((X509CRL) i.next()).verify(publicKey);
+            }
+        }
+    }
+
+    /**
+     * generateCertificates method testing.
+     */
+    public void testGenerateCertificates() throws Exception {
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+
+        // Testing the Certificates generation
+        // on the base of PKCS7 SignedData object
+        ByteArrayInputStream bais = new ByteArrayInputStream(
+                Base64.decode(pkcs7so.getBytes()));
+
+        Collection certs = factory.generateCertificates(bais);
+        assertNotNull("Factory returned null on correct PKCS7 data", certs);
+        assertEquals("The size of collection differs from expected",
+                2, certs.size());
+
+        if (publicKey != null) {
+            // verify the signatures
+            for (Iterator i = certs.iterator(); i.hasNext();) {
+                ((X509Certificate) i.next()).verify(publicKey);
+            }
+        }
+    }
+
+    /**
+     * generateCertificates method testing.
+     */
+    public void testGenerateCertPath() throws Exception {
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+
+        // Testing the CertPath generation
+        // on the base of PKCS7 SignedData object
+        ByteArrayInputStream bais = new ByteArrayInputStream(
+                Base64.decode(pkcs7so.getBytes()));
+
+        Collection certPath =
+            factory.generateCertPath(bais, "PKCS7").getCertificates();
+        assertEquals("The size of collection differs from expected",
+                2, certPath.size());
+
+        if (publicKey != null) {
+            // verify the signatures
+            for (Iterator i = certPath.iterator(); i.hasNext();) {
+                ((X509Certificate) i.next()).verify(publicKey);
+            }
+        }
+    }
+
+    public static Test suite() {
+        return new TestSuite(CertificateFactoryTest.class);
+    }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/cert/CertificateFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native