Problems copying PKCS # 11

I am trying to sign a pdf file using a smart card and PKCS # 11. I am linking the right .dll and I am making the configuration file dynamically, but I ran into configuration problems.

String config = "name=zz\n" + "library=" + DLL + "\n" + "slotListIndex = " + getSlotsWithTokens(DLL)[0]; ByteArrayInputStream pot = new ByteArrayInputStream(config.getBytes()); Provider providerPKCS11 = new SunPKCS11(pot); 

and I get the following error:

 Exception in thread "main" java.security.ProviderException: Initialization failed at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:376) at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:107) at smartCardPKCS11.scPKCS11.main(scPKCS11.java:56) Caused by: java.security.ProviderException: slotListIndex is 52481 but token only has 10 slots at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:357) ... 2 more 

the bit is tangled in the whole slot. Can someone help me?

What my getSlotsWithTokens looks like:

 public static long[] getSlotsWithTokens(String libraryPath) throws IOException{ CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS(); String functionList = "C_GetFunctionList"; initArgs.flags = 0; PKCS11 tmpPKCS11 = null; long[] slotList = null; try { try { tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, false); } catch (IOException ex) { ex.printStackTrace(); throw ex; } } catch (PKCS11Exception e) { try { initArgs = null; tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, true); } catch (IOException ex) { ex.printStackTrace(); } catch (PKCS11Exception ex) { ex.printStackTrace(); } } try { slotList = tmpPKCS11.C_GetSlotList(true); for (long slot : slotList){ CK_TOKEN_INFO tokenInfo = tmpPKCS11.C_GetTokenInfo(slot); System.out.println("slot: "+slot+"\nmanufacturerID: " + String.valueOf(tokenInfo.manufacturerID) + "\nmodel: " + String.valueOf(tokenInfo.model)); } } catch (PKCS11Exception ex) { ex.printStackTrace(); } catch (Throwable t) { t.printStackTrace(); } return slotList; } 

UPDATED version:

So, I made the changes as @albciff suggested: here is the full code:

 import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.security.pkcs11.SunPKCS11; import sun.security.pkcs11.wrapper.CK_C_INITIALIZE_ARGS; import sun.security.pkcs11.wrapper.CK_TOKEN_INFO; import sun.security.pkcs11.wrapper.PKCS11; import sun.security.pkcs11.wrapper.PKCS11Exception; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Rectangle; import com.itextpdf.text.log.LoggerFactory; import com.itextpdf.text.log.SysoLogger; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfSignatureAppearance; import com.itextpdf.text.pdf.PdfStamper; import com.itextpdf.text.pdf.security.BouncyCastleDigest; import com.itextpdf.text.pdf.security.CrlClient; import com.itextpdf.text.pdf.security.CrlClientOnline; import com.itextpdf.text.pdf.security.DigestAlgorithms; import com.itextpdf.text.pdf.security.ExternalDigest; import com.itextpdf.text.pdf.security.ExternalSignature; import com.itextpdf.text.pdf.security.MakeSignature; import com.itextpdf.text.pdf.security.PrivateKeySignature; import com.itextpdf.text.pdf.security.TSAClient; import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard; import com.itextpdf.text.pdf.security.OcspClient; import com.itextpdf.text.pdf.security.OcspClientBouncyCastle; public class sPKCS11 { public static final String SRC = "src/Test.pdf"; public static final String DEST = "src/scTest.pdf"; public static final String DLL = "c:/windows/system32/aetpkss1.dll"; public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException { LoggerFactory.getInstance().setLogger(new SysoLogger()); String pkcs11ConfigSettings = "name=aet\n"+"library="+DLL; byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes(); ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes); SunPKCS11 pkcs11 = new SunPKCS11(confStream); Security.addProvider(pkcs11); BouncyCastleProvider providerBC = new BouncyCastleProvider(); Security.addProvider(providerBC); KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, null); Enumeration<String> aliases = ks.aliases(); while (aliases.hasMoreElements()) { System.out.println(aliases.nextElement()); } // alias is here just for the sake of keeping things private smartcardsign(pkcs11.getName(), ks, "alias"); } public static void smartcardsign(String provider, KeyStore ks, String alias) throws GeneralSecurityException, IOException, DocumentException { PrivateKey pk = (PrivateKey)ks.getKey(alias, null); Certificate[] chain = ks.getCertificateChain(alias); OcspClient ocspClient = new OcspClientBouncyCastle(); List<CrlClient> crlList = new ArrayList<CrlClient>(); crlList.add(new CrlClientOnline(chain)); scPKCS11 app = new scPKCS11(); app.sign(SRC, String.format(DEST, alias), chain, pk, DigestAlgorithms.SHA256, provider, CryptoStandard.CMS, "Test", "B", crlList, ocspClient, null, 0); } public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm, String provider, CryptoStandard subfilter, String reason, String location, Collection<CrlClient> crlList, OcspClient ocspClient, TSAClient tsaClient, int estimatedSize) throws GeneralSecurityException, IOException, DocumentException { // Creating the reader and the stamper PdfReader reader = new PdfReader(src); FileOutputStream os = new FileOutputStream(dest); PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true); // Creating the appearance PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setReason(reason); appearance.setLocation(location); appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED); // Creating the signature ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider); ExternalDigest digest = new BouncyCastleDigest(); MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); } } 

And this is a new msg error:

 Exception in thread "main" java.security.KeyStoreException: PKCS11 not found at java.security.KeyStore.getInstance(Unknown Source) at smartCardPKCS11.sPKCS11.main(sPKCS11.java:65) Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available at sun.security.jca.GetInstance.getInstance(Unknown Source) at java.security.Security.getImpl(Unknown Source) ... 2 more 

I know this is really stupid, help is appreciated.

+6
source share
2 answers

Tell slotListIndex in the setting option (however, the getSlotsWithTokens() method does not return the expected value). You can see the description of the slotListIndex parameter in the PKCS11 Reference :

This is the slot index with which this provider instance should be associated. This is an index to the list of all slots returned by the PKCS # 11 C_GetSlotList function. For example, 0 indicates the first slot in the list. No more than one slot or slotListIndex can be specified. If none of these are specified, the default value is slotListIndex of 0.

So only configure the name and library parameter to configure the PKCS11 provider to avoid your exception:

 // Configure the Sun PKCS#11 provider. It requires a stream // containing the configuration parameters - "name" and "library". String pkcs11ConfigSettings = "name = " + pkcs11ID + "\n" + "library = " + libraryPath; byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes(); ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes); // instantiate the provider SunPKCS11 pkcs11 = new SunPKCS11(confStream); Security.addProvider(pkcs11); ... 

EDIT:

In your code, you are now loading the provider correctly, so java.security.KeyStoreException: PKCS11 not found is called in the following call to KeyStore ks = KeyStore.getInstance("PKCS11"); , because your smart card is not connected or if it is connected, there may be problems with the provider (both problems throw the same exception), so try explicitly passing the instance to the provider using getInstance(String,Provider) :

Using:

 SunPKCS11 pkcs11 = new SunPKCS11(confStream); KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11); 

Instead:

 KeyStore ks = KeyStore.getInstance("PKCS11"); 

In addition, there is an error in your code: you must specify the PKCS11 password is not null when trying to load the keystore.

Therefore use:

 ks.load(null, "yourPassword".toCharArray()); 

Instead:

 ks.load(null, null); 

Note the alternative that a password callback handler is often used to access PKCS11 key stores .

Putting it all together, the code could be:

 // Configure the Sun PKCS#11 provider. It requires a stream // containing the configuration parameters - "name" and "library". String pkcs11ConfigSettings = "name = " + pkcs11ID + "\n" + "library = " + libraryPath; byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes(); ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes); // instantiate the provider SunPKCS11 pkcs11 = new SunPKCS11(confStream); Security.addProvider(pkcs11); KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11); ks.load(null, "yourPassword".toCharArray()); 
+2
source

I had the same problem.

Try passing -Djava.security.debug=sunpkcs11 to jvm. I did it and it worked.

If you are using jarsigner or keytool pass -J-Djava.security.debug=sunpkcs11 .

See OpenJDK Error . This problem is solved in OpenJDK, but perhaps it has not yet been solved in Oracle JDK.

+2
source

Source: https://habr.com/ru/post/973813/


All Articles