[Pki-devel] [PATCH] 688 Updated PKCS12Util.

Endi Sukma Dewata edewata at redhat.com
Tue Feb 23 05:37:44 UTC 2016


The PKCSUtil has been updated to match the functionality provided
by JSS.

In order to import a certificate properly, the certificate needs
to be exported with its private key and certificate chain, so the
option to export without key or without the certificate chain has
been removed. The option to export only the certificate chain has
also been removed since it can be done by exporting the complete
certificate chain, then remove the leaf certificate while keeping
the chain.

The pki pkcs12-cert-add has been modified to provide an option
to create a new PKCS #12 file to store the certificate.

The pki pkcs12-export has been modified to always overwrite
existing file to match the behavior of PKCS12Export. It also has
been modified to accept a list of nicknames of certificates to
export.

https://fedorahosted.org/pki/ticket/1742

-- 
Endi S. Dewata
-------------- next part --------------
From b0dc5b8b694ec1bf971fc203f551e8a72bd10459 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Mon, 22 Feb 2016 18:29:46 +0100
Subject: [PATCH] Updated PKCS12Util.

The PKCSUtil has been updated to match the functionality provided
by JSS.

In order to import a certificate properly, the certificate needs
to be exported with its private key and certificate chain, so the
option to export without key or without the certificate chain has
been removed. The option to export only the certificate chain has
also been removed since it can be done by exporting the complete
certificate chain, then remove the leaf certificate while keeping
the chain.

The pki pkcs12-cert-add has been modified to provide an option
to create a new PKCS #12 file to store the certificate.

The pki pkcs12-export has been modified to always overwrite
existing file to match the behavior of PKCS12Export. It also has
been modified to accept a list of nicknames of certificates to
export.

https://fedorahosted.org/pki/ticket/1742
---
 .../netscape/cmstools/pkcs12/PKCS12CertAddCLI.java | 19 +++---
 .../netscape/cmstools/pkcs12/PKCS12ExportCLI.java  | 19 +++---
 base/util/src/netscape/security/pkcs/PKCS12.java   |  8 ++-
 .../src/netscape/security/pkcs/PKCS12Util.java     | 67 +++++++++++-----------
 4 files changed, 63 insertions(+), 50 deletions(-)

diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java
index 6c9d8032edabc36476d1b81a146e140dc3d2c25f..ce7b3dd792c34f8c26e21a58962704f6e4ac2dee 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertAddCLI.java
@@ -63,10 +63,8 @@ public class PKCS12CertAddCLI extends CLI {
         option.setArgName("path");
         options.addOption(option);
 
+        options.addOption(null, "new-file", false, "Create a new PKCS #12 file");
         options.addOption(null, "no-trust-flags", false, "Do not include trust flags");
-        options.addOption(null, "no-cert", false, "Do not include certificate itself");
-        options.addOption(null, "no-key", false, "Do not include certificate key");
-        options.addOption(null, "no-chain", false, "Do not include certificate chain");
 
         options.addOption("v", "verbose", false, "Run in verbose mode.");
         options.addOption(null, "debug", false, "Run in debug mode.");
@@ -139,10 +137,8 @@ public class PKCS12CertAddCLI extends CLI {
 
         Password password = new Password(passwordString.toCharArray());
 
+        boolean newFile = cmd.hasOption("new-file");
         boolean includeTrustFlags = !cmd.hasOption("no-trust-flags");
-        boolean includeCert = !cmd.hasOption("no-cert");
-        boolean includeKey = !cmd.hasOption("no-key");
-        boolean includeChain = !cmd.hasOption("no-chain");
 
         try {
             PKCS12Util util = new PKCS12Util();
@@ -150,13 +146,16 @@ public class PKCS12CertAddCLI extends CLI {
 
             PKCS12 pkcs12;
 
-            if (new File(filename).exists()) {
-                pkcs12 = util.loadFromFile(filename, password);
-            } else {
+            if (newFile || !new File(filename).exists()) {
+                // if new file requested or file does not exist, create a new file
                 pkcs12 = new PKCS12();
+
+            } else {
+                // otherwise, add into the same file
+                pkcs12 = util.loadFromFile(filename, password);
             }
 
-            util.loadFromNSS(pkcs12, nickname, includeCert, includeKey, includeChain);
+            util.loadCertFromNSS(pkcs12, nickname);
             util.storeIntoFile(pkcs12, filename, password);
 
         } finally {
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 a5c9e282375e31d1c0b8d20d69e229ba1d0c0264..f172512845378c6a45287815eda8006173bbaba5 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ExportCLI.java
@@ -18,7 +18,6 @@
 package com.netscape.cmstools.pkcs12;
 
 import java.io.BufferedReader;
-import java.io.File;
 import java.io.FileReader;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -45,7 +44,7 @@ public class PKCS12ExportCLI extends CLI {
     }
 
     public void printHelp() {
-        formatter.printHelp(getFullName() + " [OPTIONS...]", options);
+        formatter.printHelp(getFullName() + " [OPTIONS...] [nicknames...]", options);
     }
 
     public void createOptions() {
@@ -96,6 +95,7 @@ public class PKCS12ExportCLI extends CLI {
             Logger.getLogger("netscape").setLevel(Level.FINE);
         }
 
+        String[] nicknames = cmd.getArgs();
         String filename = cmd.getOptionValue("pkcs12");
 
         if (filename == null) {
@@ -130,15 +130,20 @@ public class PKCS12ExportCLI extends CLI {
             PKCS12Util util = new PKCS12Util();
             util.setTrustFlagsEnabled(trustFlagsEnabled);
 
-            PKCS12 pkcs12;
+            // overwrite existing file
+            PKCS12 pkcs12 = new PKCS12();
+
+            if (nicknames.length == 0) {
+                // load all certificates
+                util.loadFromNSS(pkcs12);
 
-            if (new File(filename).exists()) {
-                pkcs12 = util.loadFromFile(filename, password);
             } else {
-                pkcs12 = new PKCS12();
+                // load specified certificates
+                for (String nickname : nicknames) {
+                    util.loadCertFromNSS(pkcs12, nickname);
+                }
             }
 
-            util.loadFromNSS(pkcs12);
             util.storeIntoFile(pkcs12, filename, password);
 
         } finally {
diff --git a/base/util/src/netscape/security/pkcs/PKCS12.java b/base/util/src/netscape/security/pkcs/PKCS12.java
index da4023f12c0b39dd14364dab196606e276c8a9b4..19e9fd039abfb003cdf3b8d95ea4782c1ba38d9b 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12.java
@@ -175,6 +175,12 @@ public class PKCS12 {
     }
 
     public PKCS12CertInfo removeCertInfoByNickname(String nickname) {
-        return certInfosByNickname.remove(nickname);
+        // remove cert
+        PKCS12CertInfo certInfo = certInfosByNickname.remove(nickname);
+        if (certInfo == null) return null;
+
+        // remove private key
+        keyInfosByID.remove(certInfo.getKeyID());
+        return certInfo;
     }
 }
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 8d189a9d785cac4492ffe5a57ac941282aba8d50..665998e2fed640b8f99add3b5645f9094415ce06 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -240,34 +240,23 @@ public class PKCS12Util {
         CryptoToken token = cm.getInternalKeyStorageToken();
         CryptoStore store = token.getCryptoStore();
 
-        // load all certs
         for (X509Certificate cert : store.getCertificates()) {
-            loadCertFromNSS(pkcs12, cert, true); // load cert with private key
-        }
-    }
-
-    public void loadFromNSS(PKCS12 pkcs12, String nickname, boolean includeCert, boolean includeKey, boolean includeChain) throws Exception {
-
-        CryptoManager cm = CryptoManager.getInstance();
-
-        X509Certificate cert = cm.findCertByNickname(nickname);
-
-        if (includeCert) {
-            loadCertFromNSS(pkcs12, cert, includeKey);
-        }
-
-        if (includeChain) {
             loadCertChainFromNSS(pkcs12, cert);
         }
     }
 
-    public void loadCertFromNSS(PKCS12 pkcs12, X509Certificate cert, boolean includeKey) throws Exception {
+    public void loadCertFromNSS(PKCS12 pkcs12, String nickname) throws Exception {
+
+        CryptoManager cm = CryptoManager.getInstance();
+        X509Certificate cert = cm.findCertByNickname(nickname);
+        loadCertChainFromNSS(pkcs12, cert);
+    }
+
+    public void loadCertFromNSS(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();
@@ -276,17 +265,23 @@ public class PKCS12Util {
         certInfo.cert = new X509CertImpl(cert.getEncoded());
         certInfo.trustFlags = getTrustFlags(cert);
         pkcs12.addCertInfo(certInfo);
+    }
 
-        if (!includeKey) return;
+    public void loadCertKeyFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception {
 
+        String nickname = cert.getNickname();
         logger.info("Loading private key for certificate \"" + nickname + "\" from NSS database");
 
+        CryptoManager cm = CryptoManager.getInstance();
+
         try {
             PrivateKey privateKey = cm.findPrivKeyByCert(cert);
             logger.fine("Certificate \"" + nickname + "\" has private key");
 
+            PKCS12CertInfo certInfo = pkcs12.getCertInfoByNickname(nickname);
+
             PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
-            keyInfo.id = keyID;
+            keyInfo.id = certInfo.getKeyID();
             keyInfo.subjectDN = cert.getSubjectDN().toString();
 
             byte[] privateData = getEncodedKey(privateKey);
@@ -302,15 +297,17 @@ public class PKCS12Util {
 
     public void loadCertChainFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception {
 
-        logger.info("Loading certificate chain for \"" + cert.getNickname() + "\"");
-
         CryptoManager cm = CryptoManager.getInstance();
+
+        // load cert with key
+        loadCertFromNSS(pkcs12, cert);
+        loadCertKeyFromNSS(pkcs12, cert);
+
+        // load parent certs without key
         X509Certificate[] certChain = cm.buildCertificateChain(cert);
-
-        // load parent certificates only
         for (int i = 1; i < certChain.length; i++) {
             X509Certificate c = certChain[i];
-            loadCertFromNSS(pkcs12, c, false); // do not include private key
+            loadCertFromNSS(pkcs12, c);
         }
     }
 
@@ -601,14 +598,20 @@ public class PKCS12Util {
         }
     }
 
-    public void importCert(PKCS12CertInfo certInfo) throws Exception {
-
-        logger.fine("Importing certificate " + certInfo.nickname);
+    public void importCert(PKCS12 pkcs12, PKCS12CertInfo certInfo) throws Exception {
 
         CryptoManager cm = CryptoManager.getInstance();
 
-        X509Certificate cert = cm.importUserCACertPackage(
-                certInfo.cert.getEncoded(), certInfo.nickname);
+        X509Certificate cert;
+
+        if (pkcs12.getKeyInfoByID(certInfo.getKeyID()) != null) { // cert has key
+            logger.fine("Importing user CA certificate " + certInfo.nickname);
+            cert = cm.importUserCACertPackage(certInfo.cert.getEncoded(), certInfo.nickname);
+
+        } else { // cert has no key
+            logger.fine("Importing CA certificate " + certInfo.nickname);
+            cert = cm.importCACertPackage(certInfo.cert.getEncoded());
+        }
 
         if (certInfo.trustFlags != null && trustFlagsEnabled)
             setTrustFlags(cert, certInfo.trustFlags);
@@ -617,7 +620,7 @@ public class PKCS12Util {
     public void importCerts(PKCS12 pkcs12) throws Exception {
 
         for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
-            importCert(certInfo);
+            importCert(pkcs12, certInfo);
         }
     }
 
-- 
2.4.3



More information about the Pki-devel mailing list