[Pki-devel] [PATCH] 685 Refactored PKCS12Util to use PKCS12 object.

Endi Sukma Dewata edewata at redhat.com
Wed Feb 17 19:52:32 UTC 2016


On 2/17/2016 1:02 AM, Endi Sukma Dewata wrote:
> On 2/16/2016 11:40 AM, Endi Sukma Dewata wrote:
>> The PKCS12Util has been modified such that it stores the certs and
>> keys in PKCS12 object instead of PFX object. The PKCS12 object can
>> be loaded either from NSS database or PKCS #12 file. The PKCS12
>> object can later be stored into NSS database or PKCS #12 file.
>>
>> https://fedorahosted.org/pki/ticket/1742
>>
>> This depends on patch #684.
>
> Rebased on top of #684-1.

New patch #685-2 attached. I added the missing code that's supposed to 
populate the keyID in PKCS12CertInfo.

Patch #686 can be applied on top of this patch.

-- 
Endi S. Dewata
-------------- next part --------------
>From 23468b55732acfa0679ae1d65bd63e7049680395 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Mon, 15 Feb 2016 05:27:19 +0100
Subject: [PATCH] Refactored PKCS12Util to use PKCS12 object.

The PKCS12Util has been modified such that it stores the certs and
keys in PKCS12 object instead of PFX object. The PKCS12 object can
be loaded either from NSS database or PKCS #12 file. The PKCS12
object can later be stored into NSS database or PKCS #12 file.

The pki pkcs12-key-find was modified to require the PKCS #12 file
password in all cases.

https://fedorahosted.org/pki/ticket/1742
---
 .../src/com/netscape/cmstools/PKCS12Export.java    |   5 +-
 .../cmstools/pkcs12/PKCS12CertFindCLI.java         |   7 +-
 .../netscape/cmstools/pkcs12/PKCS12ExportCLI.java  |   6 +-
 .../netscape/cmstools/pkcs12/PKCS12ImportCLI.java  |   6 +-
 .../com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java |   5 +-
 .../netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java |  20 +-
 base/util/src/netscape/security/pkcs/PKCS12.java   |  44 +++
 .../src/netscape/security/pkcs/PKCS12CertInfo.java |  11 +
 .../src/netscape/security/pkcs/PKCS12KeyInfo.java  |  13 +-
 .../src/netscape/security/pkcs/PKCS12Util.java     | 363 ++++++++++-----------
 10 files changed, 267 insertions(+), 213 deletions(-)

diff --git a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
index 5d698bea3f7ebd0b01984b99d45d927d81e525c2..bcc4252ba86fbaca88089ff8fd97575eb87b6908 100644
--- a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
+++ b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
@@ -26,6 +26,7 @@ import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.util.Password;
 
+import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS12Util;
 
 /**
@@ -126,7 +127,9 @@ public class PKCS12Export {
 
         try {
             PKCS12Util util = new PKCS12Util();
-            util.exportData(pkcs12OutputFilename, password);
+            PKCS12 pkcs12 = util.loadFromNSS();
+            util.storeIntoFile(pkcs12, pkcs12OutputFilename, password);
+
         } finally {
             password.clear();
         }
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java
index 3aec7a6b2a4c0d640dd4289da2b08f150989d7e1..7d792c782e759a7eef7c3ad16eb8edaad306595c 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java
@@ -18,7 +18,7 @@
 
 package com.netscape.cmstools.pkcs12;
 
-import java.util.List;
+import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -29,6 +29,7 @@ import org.apache.commons.cli.ParseException;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 
+import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS12CertInfo;
 import netscape.security.pkcs.PKCS12Util;
 
@@ -102,9 +103,9 @@ public class PKCS12CertFindCLI extends CLI {
         }
 
         PKCS12Util util = new PKCS12Util();
-        util.loadFromPKCS12(filename);
+        PKCS12 pkcs12 = util.loadFromFile(filename);
 
-        List<PKCS12CertInfo> certInfos = util.getCertInfos();
+        Collection<PKCS12CertInfo> certInfos = pkcs12.getCertInfos();
 
         MainCLI.printMessage(certInfos.size() + " entries found");
         if (certInfos.size() == 0) return;
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java
index e5acd06007b0bd0ef8edb561e6cf861b245a9dcb..174748262a5449d9aedb6cbb23dbe3394cb6b61f 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java
@@ -29,6 +29,7 @@ import org.mozilla.jss.util.Password;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 
+import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS12Util;
 
 /**
@@ -127,7 +128,10 @@ public class PKCS12ExportCLI extends CLI {
         try {
             PKCS12Util util = new PKCS12Util();
             util.setTrustFlagsEnabled(trustFlagsEnabled);
-            util.exportData(filename, password);
+
+            PKCS12 pkcs12 = util.loadFromNSS();
+            util.storeIntoFile(pkcs12, filename, password);
+
         } finally {
             password.clear();
         }
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
index 4e9ed23fc000842b9df0063b4b61ab59b7b5e8af..3e42efcbcf79db65018f21d287afe6e112292dd2 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
@@ -29,6 +29,7 @@ import org.mozilla.jss.util.Password;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 
+import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS12Util;
 
 /**
@@ -127,7 +128,10 @@ public class PKCS12ImportCLI extends CLI {
         try {
             PKCS12Util util = new PKCS12Util();
             util.setTrustFlagsEnabled(trustFlagsEnabled);
-            util.importData(filename, password);
+
+            PKCS12 pkcs12 = util.loadFromFile(filename, password);
+            util.storeIntoNSS(pkcs12, password);
+
         } finally {
             password.clear();
         }
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
index d859fcea1c480a17217ab6ee76138ff8641c0bc2..89565778702fbdc29e94385b0d0381f09db5508d 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
@@ -35,9 +35,6 @@ public class PKCS12KeyCLI extends CLI {
 
     public static void printKeyInfo(PKCS12KeyInfo keyInfo) throws Exception {
         System.out.println("  Subject DN: " + keyInfo.getSubjectDN());
-
-        if (keyInfo.getPrivateKeyInfo() != null) {
-            System.out.println("  Algorithm: " + keyInfo.getPrivateKeyInfo().getAlgorithm());
-        }
+        System.out.println("  Algorithm: " + keyInfo.getPrivateKeyInfo().getAlgorithm());
     }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java
index 3bda750a477e000f946cdb39d049245c3cb59176..92b9cf1321d4ce7237bae93ea99456991fdef0a0 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyFindCLI.java
@@ -20,7 +20,7 @@ package com.netscape.cmstools.pkcs12;
 
 import java.io.BufferedReader;
 import java.io.FileReader;
-import java.util.List;
+import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -32,6 +32,7 @@ import org.mozilla.jss.util.Password;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 
+import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS12KeyInfo;
 import netscape.security.pkcs.PKCS12Util;
 
@@ -124,21 +125,24 @@ public class PKCS12KeyFindCLI extends CLI {
             }
         }
 
-        Password password = null;
-        if (passwordString != null) {
-            password = new Password(passwordString.toCharArray());
+        if (passwordString == null) {
+            System.err.println("Error: Missing PKCS #12 password.");
+            printHelp();
+            System.exit(-1);
         }
 
-        List<PKCS12KeyInfo> keyInfos;
+        Password password = new Password(passwordString.toCharArray());
+
+        Collection<PKCS12KeyInfo> keyInfos;
 
         try {
             PKCS12Util util = new PKCS12Util();
-            util.loadFromPKCS12(filename);
+            PKCS12 pkcs12 = util.loadFromFile(filename, password);
 
-            keyInfos = util.getKeyInfos(password);
+            keyInfos = pkcs12.getKeyInfos();
 
         } finally {
-            if (password != null) password.clear();
+            password.clear();
         }
 
         MainCLI.printMessage(keyInfos.size() + " entries found");
diff --git a/base/util/src/netscape/security/pkcs/PKCS12.java b/base/util/src/netscape/security/pkcs/PKCS12.java
index df7fde447745dc9f17ee7c0e0d1ea42de1aab796..da4023f12c0b39dd14364dab196606e276c8a9b4 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12.java
@@ -17,6 +17,11 @@
 // --- END COPYRIGHT BLOCK ---
 package netscape.security.pkcs;
 
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
 
 public class PKCS12 {
@@ -133,4 +138,43 @@ public class PKCS12 {
 
         return value;
     }
+
+    Map<BigInteger, PKCS12KeyInfo> keyInfosByID = new LinkedHashMap<BigInteger, PKCS12KeyInfo>();
+
+    Map<String, PKCS12CertInfo> certInfosByNickname = new LinkedHashMap<String, PKCS12CertInfo>();
+
+    public PKCS12() {
+    }
+
+    public Collection<PKCS12KeyInfo> getKeyInfos() {
+        return keyInfosByID.values();
+    }
+
+    public void addKeyInfo(PKCS12KeyInfo keyInfo) {
+        keyInfosByID.put(keyInfo.id, keyInfo);
+    }
+
+    public PKCS12KeyInfo getKeyInfoByID(BigInteger id) {
+        return keyInfosByID.get(id);
+    }
+
+    public PKCS12KeyInfo removeKeyInfoByID(BigInteger id) {
+        return keyInfosByID.remove(id);
+    }
+
+    public Collection<PKCS12CertInfo> getCertInfos() {
+        return certInfosByNickname.values();
+    }
+
+    public void addCertInfo(PKCS12CertInfo certInfo) {
+        certInfosByNickname.put(certInfo.nickname, certInfo);
+    }
+
+    public PKCS12CertInfo getCertInfoByNickname(String nickname) {
+        return certInfosByNickname.get(nickname);
+    }
+
+    public PKCS12CertInfo removeCertInfoByNickname(String nickname) {
+        return certInfosByNickname.remove(nickname);
+    }
 }
diff --git a/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java b/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java
index d1a9cc9fca9ff53a13a2ad79269994fd3b19fcf7..3ac643eb1507d528e02ec23c1517f2b135745528 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12CertInfo.java
@@ -17,10 +17,13 @@
 // --- END COPYRIGHT BLOCK ---
 package netscape.security.pkcs;
 
+import java.math.BigInteger;
+
 import netscape.security.x509.X509CertImpl;
 
 public class PKCS12CertInfo {
 
+    BigInteger keyID;
     X509CertImpl cert;
     String nickname;
     String trustFlags;
@@ -28,6 +31,14 @@ public class PKCS12CertInfo {
     public PKCS12CertInfo() {
     }
 
+    public BigInteger getKeyID() {
+        return keyID;
+    }
+
+    public void setKeyID(BigInteger keyID) {
+        this.keyID = keyID;
+    }
+
     public X509CertImpl getCert() {
         return cert;
     }
diff --git a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
index ff3f2a289dea23e6d26482b3dd610867f49e385a..c7e84f01ffa19a0fc116f1f3fddf2bf3dfe9de9e 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
@@ -17,24 +17,25 @@
 // --- END COPYRIGHT BLOCK ---
 package netscape.security.pkcs;
 
-import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
+import java.math.BigInteger;
+
 import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
 
 public class PKCS12KeyInfo {
 
-    EncryptedPrivateKeyInfo encPrivateKeyInfo;
+    BigInteger id;
     PrivateKeyInfo privateKeyInfo;
     String subjectDN;
 
     public PKCS12KeyInfo() {
     }
 
-    public EncryptedPrivateKeyInfo getEncPrivateKeyInfo() {
-        return encPrivateKeyInfo;
+    public BigInteger getID() {
+        return id;
     }
 
-    public void setEncPrivateKeyInfo(EncryptedPrivateKeyInfo encPrivateKeyInfo) {
-        this.encPrivateKeyInfo = encPrivateKeyInfo;
+    public void setID(BigInteger id) {
+        this.id = id;
     }
 
     public PrivateKeyInfo getPrivateKeyInfo() {
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 3233446d3ef0a7ea3d96812fed52f3e2457ec068..7af63db6e599d1886c3a40e95efd455fcdb1cf1c 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -28,8 +28,6 @@ import java.security.MessageDigest;
 import java.security.Principal;
 import java.security.PublicKey;
 import java.security.cert.CertificateException;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.logging.Logger;
 
 import org.mozilla.jss.CryptoManager;
@@ -74,7 +72,6 @@ public class PKCS12Util {
 
     private static Logger logger = Logger.getLogger(PKCS12Util.class.getName());
 
-    PFX pfx;
     boolean trustFlagsEnabled = true;
 
     public boolean isTrustFlagsEnabled() {
@@ -131,53 +128,36 @@ public class PKCS12Util {
         return c.doFinal(enckey);
     }
 
-    public void addKeyBag(PrivateKey privateKey, X509Certificate x509cert,
-            Password pass, BigInteger localKeyID, SEQUENCE safeContents) throws Exception {
+    public void addKeyBag(PKCS12KeyInfo keyInfo, Password password,
+            SEQUENCE encSafeContents) throws Exception {
 
-        logger.fine("Creating key bag for " + x509cert.getSubjectDN());
+        logger.fine("Creating key bag for " + keyInfo.subjectDN);
 
         PasswordConverter passConverter = new PasswordConverter();
         byte salt[] = { 0x01, 0x01, 0x01, 0x01 };
-        byte[] priData = getEncodedKey(privateKey);
 
-        PrivateKeyInfo pki = (PrivateKeyInfo)
-                ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData);
-
-        ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
+        EncryptedPrivateKeyInfo encPrivateKeyInfo = EncryptedPrivateKeyInfo.createPBE(
                 PBEAlgorithm.PBE_SHA1_DES3_CBC,
-                pass, salt, 1, passConverter, pki);
+                password, salt, 1, passConverter, keyInfo.privateKeyInfo);
 
-        SET keyAttrs = createKeyBagAttrs(
-                x509cert.getSubjectDN().toString(), localKeyID);
+        SET keyAttrs = createKeyBagAttrs(keyInfo);
 
-        SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG,
-                key, keyAttrs);
-
-        safeContents.addElement(keyBag);
+        SafeBag safeBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, encPrivateKeyInfo, keyAttrs);
+        encSafeContents.addElement(safeBag);
     }
 
-    public BigInteger addCertBag(X509Certificate x509cert, String nickname,
+    public void addCertBag(PKCS12CertInfo certInfo,
             SEQUENCE safeContents) throws Exception {
 
-        logger.fine("Creating cert bag for " + nickname);
+        logger.fine("Creating cert bag for " + certInfo.nickname);
 
-        ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
-        BigInteger keyID = createLocalKeyID(x509cert);
+        ASN1Value cert = new OCTET_STRING(certInfo.cert.getEncoded());
+        CertBag certBag = new CertBag(CertBag.X509_CERT_TYPE, cert);
 
-        String trustFlags = null;
-        if (trustFlagsEnabled) {
-            trustFlags = getTrustFlags(x509cert);
-            logger.fine("Trust flags: " + trustFlags);
-        }
+        SET certAttrs = createCertBagAttrs(certInfo);
 
-        SET certAttrs = createCertBagAttrs(nickname, keyID, trustFlags);
-
-        SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
-                new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs);
-
-        safeContents.addElement(certBag);
-
-        return keyID;
+        SafeBag safeBag = new SafeBag(SafeBag.CERT_BAG, certBag, certAttrs);
+        safeContents.addElement(safeBag);
     }
 
     BigInteger createLocalKeyID(X509Certificate cert) throws Exception {
@@ -191,8 +171,7 @@ public class PKCS12Util {
         return new BigInteger(md.digest());
     }
 
-    SET createKeyBagAttrs(String subjectDN, BigInteger localKeyID)
-            throws Exception {
+    SET createKeyBagAttrs(PKCS12KeyInfo keyInfo) throws Exception {
 
         SET attrs = new SET();
 
@@ -200,7 +179,7 @@ public class PKCS12Util {
         subjectAttr.addElement(SafeBag.FRIENDLY_NAME);
 
         SET subjectSet = new SET();
-        subjectSet.addElement(new BMPString(subjectDN));
+        subjectSet.addElement(new BMPString(keyInfo.subjectDN));
         subjectAttr.addElement(subjectSet);
 
         attrs.addElement(subjectAttr);
@@ -209,7 +188,7 @@ public class PKCS12Util {
         localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
 
         SET localKeySet = new SET();
-        localKeySet.addElement(new OCTET_STRING(localKeyID.toByteArray()));
+        localKeySet.addElement(new OCTET_STRING(keyInfo.id.toByteArray()));
         localKeyAttr.addElement(localKeySet);
 
         attrs.addElement(localKeyAttr);
@@ -217,8 +196,7 @@ public class PKCS12Util {
         return attrs;
     }
 
-    SET createCertBagAttrs(String nickname, BigInteger keyID, String trustFlags)
-            throws Exception {
+    SET createCertBagAttrs(PKCS12CertInfo certInfo) throws Exception {
 
         SET attrs = new SET();
 
@@ -226,7 +204,7 @@ public class PKCS12Util {
         nicknameAttr.addElement(SafeBag.FRIENDLY_NAME);
 
         SET nicknameSet = new SET();
-        nicknameSet.addElement(new BMPString(nickname));
+        nicknameSet.addElement(new BMPString(certInfo.nickname));
         nicknameAttr.addElement(nicknameSet);
 
         attrs.addElement(nicknameAttr);
@@ -235,17 +213,17 @@ public class PKCS12Util {
         localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
 
         SET localKeySet = new SET();
-        localKeySet.addElement(new OCTET_STRING(keyID.toByteArray()));
+        localKeySet.addElement(new OCTET_STRING(certInfo.keyID.toByteArray()));
         localKeyAttr.addElement(localKeySet);
 
         attrs.addElement(localKeyAttr);
 
-        if (trustFlags != null && trustFlagsEnabled) {
+        if (certInfo.trustFlags != null && trustFlagsEnabled) {
             SEQUENCE trustFlagsAttr = new SEQUENCE();
             trustFlagsAttr.addElement(PKCS12.CERT_TRUST_FLAGS_OID);
 
             SET trustFlagsSet = new SET();
-            trustFlagsSet.addElement(new BMPString(trustFlags));
+            trustFlagsSet.addElement(new BMPString(certInfo.trustFlags));
             trustFlagsAttr.addElement(trustFlagsSet);
 
             attrs.addElement(trustFlagsAttr);
@@ -254,7 +232,7 @@ public class PKCS12Util {
         return attrs;
     }
 
-    public void loadFromNSS(Password password) throws Exception {
+    public PKCS12 loadFromNSS() throws Exception {
 
         logger.info("Loading data from NSS database");
 
@@ -262,40 +240,72 @@ public class PKCS12Util {
         CryptoToken token = cm.getInternalKeyStorageToken();
         CryptoStore store = token.getCryptoStore();
 
-        SEQUENCE encSafeContents = new SEQUENCE();
+        PKCS12 pkcs12 = new PKCS12();
+
+        for (X509Certificate cert : store.getCertificates()) {
+            loadCertAndKeyFromNSS(pkcs12, cert);
+        }
+
+        return pkcs12;
+    }
+
+    public void loadCertAndKeyFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception {
+
+        String nickname = cert.getNickname();
+        logger.info("Loading certificate \"" + nickname + "\" from NSS database");
+
+        CryptoManager cm = CryptoManager.getInstance();
+
+        BigInteger keyID = createLocalKeyID(cert);
+
+        PKCS12CertInfo certInfo = new PKCS12CertInfo();
+        certInfo.keyID = keyID;
+        certInfo.nickname = nickname;
+        certInfo.cert = new X509CertImpl(cert.getEncoded());
+        certInfo.trustFlags = getTrustFlags(cert);
+        pkcs12.addCertInfo(certInfo);
+
+        try {
+            PrivateKey privateKey = cm.findPrivKeyByCert(cert);
+
+            logger.fine("Certificate \"" + nickname + "\" has private key");
+
+            PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
+            keyInfo.id = keyID;
+            keyInfo.subjectDN = cert.getSubjectDN().toString();
+
+            byte[] privateData = getEncodedKey(privateKey);
+            keyInfo.privateKeyInfo = (PrivateKeyInfo)
+                    ASN1Util.decode(PrivateKeyInfo.getTemplate(), privateData);
+
+            pkcs12.addKeyInfo(keyInfo);
+
+        } catch (ObjectNotFoundException e) {
+            logger.fine("Certificate \"" + nickname + "\" has no private key");
+        }
+    }
+
+    public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception {
+
+        logger.info("Storing data into PKCS #12 file");
+
         SEQUENCE safeContents = new SEQUENCE();
 
-        logger.fine("Loading certificates");
+        for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
+            addCertBag(certInfo, safeContents);
+        }
 
-        X509Certificate[] certs = store.getCertificates();
+        SEQUENCE encSafeContents = new SEQUENCE();
 
-        for (X509Certificate cert : certs) {
-            String nickname = cert.getNickname();
-
-            try {
-                PrivateKey prikey = cm.findPrivKeyByCert(cert);
-                logger.fine("Found certificate " + nickname + " with private key");
-
-                BigInteger localKeyID = addCertBag(cert, nickname, safeContents);
-                addKeyBag(prikey, cert, password, localKeyID, encSafeContents);
-
-            } catch (ObjectNotFoundException e) {
-                logger.fine("Found certificate " + nickname + " without private key");
-                addCertBag(cert, nickname, safeContents);
-            }
+        for (PKCS12KeyInfo keyInfo : pkcs12.getKeyInfos()) {
+            addKeyBag(keyInfo, password, encSafeContents);
         }
 
         AuthenticatedSafes authSafes = new AuthenticatedSafes();
         authSafes.addSafeContents(safeContents);
         authSafes.addSafeContents(encSafeContents);
 
-        pfx = new PFX(authSafes);
-    }
-
-    public void storeIntoPKCS12(String filename, Password password) throws Exception {
-
-        logger.info("Storing data into PKCS #12 file");
-
+        PFX pfx = new PFX(authSafes);
         pfx.computeMacData(password, null, 5);
 
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -307,57 +317,51 @@ public class PKCS12Util {
         }
     }
 
-    public void exportData(String filename, Password password) throws Exception {
-
-        loadFromNSS(password);
-        storeIntoPKCS12(filename, password);
-    }
-
     public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception {
 
+        PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
+
         // get private key info
         EncryptedPrivateKeyInfo encPrivateKeyInfo = (EncryptedPrivateKeyInfo) bag.getInterpretedBagContent();
+        keyInfo.privateKeyInfo = encPrivateKeyInfo.decrypt(password, new PasswordConverter());
 
-        PrivateKeyInfo privateKeyInfo = null;
-        if (password != null) {
-            privateKeyInfo = encPrivateKeyInfo.decrypt(password, new PasswordConverter());
-        }
-
-        // find private key's subject DN
+        // get key attributes
         SET bagAttrs = bag.getBagAttributes();
-        String subjectDN = null;
 
         for (int i = 0; i < bagAttrs.size(); i++) {
 
             Attribute attr = (Attribute) bagAttrs.elementAt(i);
             OBJECT_IDENTIFIER oid = attr.getType();
 
-            if (!oid.equals(SafeBag.FRIENDLY_NAME)) continue;
+            if (oid.equals(SafeBag.FRIENDLY_NAME)) {
 
-            SET values = attr.getValues();
-            ANY value = (ANY) values.elementAt(0);
+                SET values = attr.getValues();
+                ANY value = (ANY) values.elementAt(0);
 
-            ByteArrayInputStream bbis = new ByteArrayInputStream(value.getEncoded());
-            BMPString sss = (BMPString) new BMPString.Template().decode(bbis);
-            subjectDN = sss.toString();
+                ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
+                BMPString subjectDN = (BMPString) new BMPString.Template().decode(bis);
 
-            break;
+                keyInfo.subjectDN = subjectDN.toString();
+                logger.fine("Subject DN: " + keyInfo.subjectDN);
+
+            } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) {
+
+                SET values = attr.getValues();
+                ANY value = (ANY) values.elementAt(0);
+
+                ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
+                OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis);
+
+                keyInfo.id = new BigInteger(keyID.toByteArray());
+                logger.fine("Key ID: 0x" + keyInfo.id.toString(16));
+            }
         }
 
-        logger.fine("Found private key " + subjectDN);
-
-        PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
-        keyInfo.encPrivateKeyInfo = encPrivateKeyInfo;
-        keyInfo.privateKeyInfo = privateKeyInfo;
-        keyInfo.subjectDN = subjectDN;
+        logger.fine("Found private key " + keyInfo.subjectDN);
 
         return keyInfo;
     }
 
-    public PKCS12KeyInfo getKeyInfo(SafeBag bag) throws Exception {
-        return getKeyInfo(bag, null);
-    }
-
     public PKCS12CertInfo getCertInfo(SafeBag bag) throws Exception {
 
         PKCS12CertInfo certInfo = new PKCS12CertInfo();
@@ -383,21 +387,33 @@ public class PKCS12Util {
                 SET values = attr.getValues();
                 ANY value = (ANY) values.elementAt(0);
 
-                ByteArrayInputStream is = new ByteArrayInputStream(value.getEncoded());
-                BMPString nicknameStr = (BMPString) (new BMPString.Template()).decode(is);
+                ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
+                BMPString nickname = (BMPString) (new BMPString.Template()).decode(bis);
 
-                certInfo.nickname = nicknameStr.toString();
+                certInfo.nickname = nickname.toString();
                 logger.fine("Nickname: " + certInfo.nickname);
 
+
+            } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) {
+
+                SET values = attr.getValues();
+                ANY value = (ANY) values.elementAt(0);
+
+                ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
+                OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis);
+
+                certInfo.keyID = new BigInteger(keyID.toByteArray());
+                logger.fine("Key ID: 0x" + certInfo.keyID.toString(16));
+
             } else if (oid.equals(PKCS12.CERT_TRUST_FLAGS_OID) && trustFlagsEnabled) {
 
                 SET values = attr.getValues();
                 ANY value = (ANY) values.elementAt(0);
 
                 ByteArrayInputStream is = new ByteArrayInputStream(value.getEncoded());
-                BMPString trustFlagsStr = (BMPString) (new BMPString.Template()).decode(is);
+                BMPString trustFlags = (BMPString) (new BMPString.Template()).decode(is);
 
-                certInfo.trustFlags = trustFlagsStr.toString();
+                certInfo.trustFlags = trustFlags.toString();
                 logger.fine("Trust flags: " + certInfo.trustFlags);
             }
         }
@@ -405,11 +421,10 @@ public class PKCS12Util {
         return certInfo;
     }
 
-    public List<PKCS12KeyInfo> getKeyInfos(Password password) throws Exception {
+    public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception {
 
         logger.fine("Getting private keys");
 
-        List<PKCS12KeyInfo> keyInfos = new ArrayList<PKCS12KeyInfo>();
         AuthenticatedSafes safes = pfx.getAuthSafes();
 
         for (int i = 0; i < safes.getSize(); i++) {
@@ -424,22 +439,15 @@ public class PKCS12Util {
                 if (!oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) continue;
 
                 PKCS12KeyInfo keyInfo = getKeyInfo(bag, password);
-                keyInfos.add(keyInfo);
+                pkcs12.addKeyInfo(keyInfo);
             }
         }
-
-        return keyInfos;
-    }
-
-    public List<PKCS12KeyInfo> getKeyInfos() throws Exception {
-        return getKeyInfos(null);
     }
 
-    public List<PKCS12CertInfo> getCertInfos() throws Exception {
+    public void getCertInfos(PKCS12 pkcs12, PFX pfx) throws Exception {
 
         logger.fine("Getting certificates");
 
-        List<PKCS12CertInfo> certInfos = new ArrayList<PKCS12CertInfo>();
         AuthenticatedSafes safes = pfx.getAuthSafes();
 
         for (int i = 0; i < safes.getSize(); i++) {
@@ -454,14 +462,12 @@ public class PKCS12Util {
                 if (!oid.equals(SafeBag.CERT_BAG)) continue;
 
                 PKCS12CertInfo certInfo = getCertInfo(bag);
-                certInfos.add(certInfo);
+                pkcs12.addCertInfo(certInfo);
             }
         }
-
-        return certInfos;
     }
 
-    public void loadFromPKCS12(String filename) throws Exception {
+    public PKCS12 loadFromFile(String filename, Password password) throws Exception {
 
         logger.info("Loading PKCS #12 file");
 
@@ -470,7 +476,28 @@ public class PKCS12Util {
 
         ByteArrayInputStream bis = new ByteArrayInputStream(b);
 
-        pfx = (PFX) (new PFX.Template()).decode(bis);
+        PFX pfx = (PFX) (new PFX.Template()).decode(bis);
+
+        PKCS12 pkcs12 = new PKCS12();
+
+        if (password != null) {
+            StringBuffer reason = new StringBuffer();
+            boolean valid = pfx.verifyAuthSafes(password, reason);
+
+            if (!valid) {
+                throw new Exception("Invalid PKCS #12 password: " + reason);
+            }
+
+            getKeyInfos(pkcs12, pfx, password);
+        }
+
+        getCertInfos(pkcs12, pfx);
+
+        return pkcs12;
+    }
+
+    public PKCS12 loadFromFile(String filename) throws Exception {
+        return loadFromFile(filename, null);
     }
 
     public PrivateKey.Type getPrivateKeyType(PublicKey publicKey) {
@@ -480,40 +507,32 @@ public class PKCS12Util {
         return PrivateKey.Type.RSA;
     }
 
-    public X509CertImpl getCertBySubjectDN(String subjectDN, List<PKCS12CertInfo> certInfos)
+    public PKCS12CertInfo getCertBySubjectDN(PKCS12 pkcs12, String subjectDN)
             throws CertificateException {
 
-        for (PKCS12CertInfo certInfo : certInfos) {
-            X509CertImpl cert = certInfo.cert;
-            Principal certSubjectDN = cert.getSubjectDN();
-            if (LDAPDN.equals(certSubjectDN.toString(), subjectDN)) return cert;
+        for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
+            Principal certSubjectDN = certInfo.cert.getSubjectDN();
+            if (LDAPDN.equals(certSubjectDN.toString(), subjectDN)) return certInfo;
         }
 
         return null;
     }
 
     public void importKey(
-            PKCS12KeyInfo keyInfo,
-            Password password,
-            List<PKCS12CertInfo> certInfos) throws Exception {
+            PKCS12 pkcs12,
+            PKCS12KeyInfo keyInfo) throws Exception {
+
+        logger.fine("Importing private key " + keyInfo.subjectDN);
 
         PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo;
 
-        if (privateKeyInfo == null) {
-            privateKeyInfo = keyInfo.encPrivateKeyInfo.decrypt(password, new PasswordConverter());
-        }
-
-        String subjectDN = keyInfo.subjectDN;
-
-        logger.fine("Importing private key " + subjectDN);
-
         // encode private key
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         privateKeyInfo.encode(bos);
         byte[] privateKey = bos.toByteArray();
 
-        X509CertImpl x509cert = getCertBySubjectDN(subjectDN, certInfos);
-        if (x509cert == null) {
+        PKCS12CertInfo certInfo = getCertBySubjectDN(pkcs12, keyInfo.subjectDN);
+        if (certInfo == null) {
             logger.fine("Private key nas no certificate, ignore");
             return;
         }
@@ -522,7 +541,7 @@ public class PKCS12Util {
         CryptoToken token = cm.getInternalKeyStorageToken();
         CryptoStore store = token.getCryptoStore();
 
-        X509Certificate cert = cm.importCACertPackage(x509cert.getEncoded());
+        X509Certificate cert = cm.importCACertPackage(certInfo.cert.getEncoded());
 
         // get public key
         PublicKey publicKey = cert.getPublicKey();
@@ -549,72 +568,38 @@ public class PKCS12Util {
         wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publicKey), publicKey);
     }
 
-    public void importKeys(
-            List<PKCS12KeyInfo> keyInfos,
-            Password password,
-            List<PKCS12CertInfo> certInfos
-        ) throws Exception {
+    public void importKeys(PKCS12 pkcs12) throws Exception {
 
-        for (int i = 0; i < keyInfos.size(); i++) {
-            PKCS12KeyInfo keyInfo = keyInfos.get(i);
-            importKey(keyInfo, password, certInfos);
+        for (PKCS12KeyInfo keyInfo : pkcs12.getKeyInfos()) {
+            importKey(pkcs12, keyInfo);
         }
     }
 
-    public X509Certificate importCert(X509CertImpl cert, String nickname, String trustFlags) throws Exception {
+    public void importCert(PKCS12CertInfo certInfo) throws Exception {
 
-        logger.fine("Importing certificate " + cert.getSubjectDN());
+        logger.fine("Importing certificate " + certInfo.nickname);
 
         CryptoManager cm = CryptoManager.getInstance();
 
-        X509Certificate xcert;
+        X509Certificate cert = cm.importUserCACertPackage(
+                certInfo.cert.getEncoded(), certInfo.nickname);
 
-        if (nickname == null) {
-            xcert = cm.importCACertPackage(cert.getEncoded());
-
-        } else {
-            xcert = cm.importUserCACertPackage(cert.getEncoded(), nickname);
-        }
-
-        if (trustFlags != null && trustFlagsEnabled)
-            setTrustFlags(xcert, trustFlags);
-
-        return xcert;
+        if (certInfo.trustFlags != null && trustFlagsEnabled)
+            setTrustFlags(cert, certInfo.trustFlags);
     }
 
-    public void importCerts(List<PKCS12CertInfo> certInfos) throws Exception {
-
-        for (PKCS12CertInfo certInfo : certInfos) {
-            importCert(certInfo.cert, certInfo.nickname, certInfo.trustFlags);
-        }
-    }
-
-    public void verifyPassword(Password password) throws Exception {
-
-        StringBuffer reason = new StringBuffer();
-        boolean valid = pfx.verifyAuthSafes(password, reason);
+    public void importCerts(PKCS12 pkcs12) throws Exception {
 
-        if (!valid) {
-            throw new Exception(reason.toString());
+        for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
+            importCert(certInfo);
         }
     }
 
-    public void storeIntoNSS(Password password) throws Exception {
+    public void storeIntoNSS(PKCS12 pkcs12, Password password) throws Exception {
 
         logger.info("Storing data into NSS database");
 
-        verifyPassword(password);
-
-        List<PKCS12KeyInfo> keyInfos = getKeyInfos();
-        List<PKCS12CertInfo> certInfos = getCertInfos();
-
-        importKeys(keyInfos, password, certInfos);
-        importCerts(certInfos);
-    }
-
-    public void importData(String filename, Password password) throws Exception {
-
-        loadFromPKCS12(filename);
-        storeIntoNSS(password);
+        importKeys(pkcs12);
+        importCerts(pkcs12);
     }
 }
-- 
2.4.3



More information about the Pki-devel mailing list