[Pki-devel] [PATCH] 680 Refactored PKCS12Export.

Endi Sukma Dewata edewata at redhat.com
Thu Feb 11 21:14:47 UTC 2016


The code to export NSS database into PKCS #12 file in PKCS12Export
tool has been refactored into PKCS12Util class to simplify further
enhancements.

The PKCS12Export tool has also been modified to use Java Logging
API. A default logging configuration file has been added. The
command-line wrapper has been modified to get the path to the
logging configuration file from pki.conf.

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

-- 
Endi S. Dewata
-------------- next part --------------
From de125310d5cfc6e62ba463d643e771b0bae0394d Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Tue, 9 Feb 2016 18:41:40 +0100
Subject: [PATCH] Refactored PKCS12Export.

The code to export NSS database into PKCS #12 file in PKCS12Export
tool has been refactored into PKCS12Util class to simplify further
enhancements.

The PKCS12Export tool has also been modified to use Java Logging
API. A default logging configuration file has been added. The
command-line wrapper has been modified to get the path to the
logging configuration file from pki.conf.

https://fedorahosted.org/pki/ticket/1742
---
 base/common/CMakeLists.txt                         |   1 +
 base/common/share/etc/logging.properties           |  28 +++
 base/common/share/etc/pki.conf                     |   3 +
 .../src/com/netscape/cmstools/PKCS12Export.java    | 215 ++-------------------
 .../templates/pki_java_command_wrapper.in          |   7 +-
 .../src/netscape/security/pkcs/PKCS12Util.java     | 214 ++++++++++++++++++++
 6 files changed, 273 insertions(+), 195 deletions(-)
 create mode 100644 base/common/share/etc/logging.properties
 create mode 100644 base/util/src/netscape/security/pkcs/PKCS12Util.java

diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt
index ee401f201429167b67348c35c9c89c3d52b3c3fd..121392512de0b4695c5508fa432bca4f18d167cf 100644
--- a/base/common/CMakeLists.txt
+++ b/base/common/CMakeLists.txt
@@ -13,6 +13,7 @@ configure_file(
 
 install(
     FILES
+        ${CMAKE_CURRENT_SOURCE_DIR}/share/etc/logging.properties
         ${CMAKE_CURRENT_BINARY_DIR}/share/etc/pki.conf
     DESTINATION
         ${DATA_INSTALL_DIR}/etc/
diff --git a/base/common/share/etc/logging.properties b/base/common/share/etc/logging.properties
new file mode 100644
index 0000000000000000000000000000000000000000..bd5b5b627903e0daa2c8b70a0569a5cc78321765
--- /dev/null
+++ b/base/common/share/etc/logging.properties
@@ -0,0 +1,28 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+# Modifications: configuration parameters
+# --- END COPYRIGHT BLOCK ---
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+handlers = java.util.logging.ConsoleHandler
+
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format = %4$s: %5$s%6$s%n
+
+.level = WARNING
diff --git a/base/common/share/etc/pki.conf b/base/common/share/etc/pki.conf
index a43d1d6c144379d655da06f77e8b5056bc787e6a..57cb83e5a5087f4d8efea2743a1b3b7cc95c0489 100644
--- a/base/common/share/etc/pki.conf
+++ b/base/common/share/etc/pki.conf
@@ -1,2 +1,5 @@
 # JNI jar file location
 JNI_JAR_DIR=/usr/lib/java
+
+# logging configuration location
+LOGGING_CONFIG=/usr/share/pki/etc/logging.properties
diff --git a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
index b8999fe99f57af644643011345323484c7b6e4ac..c23aa1fe1aa00ff43eb3c1da46bb8811c3ecbe31 100644
--- a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
+++ b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
@@ -18,39 +18,16 @@
 package com.netscape.cmstools;
 
 import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
 import java.io.FileReader;
-import java.security.MessageDigest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import org.mozilla.jss.CryptoManager;
-import org.mozilla.jss.asn1.ASN1Util;
-import org.mozilla.jss.asn1.ASN1Value;
-import org.mozilla.jss.asn1.BMPString;
-import org.mozilla.jss.asn1.OCTET_STRING;
-import org.mozilla.jss.asn1.SEQUENCE;
-import org.mozilla.jss.asn1.SET;
-import org.mozilla.jss.crypto.Cipher;
-import org.mozilla.jss.crypto.CryptoStore;
 import org.mozilla.jss.crypto.CryptoToken;
-import org.mozilla.jss.crypto.EncryptionAlgorithm;
-import org.mozilla.jss.crypto.IVParameterSpec;
-import org.mozilla.jss.crypto.KeyGenAlgorithm;
-import org.mozilla.jss.crypto.KeyGenerator;
-import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
-import org.mozilla.jss.crypto.PBEAlgorithm;
-import org.mozilla.jss.crypto.SymmetricKey;
-import org.mozilla.jss.crypto.X509Certificate;
-import org.mozilla.jss.pkcs12.AuthenticatedSafes;
-import org.mozilla.jss.pkcs12.CertBag;
-import org.mozilla.jss.pkcs12.PFX;
-import org.mozilla.jss.pkcs12.PasswordConverter;
-import org.mozilla.jss.pkcs12.SafeBag;
-import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
-import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
 import org.mozilla.jss.util.Password;
 
+import netscape.security.pkcs.PKCS12Util;
+
 /**
  * Tool for creating PKCS12 file
  *
@@ -61,7 +38,7 @@ import org.mozilla.jss.util.Password;
  */
 public class PKCS12Export {
 
-    boolean debug;
+    private static Logger logger = Logger.getLogger(PKCS12Export.class.getName());
 
     String databaseDirectory;
     String databasePasswordFilename;
@@ -69,14 +46,6 @@ public class PKCS12Export {
     String pkcs12PasswordFilename;
     String pkcs12OutputFilename;
 
-    public boolean isDebug() {
-        return debug;
-    }
-
-    public void setDebug(boolean debug) {
-        this.debug = debug;
-    }
-
     public String getDatabaseDirectory() {
         return databaseDirectory;
     }
@@ -108,152 +77,9 @@ public class PKCS12Export {
         this.pkcs12OutputFilename = pkcs12OutputFilename;
     }
 
-    void debug(String s) {
-        if (debug)
-            System.out.println("PKCS12Export: " + s);
-    }
-
-    byte[] getEncodedKey(org.mozilla.jss.crypto.PrivateKey pkey) throws Exception {
-
-        CryptoManager cm = CryptoManager.getInstance();
-        CryptoToken token = cm.getInternalKeyStorageToken();
-
-        KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
-        SymmetricKey sk = kg.generate();
-
-        KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
-        byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
-        IVParameterSpec param = new IVParameterSpec(iv);
-        wrapper.initWrap(sk, param);
-        byte[] enckey = wrapper.wrap(pkey);
-
-        Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
-        c.initDecrypt(sk, param);
-        return c.doFinal(enckey);
-    }
-
-    void addKeyBag(org.mozilla.jss.crypto.PrivateKey pkey, X509Certificate x509cert,
-            Password pass, byte[] localKeyId, SEQUENCE safeContents) throws Exception {
-
-        PasswordConverter passConverter = new PasswordConverter();
-        byte salt[] = { 0x01, 0x01, 0x01, 0x01 };
-        byte[] priData = getEncodedKey(pkey);
-
-        PrivateKeyInfo pki = (PrivateKeyInfo)
-                ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData);
-
-        ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
-                PBEAlgorithm.PBE_SHA1_DES3_CBC,
-                pass, salt, 1, passConverter, pki);
-
-        SET keyAttrs = createBagAttrs(
-                x509cert.getSubjectDN().toString(), localKeyId);
-
-        SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG,
-                key, keyAttrs);
-
-        safeContents.addElement(keyBag);
-    }
-
-    byte[] addCertBag(X509Certificate x509cert, String nickname,
-            SEQUENCE safeContents) throws Exception {
-
-        ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
-        byte[] localKeyId = createLocalKeyId(x509cert);
-
-        SET certAttrs = null;
-        if (nickname != null)
-            certAttrs = createBagAttrs(nickname, localKeyId);
-
-        SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
-                new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs);
-
-        safeContents.addElement(certBag);
-
-        return localKeyId;
-    }
-
-    byte[] createLocalKeyId(X509Certificate cert) throws Exception {
-
-        // SHA1 hash of the X509Cert der encoding
-        byte certDer[] = cert.getEncoded();
-
-        MessageDigest md = MessageDigest.getInstance("SHA");
-
-        md.update(certDer);
-        return md.digest();
-    }
-
-    SET createBagAttrs(String nickName, byte localKeyId[])
-            throws Exception {
-
-        SET attrs = new SET();
-        SEQUENCE nickNameAttr = new SEQUENCE();
-
-        nickNameAttr.addElement(SafeBag.FRIENDLY_NAME);
-        SET nickNameSet = new SET();
-
-        nickNameSet.addElement(new BMPString(nickName));
-        nickNameAttr.addElement(nickNameSet);
-        attrs.addElement(nickNameAttr);
-        SEQUENCE localKeyAttr = new SEQUENCE();
-
-        localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
-        SET localKeySet = new SET();
-
-        localKeySet.addElement(new OCTET_STRING(localKeyId));
-        localKeyAttr.addElement(localKeySet);
-        attrs.addElement(localKeyAttr);
-
-        return attrs;
-    }
-
-    public byte[] generatePKCS12Data(Password password) throws Exception {
-
-        debug("Generating PKCS #12 data");
-
-        CryptoManager cm = CryptoManager.getInstance();
-        CryptoToken token = cm.getInternalKeyStorageToken();
-        CryptoStore store = token.getCryptoStore();
-
-        X509Certificate[] certs = store.getCertificates();
-
-        SEQUENCE encSafeContents = new SEQUENCE();
-        SEQUENCE safeContents = new SEQUENCE();
-
-        for (int i = 0; i < certs.length; i++) {
-            String nickname = certs[i].getNickname();
-            debug(" * Certificate: " + nickname);
-            try {
-                org.mozilla.jss.crypto.PrivateKey prikey = cm.findPrivKeyByCert(certs[i]);
-
-                debug("   Private key exists");
-                byte localKeyId[] =
-                        addCertBag(certs[i], nickname, safeContents);
-                addKeyBag(prikey, certs[i], password, localKeyId, encSafeContents);
-
-            } catch (org.mozilla.jss.crypto.ObjectNotFoundException e) {
-                debug("   Private key does not exist");
-                addCertBag(certs[i], null, safeContents);
-            }
-        }
-
-        AuthenticatedSafes authSafes = new AuthenticatedSafes();
-        authSafes.addSafeContents(safeContents);
-        authSafes.addSafeContents(encSafeContents);
-
-        PFX pfx = new PFX(authSafes);
-        pfx.computeMacData(password, null, 5);
-
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        pfx.encode(bos);
-
-        return bos.toByteArray();
-    }
-
     public void initDatabase() throws Exception {
 
-        debug("Initializing database in " + databaseDirectory);
+        logger.info("Initializing database in " + databaseDirectory);
 
         CryptoManager.InitializationValues vals =
                 new CryptoManager.InitializationValues(
@@ -263,7 +89,7 @@ public class PKCS12Export {
         CryptoManager cm = CryptoManager.getInstance();
         CryptoToken token = cm.getInternalKeyStorageToken();
 
-        debug("Reading database password from " + databasePasswordFilename);
+        logger.info("Reading database password from " + databasePasswordFilename);
 
         String line;
         try (BufferedReader in = new BufferedReader(new FileReader(databasePasswordFilename))) {
@@ -274,7 +100,7 @@ public class PKCS12Export {
         }
         Password password = new Password(line.toCharArray());
 
-        debug("Logging into security token");
+        logger.info("Logging into security token");
 
         try {
             token.login(password);
@@ -285,7 +111,7 @@ public class PKCS12Export {
 
     public void exportData() throws Exception {
 
-        debug("Reading PKCS #12 password from " + pkcs12PasswordFilename);
+        logger.info("Reading PKCS #12 password from " + pkcs12PasswordFilename);
 
         String line;
         try (BufferedReader in = new BufferedReader(new FileReader(pkcs12PasswordFilename))) {
@@ -296,18 +122,14 @@ public class PKCS12Export {
         }
         Password password = new Password(line.toCharArray());
 
-        byte[] data;
+        logger.info("Exporting NSS database into " + pkcs12OutputFilename);
+
         try {
-            data = generatePKCS12Data(password);
+            PKCS12Util util = new PKCS12Util();
+            util.exportData(pkcs12OutputFilename, password);
         } finally {
             password.clear();
         }
-
-        debug("Storing PKCS #12 data into " + pkcs12OutputFilename);
-
-        try (FileOutputStream fos = new FileOutputStream(pkcs12OutputFilename)) {
-            fos.write(data);
-        }
     }
 
     public static void printUsage() {
@@ -355,11 +177,16 @@ public class PKCS12Export {
             }
         }
 
+        if (debug) {
+            Logger.getLogger("org.dogtagpki").setLevel(Level.FINE);
+            Logger.getLogger("com.netscape").setLevel(Level.FINE);
+            Logger.getLogger("netscape").setLevel(Level.FINE);
+        }
+
         // TODO: validate parameters
 
         try {
             PKCS12Export tool = new PKCS12Export();
-            tool.setDebug(debug);
             tool.setDatabaseDirectory(databaseDirectory);
             tool.setDatabasePasswordFilename(databasePasswordFilename);
             tool.setPkcs12PasswordFilename(pkcs12PasswordFilename);
@@ -370,9 +197,9 @@ public class PKCS12Export {
 
         } catch (Exception e) {
             if (debug) {
-                e.printStackTrace();
+                logger.log(Level.SEVERE, "Unable to export PKCS #12 file", e);
             } else {
-                System.err.println("ERROR: " + e);
+                logger.severe("Unable to export PKCS #12 file: " + e.getMessage());
             }
             System.exit(1);
         }
diff --git a/base/java-tools/templates/pki_java_command_wrapper.in b/base/java-tools/templates/pki_java_command_wrapper.in
index 404bcf0a12914f714b59f9e8fe286fd75a42367a..56ca9f1fcbdd95a2e5e2be11e1ff42c0d1f0b22b 100644
--- a/base/java-tools/templates/pki_java_command_wrapper.in
+++ b/base/java-tools/templates/pki_java_command_wrapper.in
@@ -124,12 +124,17 @@ CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
 CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP}
 export CP
 
+LOGGING_CONFIG=`source /usr/share/pki/etc/pki.conf && source /etc/pki/pki.conf && echo $LOGGING_CONFIG`
 
 ###############################################################################
 ##  (6) Execute the java command specified by this java command wrapper      ##
 ##      based upon the preset LD_LIBRARY_PATH and CP environment variables.  ##
 ###############################################################################
 
-${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@"
+${JAVA} ${JAVA_OPTIONS} \
+  -cp ${CP} \
+  -Djava.util.logging.config.file=${LOGGING_CONFIG} \
+  com.netscape.cmstools.${COMMAND} "$@"
+
 exit $?
 
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..63051858e05a23e2f8b39503e2eaad07ad7dae1a
--- /dev/null
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -0,0 +1,214 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program 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 for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2016 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package netscape.security.pkcs;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.security.MessageDigest;
+import java.util.logging.Logger;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.BMPString;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.Cipher;
+import org.mozilla.jss.crypto.CryptoStore;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs12.AuthenticatedSafes;
+import org.mozilla.jss.pkcs12.CertBag;
+import org.mozilla.jss.pkcs12.PFX;
+import org.mozilla.jss.pkcs12.PasswordConverter;
+import org.mozilla.jss.pkcs12.SafeBag;
+import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
+import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
+import org.mozilla.jss.util.Password;
+
+public class PKCS12Util {
+
+    private static Logger logger = Logger.getLogger(PKCS12Util.class.getName());
+
+    PFX pfx;
+
+    byte[] getEncodedKey(PrivateKey privateKey) throws Exception {
+
+        CryptoManager cm = CryptoManager.getInstance();
+        CryptoToken token = cm.getInternalKeyStorageToken();
+
+        KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+        SymmetricKey sk = kg.generate();
+
+        KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
+        byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+        IVParameterSpec param = new IVParameterSpec(iv);
+        wrapper.initWrap(sk, param);
+        byte[] enckey = wrapper.wrap(privateKey);
+
+        Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
+        c.initDecrypt(sk, param);
+        return c.doFinal(enckey);
+    }
+
+    public void addKeyBag(PrivateKey privateKey, X509Certificate x509cert,
+            Password pass, byte[] localKeyID, SEQUENCE safeContents) throws Exception {
+
+        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(
+                PBEAlgorithm.PBE_SHA1_DES3_CBC,
+                pass, salt, 1, passConverter, pki);
+
+        SET keyAttrs = createBagAttrs(
+                x509cert.getSubjectDN().toString(), localKeyID);
+
+        SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG,
+                key, keyAttrs);
+
+        safeContents.addElement(keyBag);
+    }
+
+    public byte[] addCertBag(X509Certificate x509cert, String nickname,
+            SEQUENCE safeContents) throws Exception {
+
+        ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
+        byte[] localKeyID = createLocalKeyID(x509cert);
+
+        SET certAttrs = null;
+        if (nickname != null)
+            certAttrs = createBagAttrs(nickname, localKeyID);
+
+        SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
+                new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs);
+
+        safeContents.addElement(certBag);
+
+        return localKeyID;
+    }
+
+    byte[] createLocalKeyID(X509Certificate cert) throws Exception {
+
+        // SHA1 hash of the X509Cert DER encoding
+        byte[] certDer = cert.getEncoded();
+
+        MessageDigest md = MessageDigest.getInstance("SHA");
+
+        md.update(certDer);
+        return md.digest();
+    }
+
+    SET createBagAttrs(String nickname, byte localKeyID[])
+            throws Exception {
+
+        SET attrs = new SET();
+        SEQUENCE nicknameAttr = new SEQUENCE();
+
+        nicknameAttr.addElement(SafeBag.FRIENDLY_NAME);
+        SET nicknameSet = new SET();
+
+        nicknameSet.addElement(new BMPString(nickname));
+        nicknameAttr.addElement(nicknameSet);
+        attrs.addElement(nicknameAttr);
+        SEQUENCE localKeyAttr = new SEQUENCE();
+
+        localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
+        SET localKeySet = new SET();
+
+        localKeySet.addElement(new OCTET_STRING(localKeyID));
+        localKeyAttr.addElement(localKeySet);
+        attrs.addElement(localKeyAttr);
+
+        return attrs;
+    }
+
+    public void loadFromNSS(Password password) throws Exception {
+
+        logger.info("Loading data from NSS database");
+
+        CryptoManager cm = CryptoManager.getInstance();
+        CryptoToken token = cm.getInternalKeyStorageToken();
+        CryptoStore store = token.getCryptoStore();
+
+        SEQUENCE encSafeContents = new SEQUENCE();
+        SEQUENCE safeContents = new SEQUENCE();
+
+        logger.fine("Loading certificates:");
+
+        X509Certificate[] certs = store.getCertificates();
+
+        for (X509Certificate cert : certs) {
+            String nickname = cert.getNickname();
+
+            try {
+                PrivateKey prikey = cm.findPrivKeyByCert(cert);
+                logger.fine(" - cert " + nickname + " with private key");
+
+                byte localKeyID[] = addCertBag(cert, nickname, safeContents);
+                addKeyBag(prikey, cert, password, localKeyID, encSafeContents);
+
+            } catch (ObjectNotFoundException e) {
+                logger.fine(" - cert " + nickname + " without private key");
+                addCertBag(cert, nickname, safeContents);
+            }
+        }
+
+        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.computeMacData(password, null, 5);
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        pfx.encode(bos);
+        byte[] data = bos.toByteArray();
+
+        try (FileOutputStream fos = new FileOutputStream(filename)) {
+            fos.write(data);
+        }
+    }
+
+    public void exportData(String filename, Password password) throws Exception {
+
+        loadFromNSS(password);
+        storeIntoPKCS12(filename, password);
+    }
+}
-- 
2.4.3



More information about the Pki-devel mailing list