Introduction
"Network Security Services (NSS) is a set of libraries designed to support cross-platform development of security-enabled client and server applications. Applications built with NSS can support SSL v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509 v3 certificates, and other security standards." [https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS]
And NSS DB is a binary storage for certificates and keys on disk. In this blog I will show you how to read that NSS DB from Java with SunPKCS11
Prerequisite
Install nss-tools on Fedora, RHEL, CentOS.
$ sudo yum install -y nss-tools
NSS DB Format
NSS DB has two types of databases:
- "The legacy security databases (cert8.db, key3.db, and secmod.db)"
- "And new SQLite databases (cert9.db, key4.db, and pkcs11.txt)"
Reference:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_certutil
Java according to official SunPKCS11 only supports the legacy database, but as we will see later, it does supports the new SQLite database.
"nssSecmodDirectory directory containing the NSS DB files The full pathname of the directory containing the NSS configuration and key information (secmod.db, key3.db, and cert8.db). This directive must be specified unless NSS has already been initialized by another component (see above) or NSS is used without database files as described below." [https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html#NSS]
The Legacy NSS DB
Lets create a new legacy NSS DB. Note that we explicitly use the prefix dbm: when we create the DB.
$ mkdir nssdb_dbm
$ echo "redhat123" > password.txt
$ certutil -N -d dbm:nssdb_dbm -f password.txt
Now lets add a self-signed certificate and a matching private key in our legacy NSS DB.
$ certutil -S -n mkk -s 'CN=MKK, O=MKK Consultancy, C=SE' -t ',,' -k rsa -g 2048 -x -v 24 -f password.txt -d dbm:nssdb_dbm -Z SHA256
Then verify the certificate, keys and the legacy NSS DB files.
$ certutil -L -d dbm:nssdb_dbm
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
mkk u,u,u
$ certutil -K -d dbm:nssdb_dbm -f password.txt
certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
< 0> rsa bc4e3491a87df6cd843f551a3f2bb714ecfa2bf7 NSS Certificate DB:mkk
$ ll nssdb_dbm/
total 80
-rw-------. 1 magnuskkarlsson magnuskkarlsson 65536 Sep 12 22:59 cert8.db
-rw-------. 1 magnuskkarlsson magnuskkarlsson 16384 Sep 12 22:59 key3.db
-rw-------. 1 magnuskkarlsson magnuskkarlsson 16384 Sep 12 22:58 secmod.db
Now lets write our Java program
package se.magnuskkarlsson.example.nssdb;
import java.security.Key;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
// https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html#NSS
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_certutil
/*
certutil supports two types of databases: the legacy
security databases (cert8.db, key3.db, and secmod.db)
and new SQLite databases (cert9.db, key4.db, and
pkcs11.txt).
*/
public class NSSTool {
public static char[] password = "redhat123".toCharArray();
public static void main(String[] args) throws Exception {
String configName = "/home/magnuskkarlsson/NetBeansProjects/example-nssdb/pkcs11.cfg";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
Security.addProvider(p);
KeyStore ks = KeyStore.getInstance("PKCS11", p); //p is the provider created above
ks.load(null, password);
System.out.println("Successfully loaded NSS DB.");
for (Enumeration aliases = ks.aliases(); aliases.hasMoreElements();) {
String alias = aliases.nextElement();
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
Key key = ks.getKey(alias, password);
System.out.println(key);
System.out.println(cert);
System.out.println("------------------------------");
}
}
}
name = NSScrypto
# nssLibraryDirectory =
nssSecmodDirectory = /home/magnuskkarlsson/NetBeansProjects/example-nssdb/nssdb_dbm
nssDbMode = readWrite
nssModule = keystore
The New SQLite NSS DB
Though the official Java documentation does state that it does not support the new format, it can read the new format, but with one hack and that is you need to create an empty secmod.db file.
But first lets create a new NSS DB with the new SQLite format, we explicitly use the prefix sql: when creating the new NSS DB.
$ mkdir nssdb_sql
$ echo "redhat123" > password.txt
$ certutil -N -d sql:nssdb_sql -f password.txt
And then the fix.
$ touch nssdb_sql/secmod.db
And finally lets create a self-signed certificate, so we have something to read.
$ certutil -S -n mkk -s 'CN=MKK, O=MKK Consultancy, C=SE' -t ',,' -k rsa -g 2048 -x -v 24 -f password.txt -d sql:nssdb_sql -Z SHA256
We now have the following files.
$ ll nssdb_sql/
total 68
-rw-------. 1 magnuskkarlsson magnuskkarlsson 28672 Sep 12 23:03 cert9.db
-rw-------. 1 magnuskkarlsson magnuskkarlsson 36864 Sep 12 23:03 key4.db
-rw-------. 1 magnuskkarlsson magnuskkarlsson 420 Sep 12 23:02 pkcs11.txt
-rw-rw-r--. 1 magnuskkarlsson magnuskkarlsson 0 Sep 12 23:04 secmod.db
The Java code stays the same, but we need to update the pkcs11.cfg with our new path
name = NSScrypto
# nssLibraryDirectory =
nssSecmodDirectory = /home/magnuskkarlsson/NetBeansProjects/example-nssdb/nssdb_sql
nssDbMode = readWrite
nssModule = keystore
No comments:
Post a Comment