pedrofernandes
pedrofernandes

Reputation: 16884

iText and Digital Signature

I trying create a signature in pdf using iText for JAVA and Portuguese Citizen Card (Smart Card). But when code execute MakeSignature class i receive always an error saying:

java.security.InvalidKeyException: Supplied key (sun.security.pkcs11.P11Key$P11PrivateKey) is not a RSAPrivateKey instance

I need some help here, can anyone help me?

 try {
        String pkcs11Config = "name=GemPC" + "\n" + "library=C:/WINDOWS/system32/pteidpkcs11.dll";
        ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11Config.getBytes());
        Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);

        Security.addProvider(pkcs11Provider);
        CallbackHandler cmdLineHdlr = new DialogCallbackHandler();

        KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider,
                new KeyStore.CallbackHandlerProtection(cmdLineHdlr));

        KeyStore ks = builder.getKeyStore();

        PdfReader pdf = new PdfReader(filePath);
        FileOutputStream fos = new FileOutputStream(dest);
        PdfStamper stp = PdfStamper.createSignature(pdf, fos, '\0');
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setReason("I'm the author");

        String alias = (String) ks.aliases().nextElement();

        PrivateKey pk = (PrivateKey) ks.getKey("CITIZEN SIGNATURE CERTIFICATE", null);
        Certificate chain = ks.getCertificate(alias);

        X509Certificate x509 = (X509Certificate) chain;
        x509.checkValidity();

        ExternalSignature es = new PrivateKeySignature(pk, "SHA-1", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        Certificate[] certs = new Certificate[1];
        certs[0] = chain;

        MakeSignature.signDetached(sap, digest, es, certs, null, null, null, 0, CryptoStandard.CMS);
        return dest;
    } catch (CertificateExpiredException | CertificateNotYetValidException ex) {
        Logger.getLogger(Signer.class.getName()).log(Level.SEVERE, null, ex);
        return null;
    }

Upvotes: 2

Views: 3817

Answers (1)

albciff
albciff

Reputation: 18517

If you have your private key in a smartcard (PKCS11) you cannot wrapp this key in a java.security.interfaces.RSAPrivateKey because your key material is in a secure device.

So probably you must change the provider in your code:

 ExternalSignature es = new PrivateKeySignature(pk, "SHA-1", "BC");

for:

 ExternalSignature es = new PrivateKeySignature(pk, "SHA-1", pkcs11Provider.getName());

Hope this helps,

Upvotes: 5

Related Questions