diff options
11 files changed, 308 insertions, 214 deletions
diff --git a/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java b/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java index 5d698bea3..bcc4252ba 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/PKCS12CertCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java index a83fbac4f..807404749 100644 --- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertCLI.java @@ -40,6 +40,10 @@ public class PKCS12CertCLI extends CLI { System.out.println(" Subject DN: " + certInfo.getCert().getSubjectDN()); System.out.println(" Issuer DN: " + certInfo.getCert().getIssuerDN()); + if (certInfo.getKeyID() != null) { + System.out.println(" Key ID: " + certInfo.getKeyID().toString(16)); + } + if (certInfo.getTrustFlags() != null) { System.out.println(" Trust flags: " + certInfo.getTrustFlags()); } 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 3aec7a6b2..8c6fb8845 100644 --- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12CertFindCLI.java @@ -18,17 +18,21 @@ package com.netscape.cmstools.pkcs12; -import java.util.List; +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.ParseException; +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.PKCS12CertInfo; import netscape.security.pkcs.PKCS12Util; @@ -52,7 +56,15 @@ public class PKCS12CertFindCLI extends CLI { option.setArgName("path"); options.addOption(option); - options.addOption("v", "verbose", false, "Run in verbose mode."); + option = new Option(null, "pkcs12-password", true, "PKCS #12 password"); + option.setArgName("password"); + options.addOption(option); + + option = new Option(null, "pkcs12-password-file", true, "PKCS #12 password file"); + option.setArgName("path"); + options.addOption(option); + + options.addOption("v", "verbose", false, "Run in verbose mode."); options.addOption(null, "debug", false, "Run in debug mode."); options.addOption(null, "help", false, "Show help message."); } @@ -101,10 +113,36 @@ public class PKCS12CertFindCLI extends CLI { System.exit(-1); } - PKCS12Util util = new PKCS12Util(); - util.loadFromPKCS12(filename); + String passwordString = cmd.getOptionValue("pkcs12-password"); + + if (passwordString == null) { + + String passwordFile = cmd.getOptionValue("pkcs12-password-file"); + if (passwordFile != null) { + try (BufferedReader in = new BufferedReader(new FileReader(passwordFile))) { + passwordString = in.readLine(); + } + } + } + + if (passwordString == null) { + System.err.println("Error: Missing PKCS #12 password."); + printHelp(); + System.exit(-1); + } + + Password password = new Password(passwordString.toCharArray()); - List<PKCS12CertInfo> certInfos = util.getCertInfos(); + Collection<PKCS12CertInfo> certInfos; + try { + PKCS12Util util = new PKCS12Util(); + PKCS12 pkcs12 = util.loadFromFile(filename, password); + + certInfos = pkcs12.getCertInfos(); + + } finally { + password.clear(); + } 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 e5acd0600..174748262 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 4e9ed23fc..3e42efcbc 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 d859fcea1..bce1e137b 100644 --- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java @@ -34,10 +34,9 @@ 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(" Key ID: " + keyInfo.getID().toString(16)); + System.out.println(" Subject DN: " + keyInfo.getSubjectDN()); + 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 3bda750a4..92b9cf132 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 df7fde447..da4023f12 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 d1a9cc9fc..3ac643eb1 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 ff3f2a289..c7e84f01f 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 9d852cb6a..c5173a208 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); - - SET keyAttrs = createKeyBagAttrs( - x509cert.getSubjectDN().toString(), localKeyID); + password, salt, 1, passConverter, keyInfo.privateKeyInfo); - SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, - key, keyAttrs); + SET keyAttrs = createKeyBagAttrs(keyInfo); - 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 localKeyID = createLocalKeyID(x509cert); - - String trustFlags = null; - if (trustFlagsEnabled) { - trustFlags = getTrustFlags(x509cert); - logger.fine("Trust flags: " + trustFlags); - } + ASN1Value cert = new OCTET_STRING(certInfo.cert.getEncoded()); + CertBag certBag = new CertBag(CertBag.X509_CERT_TYPE, cert); - SET certAttrs = createCertBagAttrs(nickname, localKeyID, trustFlags); + SET certAttrs = createCertBagAttrs(certInfo); - SafeBag certBag = new SafeBag(SafeBag.CERT_BAG, - new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs); - - safeContents.addElement(certBag); - - return localKeyID; + 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(1, 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 localKeyID, 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(localKeyID.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(); - SEQUENCE safeContents = new SEQUENCE(); + PKCS12 pkcs12 = new PKCS12(); - logger.fine("Loading certificates"); + for (X509Certificate cert : store.getCertificates()) { + loadCertAndKeyFromNSS(pkcs12, cert); + } - X509Certificate[] certs = store.getCertificates(); + return pkcs12; + } - for (X509Certificate cert : certs) { - String nickname = cert.getNickname(); + public void loadCertAndKeyFromNSS(PKCS12 pkcs12, X509Certificate cert) throws Exception { - try { - PrivateKey prikey = cm.findPrivKeyByCert(cert); - logger.fine("Found certificate " + nickname + " with private key"); + String nickname = cert.getNickname(); + logger.info("Loading certificate \"" + nickname + "\" from NSS database"); - BigInteger localKeyID = addCertBag(cert, nickname, safeContents); - addKeyBag(prikey, cert, password, localKeyID, encSafeContents); + CryptoManager cm = CryptoManager.getInstance(); - } catch (ObjectNotFoundException e) { - logger.fine("Found certificate " + nickname + " without private key"); - addCertBag(cert, nickname, safeContents); - } - } + BigInteger keyID = createLocalKeyID(cert); - AuthenticatedSafes authSafes = new AuthenticatedSafes(); - authSafes.addSafeContents(safeContents); - authSafes.addSafeContents(encSafeContents); + 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"); - pfx = new PFX(authSafes); + 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 storeIntoPKCS12(String filename, Password password) throws Exception { + public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception { logger.info("Storing data into PKCS #12 file"); + SEQUENCE safeContents = new SEQUENCE(); + + for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { + addCertBag(certInfo, safeContents); + } + + SEQUENCE encSafeContents = new SEQUENCE(); + + for (PKCS12KeyInfo keyInfo : pkcs12.getKeyInfos()) { + addKeyBag(keyInfo, password, encSafeContents); + } + + AuthenticatedSafes authSafes = new AuthenticatedSafes(); + authSafes.addSafeContents(safeContents); + authSafes.addSafeContents(encSafeContents); + + PFX pfx = new PFX(authSafes); pfx.computeMacData(password, null, 5); ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -307,55 +317,49 @@ 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); - logger.fine("Found private key " + subjectDN); + } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { - PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(); - keyInfo.encPrivateKeyInfo = encPrivateKeyInfo; - keyInfo.privateKeyInfo = privateKeyInfo; - keyInfo.subjectDN = subjectDN; + SET values = attr.getValues(); + ANY value = (ANY) values.elementAt(0); - return keyInfo; - } + ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); + OCTET_STRING keyID = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); + + keyInfo.id = new BigInteger(1, keyID.toByteArray()); + logger.fine("Key ID: " + keyInfo.id.toString(16)); + } + } - public PKCS12KeyInfo getKeyInfo(SafeBag bag) throws Exception { - return getKeyInfo(bag, null); + logger.fine("Found private key " + keyInfo.subjectDN); + + return keyInfo; } public PKCS12CertInfo getCertInfo(SafeBag bag) throws Exception { @@ -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(1, keyID.toByteArray()); + logger.fine("Key ID: " + 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,16 +421,15 @@ 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++) { - SEQUENCE contents = safes.getSafeContentsAt(null, i); + SEQUENCE contents = safes.getSafeContentsAt(password, i); for (int j = 0; j < contents.size(); j++) { @@ -424,27 +439,20 @@ 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, Password password) throws Exception { logger.fine("Getting certificates"); - List<PKCS12CertInfo> certInfos = new ArrayList<PKCS12CertInfo>(); AuthenticatedSafes safes = pfx.getAuthSafes(); for (int i = 0; i < safes.getSize(); i++) { - SEQUENCE contents = safes.getSafeContentsAt(null, i); + SEQUENCE contents = safes.getSafeContentsAt(password, i); for (int j = 0; j < contents.size(); j++) { @@ -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,25 @@ 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(); + + 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, password); + + return pkcs12; + } + + public PKCS12 loadFromFile(String filename) throws Exception { + return loadFromFile(filename, null); } public PrivateKey.Type getPrivateKeyType(PublicKey publicKey) { @@ -480,40 +504,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 { - - PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo; - - if (privateKeyInfo == null) { - privateKeyInfo = keyInfo.encPrivateKeyInfo.decrypt(password, new PasswordConverter()); - } + PKCS12 pkcs12, + PKCS12KeyInfo keyInfo) throws Exception { - String subjectDN = keyInfo.subjectDN; + logger.fine("Importing private key " + keyInfo.subjectDN); - logger.fine("Importing private key " + subjectDN); + PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo; // 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 +538,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 +565,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; - - if (nickname == null) { - xcert = cm.importCACertPackage(cert.getEncoded()); - - } else { - xcert = cm.importUserCACertPackage(cert.getEncoded(), nickname); - } - - if (trustFlags != null && trustFlagsEnabled) - setTrustFlags(xcert, trustFlags); + X509Certificate cert = cm.importUserCACertPackage( + certInfo.cert.getEncoded(), certInfo.nickname); - return xcert; + if (certInfo.trustFlags != null && trustFlagsEnabled) + setTrustFlags(cert, certInfo.trustFlags); } - public void importCerts(List<PKCS12CertInfo> certInfos) throws Exception { + public void importCerts(PKCS12 pkcs12) throws Exception { - for (PKCS12CertInfo certInfo : certInfos) { - importCert(certInfo.cert, certInfo.nickname, certInfo.trustFlags); + for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { + importCert(certInfo); } } - public void verifyPassword(Password password) throws Exception { - - StringBuffer reason = new StringBuffer(); - boolean valid = pfx.verifyAuthSafes(password, reason); - - if (!valid) { - throw new Exception(reason.toString()); - } - } - - 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); } } |