0

How to get private key from HSM to sign XML doc

I want to sign a XML document used HSM. I loaded keystore, login and get certificate, but don't know how to get privateKey to use in sign function. So what's solution for it?

My code to load and get cerificate.

String library = "mypath/cs_pkcs11_R2.dll";
StringBuilder builder = new StringBuilder();
builder.append("name=" + nameLib);
builder.append(System.getProperty("line.separator"));
builder.append("library=\"" + library + "\"");
builder.append(System.getProperty("line.separator"));
builder.append("slot=" + slot);

Init.init();

ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes());                
provider = new SunPKCS11(bais);            
Security.addProvider(provider);

keystore = KeyStore.getInstance("PKCS11");
keystore.load(null, password);

Enumeration<String> aliases = keystore.aliases();
String alias;
Certificate cert = null;

while (aliases.hasMoreElements()) {
    alias = aliases.nextElement();
    System.out.println("alias name: " + alias);
        Certificate[] certChain = keystore.getCertificateChain(alias);
                            
        if (certChain == null) {
            continue;
        }
        cert = certChain[0];
        if (cert instanceof X509Certificate) {
            // avoid expired certificate
            ((X509Certificate) cert).checkValidity();
        }               

X509Certificate c1 = (X509Certificate) cert;
PublicKey pubKey = c1.getPublicKey();

And here it code to sign XML file

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = null;
XmlSigner xmlsign = new XmlSigner();
    try {
        doc = dbf.newDocumentBuilder().parse(new FileInputStream("myPath\\xml_Input.xml"));
    } catch (IOException e) {
       e.printStackTrace();
        //System.exit(5);
    }

Element documentRoot = doc.getDocumentElement();
Element signatureElement = xmlsign.getSignatureElement(doc);
            
String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
String signatureMethod= "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
XMLSignature signature = new XMLSignature(doc, "#", signatureMethod, provider);
Transforms contentTransforms = new Transforms(doc);
contentTransforms.addTransform("http://www.w3.org/2000/09/xmldsig#enveloped-signature");
contentTransforms.addTransform("http://www.w3.org/2001/10/xml-exc-c14n#");
signature.addDocument(xmlsign.getSignatureReferenceUri("ID", documentRoot), contentTransforms, digestMethod);
signatureElement = signature.getElement();

xmlsign.addSignatureELement("LAST", documentRoot, signatureElement);
signature.sign(signKey); <- need privateKey here
xmlsign.populateKeyInfo(doc, signature.getKeyInfo(), cert);
signatureElement = xmlsign.getSignatureElement(doc);
WinLord
  • 11
  • 4
  • 1
    Mostly it's a question of restructuring your thinking. You don't "get the private key from the HSM". You send the data to the HSM, along with a reference to the key, and an operation to perform. "Sign (this data) using the key called (foo)". Some HSMs/providers will use the Certificate as a proxy for the Private key, others you have to get the key reference from the key store. – rip... Mar 12 '23 at 23:37
  • 1
    You're using CryptoServers, and I see you are building the Sun.PKCS connector string manually in the code. You probably should start by looking at getting the Private Key from the key store, not the certificate, unless JCE uses the cert as filter for retrieving the private key, which would be the next step. I'm not familiar with the JCE enough to provide the interface method for retrieving the correct private key from the key store, sorry. [note: I work for Utimaco]. – rip... Mar 12 '23 at 23:42
  • Thanks for help. I used '''keyEntry = (PrivateKey) keystore.getKey(alias, password);''' and pass this issue. – WinLord Mar 15 '23 at 08:59
  • Please then enter an answer below, so that others with the same problem see exactly what you changed in order to progress. – rip... Mar 16 '23 at 02:28
  • For anyone stumbling across this later, my 'get the private key from the key store', that private key (in the Utimaco implementation) is either an encrypted key blob (encrypted using the MBK), OR it is a key handle. While the first is the actual key, it's useless without the MBK, which only exists inside the HSM. – rip... Apr 21 '23 at 17:08

1 Answers1

1

Thanks for help. I used

keyEntry = (PrivateKey) keystore.getKey(alias, password);

and pass this issue.

WinLord
  • 11
  • 4