changeset 1538:f422cf3f7cc8

8048357: PKCS basic tests Reviewed-by: coffeys Contributed-by: artem.kosarev@oracle.com
author alexp
date Tue, 20 Dec 2016 03:24:31 +0000
parents 92f45941d640
children db12cca58eea
files test/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java test/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java test/sun/security/pkcs/pkcs7/SignerOrder.java test/sun/security/pkcs/pkcs7/jarsigner/META-INF/MANIFEST.MF test/sun/security/pkcs/pkcs7/jarsigner/META-INF/PKCS7TEST.DSA.base64 test/sun/security/pkcs/pkcs7/jarsigner/META-INF/PKCS7TEST.SF test/sun/security/pkcs/pkcs8/PKCS8Test.java
diffstat 8 files changed, 1178 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8048357
+ * @summary test DER encoding of PKCS10 attributes
+ * @compile -XDignore.symbol.file PKCS10AttrEncoding.java
+ * @run main PKCS10AttrEncoding
+ */
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.util.Enumeration;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import sun.security.pkcs.PKCS9Attribute;
+import sun.security.pkcs10.PKCS10;
+import sun.security.pkcs10.PKCS10Attribute;
+import sun.security.pkcs10.PKCS10Attributes;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.X500Name;
+import sun.security.x509.X509Key;
+import sun.security.x509.X500Signer;
+
+public class PKCS10AttrEncoding {
+
+    static final ObjectIdentifier[] ids = {
+        PKCS9Attribute.CONTENT_TYPE_OID, // ContentType
+        PKCS9Attribute.SIGNING_TIME_OID, // SigningTime
+        PKCS9Attribute.CHALLENGE_PASSWORD_OID // ChallengePassword
+    };
+    static int failedCount = 0;
+    static HashMap<ObjectIdentifier, Object> constructedMap = new HashMap<ObjectIdentifier, Object>();
+
+    public static void main(String[] args) throws Exception {
+
+        // initializations
+        int len = ids.length;
+        Object[] values = {
+            new ObjectIdentifier("1.2.3.4"),
+            new GregorianCalendar(1970, 1, 25, 8, 56, 7).getTime(),
+            "challenging"
+        };
+        for (int j = 0; j < len; j++) {
+            constructedMap.put(ids[j], values[j]);
+        }
+
+        X500Name subject = new X500Name("cn=Test");
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
+        String sigAlg = "DSA";
+
+        keyGen.initialize(512);
+
+        KeyPair pair = keyGen.generateKeyPair();
+        X509Key publicKey = (X509Key) pair.getPublic();
+        PrivateKey privateKey = pair.getPrivate();
+
+        Signature signature = Signature.getInstance(sigAlg);
+        signature.initSign(privateKey);
+
+        // Create the PKCS10 request
+        PKCS10Attribute[] attrs = new PKCS10Attribute[len];
+        for (int j = 0; j < len; j++) {
+            attrs[j] = new PKCS10Attribute(ids[j], values[j]);
+        }
+        PKCS10 req = new PKCS10(publicKey, new PKCS10Attributes(attrs));
+        System.out.println("List of attributes in constructed PKCS10 "
+                + "request: ");
+        checkAttributes(req.getAttributes().getElements());
+
+        // Encode the PKCS10 request and generate another PKCS10 request from
+        // the encoded byte array
+        req.encodeAndSign(new X500Signer(signature, subject));
+        PKCS10 resp = new PKCS10(req.getEncoded());
+        System.out.println("List of attributes in DER encoded PKCS10 Request:");
+        checkAttributes(resp.getAttributes().getElements());
+
+        if (failedCount > 0) {
+            throw new RuntimeException("Attributes Compared : Failed");
+        }
+        System.out.println("Attributes Compared : Pass");
+    }
+
+    static void checkAttributes(Enumeration attrs) {
+        int numOfAttrs = 0;
+        while (attrs.hasMoreElements()) {
+            numOfAttrs ++;
+            PKCS10Attribute attr = (PKCS10Attribute) attrs.nextElement();
+
+            if (constructedMap.containsKey(attr.getAttributeId())) {
+                if (constructedMap.get(attr.getAttributeId()).
+                        equals(attr.getAttributeValue())) {
+                    System.out.print("AttributeId: " + attr.getAttributeId());
+                    System.out.println(" AttributeValue: "
+                            + attr.getAttributeValue());
+                } else {
+                    failedCount++;
+                    System.out.print("< AttributeId: " + attr.getAttributeId());
+                    System.out.println("  AttributeValue: " + constructedMap.
+                            get(attr.getAttributeId()));
+                    System.out.print("< AttributeId: " + attr.getAttributeId());
+                    System.out.println("  AttributeValue: "
+                            + attr.getAttributeValue());
+                }
+            } else {
+                failedCount++;
+                System.out.println("No " + attr.getAttributeId()
+                        + " in DER encoded PKCS10 Request");
+            }
+        }
+        if(numOfAttrs != constructedMap.size()){
+            failedCount++;
+            System.out.println("Incorrect number of attributes.");
+
+        }
+        System.out.println();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8048357
+ * @summary Read in a file containing a DER encoded PKCS10 certificate request,
+ * flanked with "begin" and "end" lines.
+ * @compile -XDignore.symbol.file PKCS10AttributeReader.java
+ * @run main PKCS10AttributeReader
+ */
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Date;
+import sun.misc.BASE64Decoder;
+import sun.security.pkcs.PKCS9Attribute;
+import sun.security.pkcs10.PKCS10Attribute;
+import sun.security.pkcs10.PKCS10Attributes;
+import sun.security.util.DerInputStream;
+import sun.security.util.ObjectIdentifier;
+
+/*
+ Tests only reads DER encoding files, contents of corresponding asn.1 files
+ are copied below for reference.
+
+ # An attribute set for testing with PKCS10.
+
+ {A0  # implicit tag
+    {SEQ  # Content Type
+        {OID 1.2.840.113549.1.9.3}
+        {SET
+            {OID "1234"}
+        }
+    }
+     {SEQ  # Challenge Password
+         {OID 1.2.840.113549.1.9.7}
+         {SET
+             {T61String "GuessWhoAmI"}
+         }
+     }
+     {SEQ  # Signing Time
+        {OID 1.2.840.113549.1.9.5}
+        {SET
+            {UTCTime "970422145010Z"}
+        }
+     }
+ }
+ */
+public class PKCS10AttributeReader {
+    // DER encoded files are binary files, to avoid attaching binary files,
+    // DER files were encoded in base64
+    static final String ATTRIBS = "oE8wEwYJKoZIhvcNAQkDMQYGBDEyMzQwGgYJKoZIhv"
+            + "cNAQkHMQ0UC0d1ZXNzV2hv\nQW1JMBwGCSqGSIb3DQEJBTEPFw05NzA0MjIxND"
+            + "UwMTBa";
+
+    public static void main(String[] args) throws Exception {
+
+        // Decode base64 encoded DER file
+        byte[] pkcs10Bytes = new BASE64Decoder().decodeBuffer(ATTRIBS);
+
+        HashMap<ObjectIdentifier, Object> RequestStander = new HashMap<ObjectIdentifier, Object>() {
+            {
+                put(PKCS9Attribute.CHALLENGE_PASSWORD_OID, "GuessWhoAmI");
+                put(PKCS9Attribute.SIGNING_TIME_OID, new Date(861720610000L));
+                put(PKCS9Attribute.CONTENT_TYPE_OID,
+                        new ObjectIdentifier("1.9.50.51.52"));
+            }
+        };
+
+        int invalidNum = 0;
+        PKCS10Attributes resp = new PKCS10Attributes(
+                new DerInputStream(pkcs10Bytes));
+        Enumeration<PKCS10Attribute> eReq = resp.getElements();
+        int numOfAttrs = 0;
+        while (eReq.hasMoreElements()) {
+            numOfAttrs++;
+            PKCS10Attribute attr = eReq.nextElement();
+            if (RequestStander.containsKey(attr.getAttributeId())) {
+                if (RequestStander.get(attr.getAttributeId())
+                        .equals(attr.getAttributeValue())) {
+                    System.out.println(attr.getAttributeId() + " "
+                            + attr.getAttributeValue());
+                } else {
+                    invalidNum++;
+                    System.out.println("< " + attr.getAttributeId() + " "
+                            + attr.getAttributeValue());
+                    System.out.println("< " + attr.getAttributeId() + " "
+                            + RequestStander.get(attr.getAttributeId()));
+                }
+            } else {
+                invalidNum++;
+                System.out.println("No" + attr.getAttributeId()
+                        + "in Certificate Request list");
+            }
+        }
+        if (numOfAttrs != RequestStander.size()) {
+            invalidNum++;
+            System.out.println("Incorrect number of attributes.");
+        }
+        System.out.println();
+        if (invalidNum > 0) {
+            throw new RuntimeException(
+                    "Attributes Compared with Stander :" + " Failed");
+        }
+        System.out.println("Attributes Compared with Stander: Pass");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8048357
+ * @summary Read signed data in one or more PKCS7 objects from individual files,
+ * verify SignerInfos and certificate chain.
+ * @run main PKCS7VerifyTest PKCS7TEST.DSA.base64
+ * @run main PKCS7VerifyTest PKCS7TEST.DSA.base64 PKCS7TEST.SF
+ */
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import sun.misc.BASE64Decoder;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+
+public class PKCS7VerifyTest {
+
+    static final String TESTSRC = System.getProperty("test.src", ".");
+    static final String FS = File.separator;
+    static final String FILEPATH = TESTSRC + FS + "jarsigner" + FS + "META-INF"
+            + FS;
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            throw new RuntimeException("usage: java JarVerify <file1> <file2>");
+        }
+
+        // The command " java PKCS7VerifyTest file1 [file2] "
+        // treats file1 as containing the DER encoding of a PKCS7 signed data
+        // object. If file2 is absent, the program verifies that some signature
+        // (SignerInfo) file1 correctly signs the data contained in the
+        // ContentInfo component of the PKCS7 object encoded by file1. If file2
+        // is present, the program verifies file1 contains a correct signature
+        // for the contents of file2.
+
+        PKCS7 pkcs7;
+        byte[] data;
+
+        // to avoid attaching binary DSA file, the DSA file was encoded
+        // in Base64, decode encoded Base64 DSA file below
+        FileInputStream fis = null;
+        try {
+            fis = new FileInputStream(new File(FILEPATH, args[0]));
+            pkcs7 = new PKCS7(new ByteArrayInputStream(
+                new BASE64Decoder().decodeBuffer(fis)));
+            fis.close();
+            if (args.length < 2) {
+                data = null;
+            } else {
+                File file = new File(FILEPATH, args[1]);
+                // Array has to be exact size of input file
+                int length = (int) file.length();
+                data = new byte[length];
+                fis = new FileInputStream(file);
+                fis.read(data);
+            }
+        } finally {
+            if (fis != null) { fis.close(); }
+        }
+
+        SignerInfo[] signerInfos = pkcs7.verify(data);
+
+        if (signerInfos == null) {
+            throw new RuntimeException("no signers verify");
+        }
+        System.out.println("Verifying SignerInfos:");
+        for (SignerInfo signerInfo : signerInfos) {
+            System.out.println(signerInfo.toString());
+        }
+
+        X509Certificate certs[] = pkcs7.getCertificates();
+
+        HashMap<String, X509Certificate> certTable = new HashMap<String, X509Certificate>(certs.length);
+        for (X509Certificate cert : certs) {
+            certTable.put(cert.getSubjectDN().toString(), cert);
+        }
+
+        // try to verify all the certs
+        for (Map.Entry<String, X509Certificate> entry : certTable.entrySet()) {
+
+            X509Certificate cert = entry.getValue();
+            X509Certificate issuerCert = certTable
+                    .get(cert.getIssuerDN().toString());
+
+            System.out.println("Subject: " + cert.getSubjectDN());
+            if (issuerCert == null) {
+                System.out.println("Issuer certificate not found");
+            } else {
+                System.out.println("Issuer:  " + cert.getIssuerDN());
+                cert.verify(issuerCert.getPublicKey());
+                System.out.println("Cert verifies.");
+            }
+            System.out.println();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs7/SignerOrder.java	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8048357
+ * @summary test PKCS7 data signing, encoding and verification
+ * @run main SignerOrder
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import sun.misc.HexDumpEncoder;
+import sun.security.pkcs.ContentInfo;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.util.DerOutputStream;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.CertificateAlgorithmId;
+import sun.security.x509.CertificateIssuerName;
+import sun.security.x509.CertificateSerialNumber;
+import sun.security.x509.CertificateSubjectName;
+import sun.security.x509.CertificateValidity;
+import sun.security.x509.CertificateVersion;
+import sun.security.x509.CertificateX509Key;
+import sun.security.x509.X500Name;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CertInfo;
+import sun.security.x509.X509Key;
+
+public class SignerOrder {
+
+    static final HexDumpEncoder hexDump = new HexDumpEncoder();
+
+    //signer infos
+    static final byte[] data1 = "12345".getBytes();
+    static final byte[] data2 = "abcde".getBytes();
+
+    public static void main(String[] argv) throws Exception {
+
+        SignerInfo[] signerInfos = new SignerInfo[9];
+        SimpleSigner signer1 = new SimpleSigner(null, null, null, null);
+        signerInfos[8] = signer1.genSignerInfo(data1);
+        signerInfos[7] = signer1.genSignerInfo(new byte[]{});
+        signerInfos[6] = signer1.genSignerInfo(data2);
+
+        SimpleSigner signer2 = new SimpleSigner(null, null, null, null);
+        signerInfos[5] = signer2.genSignerInfo(data1);
+        signerInfos[4] = signer2.genSignerInfo(new byte[]{});
+        signerInfos[3] = signer2.genSignerInfo(data2);
+
+        SimpleSigner signer3 = new SimpleSigner(null, null, null, null);
+        signerInfos[2] = signer3.genSignerInfo(data1);
+        signerInfos[1] = signer3.genSignerInfo(new byte[]{});
+        signerInfos[0] = signer3.genSignerInfo(data2);
+
+        ContentInfo contentInfo = new ContentInfo(data1);
+
+        AlgorithmId[] algIds = {new AlgorithmId(AlgorithmId.SHA256_oid)};
+
+        X509Certificate[] certs = {signer3.getCert(), signer2.getCert(),
+            signer1.getCert()};
+
+        PKCS7 pkcs71 = new PKCS7(algIds, contentInfo,
+                certs,
+                signerInfos);
+
+        System.out.println("SignerInfos in original.");
+        printSignerInfos(pkcs71.getSignerInfos());
+
+        DerOutputStream out = new DerOutputStream();
+        pkcs71.encodeSignedData(out);
+
+        PKCS7 pkcs72 = new PKCS7(out.toByteArray());
+        System.out.println("\nSignerInfos read back in:");
+        printSignerInfos(pkcs72.getSignerInfos());
+
+        System.out.println("Verified signers of original:");
+        SignerInfo[] verifs1 = pkcs71.verify();
+
+        System.out.println("Verified signers of after read-in:");
+        SignerInfo[] verifs2 = pkcs72.verify();
+
+        if (verifs1.length != verifs2.length) {
+            throw new RuntimeException("Length or Original vs read-in "
+                    + "should be same");
+        }
+    }
+
+    static void printSignerInfos(SignerInfo signerInfo) throws IOException {
+        ByteArrayOutputStream strm = new ByteArrayOutputStream();
+        signerInfo.derEncode(strm);
+        System.out.println("SignerInfo, length: "
+                + strm.toByteArray().length);
+        System.out.println(hexDump.encode(strm.toByteArray()));
+        System.out.println("\n");
+        strm.reset();
+    }
+
+    static void printSignerInfos(SignerInfo[] signerInfos) throws IOException {
+        ByteArrayOutputStream strm = new ByteArrayOutputStream();
+        for (int i = 0; i < signerInfos.length; i++) {
+            signerInfos[i].derEncode(strm);
+            System.out.println("SignerInfo[" + i + "], length: "
+                    + strm.toByteArray().length);
+            System.out.println(hexDump.encode(strm.toByteArray()));
+            System.out.println("\n");
+            strm.reset();
+        }
+    }
+
+}
+
+/**
+ * A simple extension of sun.security.x509.X500Signer that adds a no-fuss
+ * signing algorithm.
+ */
+class SimpleSigner {
+
+    private final Signature sig;
+    private final X500Name agent;
+    private final AlgorithmId digestAlgId;
+    private final AlgorithmId encryptionAlgId;
+    private final AlgorithmId algId; // signature algid;
+                                     //combines digest + encryption
+    private final X509Key publicKey;
+    private final PrivateKey privateKey;
+    private final X509Certificate cert;
+
+    public SimpleSigner(String digestAlg,
+            String encryptionAlg,
+            KeyPair keyPair,
+            X500Name agent) throws Exception {
+
+        if (agent == null) {
+            agent = new X500Name("cn=test");
+        }
+        if (digestAlg == null) {
+            digestAlg = "SHA";
+        }
+        if (encryptionAlg == null) {
+            encryptionAlg = "DSA";
+        }
+        if (keyPair == null) {
+            KeyPairGenerator keyGen =
+                    KeyPairGenerator.getInstance(encryptionAlg);
+            keyGen.initialize(1024);
+            keyPair = keyGen.generateKeyPair();
+        }
+        publicKey = (X509Key) keyPair.getPublic();
+        privateKey = keyPair.getPrivate();
+
+        if ("DSA".equals(encryptionAlg)) {
+            this.sig = Signature.getInstance(encryptionAlg);
+        } else { // RSA
+            this.sig = Signature.getInstance(digestAlg + "/" + encryptionAlg);
+        }
+        this.sig.initSign(privateKey);
+
+        this.agent = agent;
+        this.digestAlgId = AlgorithmId.get(digestAlg);
+        this.encryptionAlgId = AlgorithmId.get(encryptionAlg);
+        this.algId = AlgorithmId.get(this.sig.getAlgorithm());
+
+        this.cert = getSelfCert();
+    }
+
+    /**
+     * Take the data and sign it.
+     *
+     * @param buf buffer holding the next chunk of the data to be signed
+     * @param offset starting point of to-be-signed data
+     * @param len how many bytes of data are to be signed
+     * @return the signature for the input data.
+     * @exception SignatureException on errors.
+     */
+    public byte[] simpleSign(byte[] buf, int offset, int len)
+            throws SignatureException {
+        sig.update(buf, offset, len);
+        return sig.sign();
+    }
+
+    /**
+     * Returns the digest algorithm used to sign.
+     */
+    public AlgorithmId getDigestAlgId() {
+        return digestAlgId;
+    }
+
+    /**
+     * Returns the encryption algorithm used to sign.
+     */
+    public AlgorithmId getEncryptionAlgId() {
+        return encryptionAlgId;
+    }
+
+    /**
+     * Returns the name of the signing agent.
+     */
+    public X500Name getSigner() {
+        return agent;
+    }
+
+    public X509Certificate getCert() {
+        return cert;
+    }
+
+    private X509Certificate getSelfCert() throws Exception {
+        long validity = 1000;
+        X509CertImpl certLocal;
+        Date firstDate, lastDate;
+
+        firstDate = new Date();
+        lastDate = new Date();
+        lastDate.setTime(lastDate.getTime() + validity + 1000);
+
+        CertificateValidity interval = new CertificateValidity(firstDate,
+                lastDate);
+
+        X509CertInfo info = new X509CertInfo();
+        // Add all mandatory attributes
+        info.set(X509CertInfo.VERSION,
+                new CertificateVersion(CertificateVersion.V1));
+        info.set(X509CertInfo.SERIAL_NUMBER,
+                new CertificateSerialNumber(
+                        (int) (firstDate.getTime() / 1000)));
+        info.set(X509CertInfo.ALGORITHM_ID,
+                new CertificateAlgorithmId(algId));
+        info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(agent));
+        info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
+        info.set(X509CertInfo.VALIDITY, interval);
+        info.set(X509CertInfo.ISSUER, new CertificateIssuerName(agent));
+
+        certLocal = new X509CertImpl(info);
+        certLocal.sign(privateKey, algId.getName());
+
+        return certLocal;
+    }
+
+    public SignerInfo genSignerInfo(byte[] data) throws SignatureException {
+        return new SignerInfo((X500Name) cert.getIssuerDN(),
+                new BigInteger("" + cert.getSerialNumber()),
+                getDigestAlgId(), algId,
+                simpleSign(data, 0, data.length));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs7/jarsigner/META-INF/MANIFEST.MF	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,82 @@
+Manifest-Version: 1.0
+
+Name: CheckCerts.class
+Digest-Algorithms: SHA
+SHA-Digest: xLygljhRro6990piIVEilVI8szQ=
+
+Name: ContentInfoTest.class
+Digest-Algorithms: SHA
+SHA-Digest: TSVdEMQW2gdFi6qeba+UixdHSdo=
+
+Name: JarVerify.class
+Digest-Algorithms: SHA
+SHA-Digest: Wg+PiDzunNGH4KrWAp00/okp39s=
+
+Name: JarVerify2.class
+Digest-Algorithms: SHA
+SHA-Digest: 5uYBQxwGWgYmNBwhnWRbymeXmWM=
+
+Name: PKCS7Read.class
+Digest-Algorithms: SHA
+SHA-Digest: JPIxttHBfRpQaFyiQJ2Wfkvj/ls=
+
+Name: PKCS7Test.class
+Digest-Algorithms: SHA
+SHA-Digest: R64SXXgZrOvGiO/eMsfG/T1Vn30=
+
+Name: PKCS7Test10.class
+Digest-Algorithms: SHA
+SHA-Digest: 2R0yxuxRHTPqdAzJJcrvqkpbQgo=
+
+Name: PKCS7Test11.class
+Digest-Algorithms: SHA
+SHA-Digest: /0HcwnpQi0hwJsJtvt5peWFGvtc=
+
+Name: PKCS7Test12.class
+Digest-Algorithms: SHA
+SHA-Digest: s5CcqimfRqR9CW25tFBY0JK3RVU=
+
+Name: PKCS7Test2.class
+Digest-Algorithms: SHA
+SHA-Digest: 71VkFEMUle5sjXNFbSW31F1ZJ58=
+
+Name: PKCS7Test3.class
+Digest-Algorithms: SHA
+SHA-Digest: mU/D5C6SgPRmwoLQzwF5VnN3aqM=
+
+Name: PKCS7Test4.class
+Digest-Algorithms: SHA
+SHA-Digest: ss9NFvxF8emaEjdKdvtzWXfs0/E=
+
+Name: PKCS7Test5.class
+Digest-Algorithms: SHA
+SHA-Digest: DHvQ20UAXoYgfCPAOeCOrglsJwU=
+
+Name: PKCS7Test6.class
+Digest-Algorithms: SHA
+SHA-Digest: aiCb8chroH7XDaNfAz6wr57lXsA=
+
+Name: PKCS7Test7.class
+Digest-Algorithms: SHA
+SHA-Digest: UoieXLC68alFgfD/Q1NW9/r2kaY=
+
+Name: PKCS7Test8.class
+Digest-Algorithms: SHA
+SHA-Digest: eMW7mq5b/KVB1M5L76wcV1+uFQs=
+
+Name: PKCS7Test9.class
+Digest-Algorithms: SHA
+SHA-Digest: EEWCZG1creWjqVZVIEgr0on3y6A=
+
+Name: SignerInfoTest.class
+Digest-Algorithms: SHA
+SHA-Digest: l6SNfpnFipGg8gy4XqY3HhA0RrY=
+
+Name: SignerInfoTest2.class
+Digest-Algorithms: SHA
+SHA-Digest: 5jbzlkZqXKNmmmE+pcjQka8D6WE=
+
+Name: SimpleSigner.class
+Digest-Algorithms: SHA
+SHA-Digest: l9ODQHY4wxhIvLw4/B0qe9NjwxQ=
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs7/jarsigner/META-INF/PKCS7TEST.DSA.base64	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,60 @@
+MIILKAYJKoZIhvcNAQcCoIILGTCCCxUCAQExCzAJBgUrDgMCGgUAMIIHbQYJKoZI
+hvcNAQcBoIIHXgSCB1pTaWduYXR1cmUtVmVyc2lvbjogMS4wDQoNCk5hbWU6IENo
+ZWNrQ2VydHMuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdl
+c3Q6IHlhMXh3dnNRTytEUnBRYnczRmgyblJCMkpRYz0NCg0KTmFtZTogQ29udGVu
+dEluZm9UZXN0LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGln
+ZXN0OiBDYStFSmFrVTZ6dzRLQWhvcWNuQ3BOcWsyTEk9DQoNCk5hbWU6IEphclZl
+cmlmeS5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDog
+K0RHYVdXa25md2U0Wk9wc29NVEZ6ZldSdmhRPQ0KDQpOYW1lOiBKYXJWZXJpZnky
+LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiBHcUR6
+WXlZNFAvV0g1SEt2aVdxWHR0UGc1ckU9DQoNCk5hbWU6IFBLQ1M3UmVhZC5jbGFz
+cw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogUW1mOEs5aFhW
+bHdJZFBZNm52MmpGUGZHcWtBPQ0KDQpOYW1lOiBQS0NTN1Rlc3QuY2xhc3MNCkRp
+Z2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IEdiZS9nenl2MkY1OGY2
+RUVoU1oxQnFHWHRsbz0NCg0KTmFtZTogUEtDUzdUZXN0MTAuY2xhc3MNCkRpZ2Vz
+dC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IDh3QnFXLy9lVzJzTlJJOTFi
+TFlFT29kY2dhRT0NCg0KTmFtZTogUEtDUzdUZXN0MTEuY2xhc3MNCkRpZ2VzdC1B
+bGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IGJYaExLRXNsY3VFWGk0dS9haGdU
+MnE2dGNFVT0NCg0KTmFtZTogUEtDUzdUZXN0MTIuY2xhc3MNCkRpZ2VzdC1BbGdv
+cml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IDlLRVkxYjUyUUxtTjBxei81ejB3QkZy
+T216MD0NCg0KTmFtZTogUEtDUzdUZXN0Mi5jbGFzcw0KRGlnZXN0LUFsZ29yaXRo
+bXM6IFNIQQ0KU0hBLURpZ2VzdDogK1VhMzIvMlE4RjJiclFRbVNYWCtYUytNL2g0
+PQ0KDQpOYW1lOiBQS0NTN1Rlc3QzLmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczog
+U0hBDQpTSEEtRGlnZXN0OiAwSFhVWnlhU2ZkZUtlZThuWnpFalJTeXJldTQ9DQoN
+Ck5hbWU6IFBLQ1M3VGVzdDQuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEEN
+ClNIQS1EaWdlc3Q6IEo3eXJTMjRvS3VTZ2F1dHZkemhxQmo3ZGJjUT0NCg0KTmFt
+ZTogUEtDUzdUZXN0NS5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hB
+LURpZ2VzdDogSlR2OVdTb3gxTEVTUjJMcTdzMFVxU2x0RFNRPQ0KDQpOYW1lOiBQ
+S0NTN1Rlc3Q2LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGln
+ZXN0OiBnR3Yra05oK3UzSFExdHp4bGNBVzdTcEZUS2s9DQoNCk5hbWU6IFBLQ1M3
+VGVzdDcuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6
+IGZpSEYxYUExYWN6czFPd0V5OEc3VkMrcjdMST0NCg0KTmFtZTogUEtDUzdUZXN0
+OC5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogNzRU
+VzdJOVZPdzVWZ0x2aFJtRGZxRVd2ZkFRPQ0KDQpOYW1lOiBQS0NTN1Rlc3Q5LmNs
+YXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiAxY0JJbkdU
+Y08xQVFaKy8wdmhGa2laV3dsQTA9DQoNCk5hbWU6IFNpZ25lckluZm9UZXN0LmNs
+YXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiBjRlk0Q3RT
+anphMUErV2pBS05TVnF1cGpSWUU9DQoNCk5hbWU6IFNpZ25lckluZm9UZXN0Mi5j
+bGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogYU5NMEZQ
+MHpFelF6eGxYeDZxQ0J4dWtta0hRPQ0KDQpOYW1lOiBTaW1wbGVTaWduZXIuY2xh
+c3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IC9MV0NzbkM3
+TVpNUjZHb3czeTJjdnA3STBTTT0NCg0KoIICvzCCArswggJ3AgUA59UzNDALBgcq
+hkjOOAQDBQAwdTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlD
+dXBlcnRpbm8xGTAXBgNVBAoTEFN1biBNaWNyb3N5c3RlbXMxETAPBgNVBAsTCEph
+dmFTb2Z0MRcwFQYDVQQDEw5Eb3VnbGFzIEhvb3ZlcjAeFw05NzEwMDIxODEyMDda
+Fw05NzEyMzExNzEyMDdaMHUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAG
+A1UEBxMJQ3VwZXJ0aW5vMRkwFwYDVQQKExBTdW4gTWljcm9zeXN0ZW1zMREwDwYD
+VQQLEwhKYXZhU29mdDEXMBUGA1UEAxMORG91Z2xhcyBIb292ZXIwggFRMIHoBgcq
+hkjOOAQBMIHcAmEA6eZCWZ01XzfJf/01ZxILjiXJzUPpJ7OpZw++xdiQFBki0sOz
+rSSACTeZhp0ehGqrSfqwrSbSzmoiIZ1HC859d31KIfvpwnC1f2BwAvPO+Dk2lM9F
+7jaIwRqMVqsSej2vAhUAnNvYTJ8awvOND4D0KrlS5zOL9RECYDBHCtWgBfsUzi2d
+zYfji8fRscX6y67L6V8ZCqejHSPE27y+BhdFREAaWywCCWXYwr0hcdNmhEV3H3S6
+CE0gKdg8HBWFR/Op8aJxW+I9Ua5NPlofanBk8xaTOjRtP1KSUgNkAAJhAMN5uB+B
+ZJ0W2UjXMyKoFUFXRYiLpnaSw63kl9tKnR9R5rEreiyHQ5IelPxjwCHGgTbYK0y+
+xKTGHVWiQN/YJmHLbSrcSSM/d89aR/sVbGoAwQOyYraFGUNIOTQjjXcXCjALBgcq
+hkjOOAQDBQADMQAwLgIVAJxmL029GLXDJVbk72d4cSPQ4/rvAhUAll9UPl8aOMEg
+V4egANhwbynMGSgxgc4wgcsCAQEwfjB1MQswCQYDVQQGEwJVUzELMAkGA1UECBMC
+Q0ExEjAQBgNVBAcTCUN1cGVydGlubzEZMBcGA1UEChMQU3VuIE1pY3Jvc3lzdGVt
+czERMA8GA1UECxMISmF2YVNvZnQxFzAVBgNVBAMTDkRvdWdsYXMgSG9vdmVyAgUA
+59UzNDAJBgUrDgMCGgUAMAsGByqGSM44BAMFAAQuMCwCFDmry17kzDD6Y5X1BqIS
+lq6swckPAhRtiXvBHa5CRGjbwk8yqf9hGgZfFA==
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs7/jarsigner/META-INF/PKCS7TEST.SF	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,82 @@
+Signature-Version: 1.0
+
+Name: CheckCerts.class
+Digest-Algorithms: SHA
+SHA-Digest: ya1xwvsQO+DRpQbw3Fh2nRB2JQc=
+
+Name: ContentInfoTest.class
+Digest-Algorithms: SHA
+SHA-Digest: Ca+EJakU6zw4KAhoqcnCpNqk2LI=
+
+Name: JarVerify.class
+Digest-Algorithms: SHA
+SHA-Digest: +DGaWWknfwe4ZOpsoMTFzfWRvhQ=
+
+Name: JarVerify2.class
+Digest-Algorithms: SHA
+SHA-Digest: GqDzYyY4P/WH5HKviWqXttPg5rE=
+
+Name: PKCS7Read.class
+Digest-Algorithms: SHA
+SHA-Digest: Qmf8K9hXVlwIdPY6nv2jFPfGqkA=
+
+Name: PKCS7Test.class
+Digest-Algorithms: SHA
+SHA-Digest: Gbe/gzyv2F58f6EEhSZ1BqGXtlo=
+
+Name: PKCS7Test10.class
+Digest-Algorithms: SHA
+SHA-Digest: 8wBqW//eW2sNRI91bLYEOodcgaE=
+
+Name: PKCS7Test11.class
+Digest-Algorithms: SHA
+SHA-Digest: bXhLKEslcuEXi4u/ahgT2q6tcEU=
+
+Name: PKCS7Test12.class
+Digest-Algorithms: SHA
+SHA-Digest: 9KEY1b52QLmN0qz/5z0wBFrOmz0=
+
+Name: PKCS7Test2.class
+Digest-Algorithms: SHA
+SHA-Digest: +Ua32/2Q8F2brQQmSXX+XS+M/h4=
+
+Name: PKCS7Test3.class
+Digest-Algorithms: SHA
+SHA-Digest: 0HXUZyaSfdeKee8nZzEjRSyreu4=
+
+Name: PKCS7Test4.class
+Digest-Algorithms: SHA
+SHA-Digest: J7yrS24oKuSgautvdzhqBj7dbcQ=
+
+Name: PKCS7Test5.class
+Digest-Algorithms: SHA
+SHA-Digest: JTv9WSox1LESR2Lq7s0UqSltDSQ=
+
+Name: PKCS7Test6.class
+Digest-Algorithms: SHA
+SHA-Digest: gGv+kNh+u3HQ1tzxlcAW7SpFTKk=
+
+Name: PKCS7Test7.class
+Digest-Algorithms: SHA
+SHA-Digest: fiHF1aA1aczs1OwEy8G7VC+r7LI=
+
+Name: PKCS7Test8.class
+Digest-Algorithms: SHA
+SHA-Digest: 74TW7I9VOw5VgLvhRmDfqEWvfAQ=
+
+Name: PKCS7Test9.class
+Digest-Algorithms: SHA
+SHA-Digest: 1cBInGTcO1AQZ+/0vhFkiZWwlA0=
+
+Name: SignerInfoTest.class
+Digest-Algorithms: SHA
+SHA-Digest: cFY4CtSjza1A+WjAKNSVqupjRYE=
+
+Name: SignerInfoTest2.class
+Digest-Algorithms: SHA
+SHA-Digest: aNM0FP0zEzQzxlXx6qCBxukmkHQ=
+
+Name: SimpleSigner.class
+Digest-Algorithms: SHA
+SHA-Digest: /LWCsnC7MZMR6Gow3y2cvp7I0SM=
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs/pkcs8/PKCS8Test.java	Tue Dec 20 03:24:31 2016 +0000
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8048357
+ * @summary PKCS8 Standards Conformance Tests
+ * @compile -XDignore.symbol.file PKCS8Test.java
+ * @run main PKCS8Test
+ */
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import sun.misc.HexDumpEncoder;
+import sun.security.pkcs.PKCS8Key;
+import sun.security.provider.DSAPrivateKey;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+import sun.security.x509.AlgorithmId;
+
+import static java.lang.System.out;
+
+public class PKCS8Test {
+
+    static final HexDumpEncoder hexDump = new HexDumpEncoder();
+
+    static final DerOutputStream derOutput = new DerOutputStream();
+
+    static final String FORMAT = "PKCS#8";
+    static final String EXPECTED_ALG_ID_CHRS = "DSA\n\tp:     02\n\tq:     03\n"
+            + "\tg:     04\n";
+    static final String ALGORITHM = "DSA";
+    static final String EXCEPTION_MESSAGE = "version mismatch: (supported:     "
+            + "00, parsed:     01";
+
+    // test second branch in byte[] encode()
+    // DER encoding,include (empty) set of attributes
+    static final int[] NEW_ENCODED_KEY_INTS = { 0x30,
+            // length 30 = 0x1e
+            0x1e,
+            // first element
+            // version Version (= INTEGER)
+            0x02,
+            // length 1
+            0x01,
+            // value 0
+            0x00,
+            // second element
+            // privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
+            // (sequence)
+            // (an object identifier?)
+            0x30,
+            // length 18
+            0x12,
+            // contents
+            // object identifier, 5 bytes
+            0x06, 0x05,
+            // { 1 3 14 3 2 12 }
+            0x2b, 0x0e, 0x03, 0x02, 0x0c,
+            // sequence, 9 bytes
+            0x30, 0x09,
+            // integer 2
+            0x02, 0x01, 0x02,
+            // integer 3
+            0x02, 0x01, 0x03,
+            // integer 4
+            0x02, 0x01, 0x04,
+            // third element
+            // privateKey PrivateKey (= OCTET STRING)
+            0x04,
+            // length
+            0x03,
+            // privateKey contents
+            0x02, 0x01, 0x01,
+            // 4th (optional) element -- attributes [0] IMPLICIT Attributes
+            // OPTIONAL
+            // (Attributes = SET OF Attribute) Here, it will be empty.
+            0xA0,
+            // length
+            0x00 };
+
+    // encoding originally created, but with the version changed
+    static final int[] NEW_ENCODED_KEY_INTS_2 = {
+            // sequence
+            0x30,
+            // length 28 = 0x1c
+            0x1c,
+            // first element
+            // version Version (= INTEGER)
+            0x02,
+            // length 1
+            0x01,
+            // value 1 (illegal)
+            0x01,
+            // second element
+            // privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
+            // (sequence)
+            // (an object identifier?)
+            0x30,
+            // length 18
+            0x12,
+            // contents
+            // object identifier, 5 bytes
+            0x06, 0x05,
+            // { 1 3 14 3 2 12 }
+            0x2b, 0x0e, 0x03, 0x02, 0x0c,
+            // sequence, 9 bytes
+            0x30, 0x09,
+            // integer 2
+            0x02, 0x01, 0x02,
+            // integer 3
+            0x02, 0x01, 0x03,
+            // integer 4
+            0x02, 0x01, 0x04,
+            // third element
+            // privateKey PrivateKey (= OCTET STRING)
+            0x04,
+            // length
+            0x03,
+            // privateKey contents
+            0x02, 0x01, 0x01 };
+
+    // 0000: 30 1E 02 01 00 30 14 06 07 2A 86 48 CE 38 04 01 0....0...*.H.8..
+    // 0010: 30 09 02 01 02 02 01 03 02 01 04 04 03 02 01 01 0...............
+    static final int[] EXPECTED = { 0x30,
+            // length 30 = 0x1e
+            0x1e,
+            // first element
+            // version Version (= INTEGER)
+            0x02,
+            // length 1
+            0x01,
+            // value 0
+            0x00,
+            // second element
+            // privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
+            // (sequence)
+            // (an object identifier?)
+            0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01,
+            // integer 2
+            0x30, 0x09, 0x02,
+            // integer 3
+            0x01, 0x02, 0x02,
+            // integer 4
+            0x01, 0x03, 0x02,
+            // third element
+            // privateKey PrivateKey (= OCTET STRING)
+            0x01,
+            // length
+            0x04,
+            // privateKey contents
+            0x04, 0x03, 0x02,
+            // 4th (optional) element -- attributes [0] IMPLICIT Attributes
+            // OPTIONAL
+            // (Attributes = SET OF Attribute) Here, it will be empty.
+            0x01,
+            // length
+            0x01 };
+
+    static void raiseException(String expected, String received) {
+        throw new RuntimeException(
+                "Expected " + expected + "; Received " + received);
+    }
+
+    public static void main(String[] args)
+            throws IOException, InvalidKeyException {
+
+        byte[] encodedKey = getEncodedKey();
+        byte[] expectedBytes = new byte[EXPECTED.length];
+        for (int i = 0; i < EXPECTED.length; i++) {
+            expectedBytes[i] = (byte) EXPECTED[i];
+        }
+
+        dumpByteArray("encodedKey :", encodedKey);
+        if (!Arrays.equals(encodedKey, expectedBytes)) {
+            raiseException(new String(expectedBytes), new String(encodedKey));
+        }
+
+        PKCS8Key decodedKey = PKCS8Key.parse(new DerValue(encodedKey));
+        String alg = decodedKey.getAlgorithm();
+        AlgorithmId algId = decodedKey.getAlgorithmId();
+        out.println("Algorithm :" + alg);
+        out.println("AlgorithmId: " + algId);
+
+        if (!ALGORITHM.equals(alg)) {
+            raiseException(ALGORITHM, alg);
+        }
+        if (!EXPECTED_ALG_ID_CHRS.equalsIgnoreCase(algId.toString())) {
+            raiseException(EXPECTED_ALG_ID_CHRS, algId.toString());
+        }
+
+        decodedKey.encode(derOutput);
+        dumpByteArray("Stream encode: ", derOutput.toByteArray());
+        if (!Arrays.equals(derOutput.toByteArray(), expectedBytes)) {
+            raiseException(new String(expectedBytes), derOutput.toString());
+        }
+
+        dumpByteArray("byte[] encoding: ", decodedKey.getEncoded());
+        if (!Arrays.equals(decodedKey.getEncoded(), expectedBytes)) {
+            raiseException(new String(expectedBytes),
+                    new String(decodedKey.getEncoded()));
+        }
+
+        if (!FORMAT.equals(decodedKey.getFormat())) {
+            raiseException(FORMAT, decodedKey.getFormat());
+        }
+
+        try {
+            byte[] newEncodedKey = new byte[NEW_ENCODED_KEY_INTS.length];
+            for (int i = 0; i < newEncodedKey.length; i++) {
+                newEncodedKey[i] = (byte) NEW_ENCODED_KEY_INTS[i];
+            }
+            PKCS8Key newDecodedKey = PKCS8Key
+                    .parse(new DerValue(newEncodedKey));
+
+            throw new RuntimeException(
+                    "key1: Expected an IOException during " + "parsing");
+        } catch (IOException e) {
+            System.out.println("newEncodedKey: should have excess data due to "
+                    + "attributes, which are not supported");
+        }
+
+        try {
+            byte[] newEncodedKey2 = new byte[NEW_ENCODED_KEY_INTS_2.length];
+            for (int i = 0; i < newEncodedKey2.length; i++) {
+                newEncodedKey2[i] = (byte) NEW_ENCODED_KEY_INTS_2[i];
+            }
+
+            PKCS8Key newDecodedKey2 = PKCS8Key
+                    .parse(new DerValue(newEncodedKey2));
+
+            throw new RuntimeException(
+                    "key2: Expected an IOException during " + "parsing");
+        } catch (IOException e) {
+            out.println("Key 2: should be illegal version");
+            out.println(e.getMessage());
+            if (!EXCEPTION_MESSAGE.equals(e.getMessage())) {
+                throw new RuntimeException("Key2: expected: "
+                        + EXCEPTION_MESSAGE + " get: " + e.getMessage());
+            }
+        }
+
+    }
+
+    // get a byte array from somewhere
+    static byte[] getEncodedKey() throws InvalidKeyException {
+        BigInteger p = BigInteger.valueOf(1);
+        BigInteger q = BigInteger.valueOf(2);
+        BigInteger g = BigInteger.valueOf(3);
+        BigInteger x = BigInteger.valueOf(4);
+
+        DSAPrivateKey priv = new DSAPrivateKey(p, q, g, x);
+        return priv.getEncoded();
+    }
+
+    static void dumpByteArray(String nm, byte[] bytes) throws IOException {
+        out.println(nm + " length: " + bytes.length);
+        hexDump.encodeBuffer(bytes, out);
+    }
+
+    static String toString(PKCS8Key key) {
+        StringBuilder builder = new StringBuilder(key.getAlgorithm());
+        builder.append('\n').append("parameters:")
+                .append(key.getAlgorithmId().toString());
+        return builder.toString();
+    }
+
+}