Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sign more than one file with API (YUBIKEY) #230

Closed
nauni77 opened this issue Jun 24, 2024 · 22 comments
Closed

sign more than one file with API (YUBIKEY) #230

nauni77 opened this issue Jun 24, 2024 · 22 comments
Milestone

Comments

@nauni77
Copy link

nauni77 commented Jun 24, 2024

Hello,
I use SpringBoot and the dependency : implementation 'net.jsign:jsign-core:6.0'. I implemented bean to execute the signing of my files. Signing the first file works perfect, but if I try to sign another file in the same program run it always fails.

I simplified the code and created a Test only using jsign specific code.

@Test
  public void testSigningTwoFilesInline() throws Exception {
    File file1 = new File("/Users/name/Desktop/HelloWorld/HelloWorld_32-bit/HelloWorld.exe");
    File file2 = new File("/Users/name/Desktop/HelloWorld/HelloWorld_64-bit/HelloWorld.exe");

    KeyStoreType keyStoreType = KeyStoreType.YUBIKEY;
    String keyStorePass = "<change_yubikey_PIN>";
    String keyStoreAlias = "X.509 Certificate for Digital Signature";
    String timeStampAuthority = "http://timestamp.sectigo.com";

    KeyStoreBuilder keyStoreBuilder = new KeyStoreBuilder().storetype(keyStoreType).storepass(keyStorePass);
    KeyStore keystore;
    try {
      keystore = keyStoreBuilder.build();
    } catch (KeyStoreException e) {
      throw new CodeSigningException("could not create keystore", e);
    }
    try (Signable file = Signable.of(file1)) {
      AuthenticodeSigner signer = new AuthenticodeSigner(keystore, keyStoreAlias, null);
      signer.withTimestamping(true)
          .withTimestampingAuthority(timeStampAuthority);
      signer.sign(file);
    } catch (Exception e) {
      throw new CodeSigningException("something went wrong during signing the file", e);
    }

    log.info("file1 is signed successfully");

    try (Signable file = Signable.of(file2)) {
      AuthenticodeSigner signer = new AuthenticodeSigner(keystore, keyStoreAlias, null);
      signer.withTimestamping(true)
          .withTimestampingAuthority(timeStampAuthority);
      signer.sign(file);
    } catch (Exception e) {
      throw new CodeSigningException("something went wrong during signing the file", e);
    }
  }

It fails with Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN, but I don't know why - because the first time the KeyStoreBuilder contains the correct PIN and the file was signed succesfully.

2024-06-25 00:20:46.446  INFO 26699 --- [    Test worker] d.n.c.SigningTestDirectImplementation    : file1 is signed successfully

something went wrong during signing the file
de.noventi.codesignservice.exceptions.CodeSigningException: something went wrong during signing the file
	at de.noventi.codesignservice.SigningTestDirectImplementation.testSigningTwoFilesInline(SigningTestDirectImplementation.java:59)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:685)
	at java.base/java.security.Signature$Delegate.engineSign(Signature.java:1404)
	at java.base/java.security.Signature.sign(Signature.java:713)
	at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder$1.getSignature(Unknown Source)
	at org.bouncycastle.cms.SignerInfoGenerator.generate(Unknown Source)
	at org.bouncycastle.cms.CMSSignedDataGenerator.generate(Unknown Source)
	at org.bouncycastle.cms.CMSSignedDataGenerator.generate(Unknown Source)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.generate(AuthenticodeSignedDataGenerator.java:50)
	at net.jsign.AuthenticodeSigner.createSignedData(AuthenticodeSigner.java:379)
	at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:354)
	at de.noventi.codesignservice.SigningTestDirectImplementation.testSigningTwoFilesInline(SigningTestDirectImplementation.java:57)
	... 84 more
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_Sign(Native Method)
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.C_Sign(PKCS11.java:1814)
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:658)
	... 94 more

Why I can only sign one file during one run of the program? I hope you can help me.

Best regards, Oli

@ebourg
Copy link
Owner

ebourg commented Jun 24, 2024

I've stumbled on this issue as well and fixed it two weeks ago (daf0594). Could you try again with the latest snapshot build?

Alternatively, you can replace the YUBIKEY storetype with PIV, it should work with Jsign 6.0.

@ebourg ebourg added this to the 7.0 milestone Jun 24, 2024
@nauni77
Copy link
Author

nauni77 commented Jun 25, 2024

Hello, thanks for your quick answer and your fix!

The storetype PIV is not working for me, it ends in an exception:

Caused by: javax.smartcardio.CardException: PIV card not found

Is there some location where I can find the Snapshot you told me? I always use gradle for my java projects and have not much experience with maven. If I try to build a SNAPSHOT it always fails.

Thanks in advance, Oli

@ebourg
Copy link
Owner

ebourg commented Jun 25, 2024

You can build the project with mvn package -DskipTests. The build artifacts are also available in the GitHub actions: https://github.com/ebourg/jsign/actions/runs/9612062377/artifacts/1624344399

@ebourg
Copy link
Owner

ebourg commented Jun 25, 2024

The storetype PIV is not working for me, it ends in an exception:

Caused by: javax.smartcardio.CardException: PIV card not found

What JDK do you use?

@nauni77
Copy link
Author

nauni77 commented Jun 25, 2024

The storetype PIV is not working for me, it ends in an exception:
Caused by: javax.smartcardio.CardException: PIV card not found

What JDK do you use?

At the moment I use for this project temurin-11 (11.0.21). In my eyes jdk-17 is not supported yet - right?

Now I got the SNAPSHOT release. I need to disconnect the YubiKey from computer and also disconnect from our company network. If I do so the tests are running. Additionally I need -Djapicmp.skip, because there is no JAR to compare.

I uploaded a SNAPSHOT from master branch to our repository using:

mvn deploy -Djapicmp.skip -DskipTests

After include implementation 'net.jsign:jsign-core:7.0-SNAPSHOT' into my build the problem still there. I can sign one file, but no additionall file can be signed. The same error is shown.

I use a "YubiKey 5C NFC"

  • Firmware: 5.7.1
  • USB-Interfaces activated: OTP, FIDO U2F, FIDO2, OPENPGP, PIV, OATH

I tried to reuse the KeyStore and AuthenticodeSigner. I tried also to create for each signing all objects again, but it's still not working.

Maybe you have some example code which worked signing multiple files in running only one java application?

@ebourg
Copy link
Owner

ebourg commented Jun 25, 2024

jdk-17 is not supported yet - right?

Jsign supports Java from 8 to 21+. Could you try the PIV type with ZuluJDK?

I uploaded a SNAPSHOT from master branch to our repository using:

mvn deploy -Djapicmp.skip -DskipTests

You can also use mvn install to install the artifacts locally only.

Maybe you have some example code which worked signing multiple files in running only one java application?

Yes, could you try running the testSigningWithYubikey() test in JsignCLITest. This test signs twice the same file and works with my Yubikey 5 NFC 5.1.2 on Windows 10 with ZuluJDK.

@nauni77
Copy link
Author

nauni77 commented Jun 26, 2024

After your information, that jsign supports JDK17 - I tried again and got the same error as before (with JDK17) with KeyStoreType.YUBIKEY (jsign 6.0).

class net.jsign.YubiKey (in unnamed module @0x2f01783a) cannot access class sun.security.pkcs11.wrapper.PKCS11 (in module jdk.crypto.cryptoki) because module jdk.crypto.cryptoki does not export sun.security.pkcs11.wrapper to unnamed module @0x2f01783a
java.lang.IllegalAccessError: class net.jsign.YubiKey (in unnamed module @0x2f01783a) cannot access class sun.security.pkcs11.wrapper.PKCS11 (in module jdk.crypto.cryptoki) because module jdk.crypto.cryptoki does not export sun.security.pkcs11.wrapper to unnamed module @0x2f01783a
	at net.jsign.YubiKey.getTokenSlot(YubiKey.java:76)
	at net.jsign.YubiKey.getSunPKCS11Configuration(YubiKey.java:60)
	at net.jsign.YubiKey.getProvider(YubiKey.java:44)
	at net.jsign.KeyStoreType$10.getProvider(KeyStoreType.java:252)
	at net.jsign.KeyStoreBuilder.provider(KeyStoreBuilder.java:268)
	at net.jsign.KeyStoreBuilder.build(KeyStoreBuilder.java:281)
	at de.noventi.codesignservice.SigningDirectImplTest.testSigningOneFileInline(SigningDirectImplTest.java:41)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Do you know this kind of error?

If I switch at this configuration to KeyStoreType.PIV - everything works now fine with JDK 17 and PIV! Even the signing of more than one file.

The Test JsignCLITest is working on command line. There appears:

[WARNING] Tests run: 53, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 15.90 s -- in net.jsign.JsignCLITest
[INFO]
[INFO] Results:
[INFO]
[WARNING] Tests run: 66, Failures: 0, Errors: 0, Skipped: 1

So the test seems to work - even with Temurin-17.0.11+9. All Tests are working. But with the IntelliJ IDE I have trouble to make it work. One thing is you use:

<plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.13.0</version>
        <configuration>
          <source>8</source>
          <target>8</target>
        </configuration>
      </plugin>
      <plugin>

and IntelliJ don't like to use the compiler configurations for my defined JDK 17 ...

--add-exports java.base/sun.net.www=ALL-UNNAMED --add-exports java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports jdk.crypto.cryptoki/sun.security.pkcs11.wrapper=ALL-UNNAMED --add-opens java.base/javax.crypto=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED

and without this it do not compile - because of missing classes.

I will try the SNAPSHOT with JDK 17 and will tell you what happened.

@nauni77
Copy link
Author

nauni77 commented Jun 26, 2024

Now with my snapshot the PIV is not working anymore.

Bad type on operand stack
Exception Details:
  Location:
    net/jsign/jca/PIVCardSigningService.sign(Lnet/jsign/jca/SigningServicePrivateKey;Ljava/lang/String;[B)[B @156: invokespecial
  Reason:
    Type 'java/lang/Object' (current frame, stack[2]) is not assignable to 'java/lang/Throwable'
  Current Frame:
    bci: @156
    flags: { }
    locals: { top, top, top, top, top, top, top, 'java/lang/Object' }
    stack: { uninitialized 150, uninitialized 150, 'java/lang/Object' }
  Bytecode:
    0000000: 2c03 2cb6 0038 1206 b600 36b6 0037 b800
    0000010: 4a3a 0419 04b6 0049 2db6 003f 3a05 2bb6
    0000020: 0057 b800 543a 062a b400 3119 06b6 0051
    0000030: 3a07 1204 2bb6 0056 b600 3599 0029 bb00
    0000040: 2759 bb00 2659 1904 b400 2eb2 002f b700
    0000050: 4b19 05b7 004c 3a09 1909 1201 b600 4d3a
    0000060: 08a7 0027 1905 be19 07b4 0030 1008 6ca4
    0000070: 0015 1905 1907 b400 3010 086c b800 443a
    0000080: 08a7 0007 1905 3a08 2ab4 0031 1906 1908
    0000090: b600 52b0 3a07 bb00 1259 1907 b700 3dbf
    00000a0:                                        
  Exception Handler Table:
    bci [39, 147] => handler: 148
    bci [39, 147] => handler: 148
  Stackmap Table:
    full_frame(@100,{Object[#43],Top,Top,Top,Top,Object[#7],Object[#41],Object[#42]},{})
    chop_frame(@132,1)
    full_frame(@136,{Object[#43],Top,Top,Top,Top,Top,Object[#41],Top,Object[#7]},{})
    full_frame(@148,{},{Object[#12]})

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    net/jsign/jca/PIVCardSigningService.sign(Lnet/jsign/jca/SigningServicePrivateKey;Ljava/lang/String;[B)[B @156: invokespecial
  Reason:
    Type 'java/lang/Object' (current frame, stack[2]) is not assignable to 'java/lang/Throwable'
  Current Frame:
    bci: @156
    flags: { }
    locals: { top, top, top, top, top, top, top, 'java/lang/Object' }
    stack: { uninitialized 150, uninitialized 150, 'java/lang/Object' }
  Bytecode:
    0000000: 2c03 2cb6 0038 1206 b600 36b6 0037 b800
    0000010: 4a3a 0419 04b6 0049 2db6 003f 3a05 2bb6
    0000020: 0057 b800 543a 062a b400 3119 06b6 0051
    0000030: 3a07 1204 2bb6 0056 b600 3599 0029 bb00
    0000040: 2759 bb00 2659 1904 b400 2eb2 002f b700
    0000050: 4b19 05b7 004c 3a09 1909 1201 b600 4d3a
    0000060: 08a7 0027 1905 be19 07b4 0030 1008 6ca4
    0000070: 0015 1905 1907 b400 3010 086c b800 443a
    0000080: 08a7 0007 1905 3a08 2ab4 0031 1906 1908
    0000090: b600 52b0 3a07 bb00 1259 1907 b700 3dbf
    00000a0:                                        
  Exception Handler Table:
    bci [39, 147] => handler: 148
    bci [39, 147] => handler: 148
  Stackmap Table:
    full_frame(@100,{Object[#43],Top,Top,Top,Top,Object[#7],Object[#41],Object[#42]},{})
    chop_frame(@132,1)
    full_frame(@136,{Object[#43],Top,Top,Top,Top,Top,Object[#41],Top,Object[#7]},{})
    full_frame(@148,{},{Object[#12]})

	at net.jsign.KeyStoreType$8.getProvider(KeyStoreType.java:229)
	at net.jsign.KeyStoreBuilder.provider(KeyStoreBuilder.java:272)
	at net.jsign.KeyStoreBuilder.build(KeyStoreBuilder.java:285)
.....

@nauni77
Copy link
Author

nauni77 commented Jun 26, 2024

The KeyStoreType.YUBIKEY is also not working:

class net.jsign.YubiKey (in unnamed module @0x2f01783a) cannot access class sun.security.pkcs11.wrapper.PKCS11 (in module jdk.crypto.cryptoki) because module jdk.crypto.cryptoki does not export sun.security.pkcs11.wrapper to unnamed module @0x2f01783a
java.lang.IllegalAccessError: class net.jsign.YubiKey (in unnamed module @0x2f01783a) cannot access class sun.security.pkcs11.wrapper.PKCS11 (in module jdk.crypto.cryptoki) because module jdk.crypto.cryptoki does not export sun.security.pkcs11.wrapper to unnamed module @0x2f01783a
	at net.jsign.YubiKey.getTokenSlot(YubiKey.java:77)
	at net.jsign.YubiKey.getSunPKCS11Configuration(YubiKey.java:61)
	at net.jsign.YubiKey.getProvider(YubiKey.java:45)
	at net.jsign.KeyStoreType$10.getProvider(KeyStoreType.java:257)
	at net.jsign.KeyStoreBuilder.provider(KeyStoreBuilder.java:272)
	at net.jsign.KeyStoreBuilder.build(KeyStoreBuilder.java:285)
	at ....

Do I have to add some exports to the compiler? Even with Zulu 17 the same errors are existing.

@ebourg
Copy link
Owner

ebourg commented Jun 26, 2024

For the YUBIKEY storetype you need this parameter: --add-exports jdk.crypto.cryptoki/sun.security.pkcs11.wrapper=ALL-UNNAMED

@nauni77
Copy link
Author

nauni77 commented Jun 27, 2024

Thanks - your right. I did it just add the "add-exports" to the compile and not for test execution. Of course it was needed to add to runtime environment.

Now with OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9) and jsign 6.0 it's possible to sign

  • one file with YUBIKEY
  • one file with PIV
  • more files with PIV
    but not (as expected) signing more than one file with YUBIKEY KeyStore.

So this is working for me. Thanks a lot for your help!

But I'm really worry about the next version, because my SNAPSHOT version don't work wit PIV or YUBIKEY. The Exception of PIV (with the SNAPSHOT) is still the same as described above. Encoding a second file with YUBIKEY will still end in Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN. But the stacktrace is a little different:

something went wrong during signing the file
de.company.codesignservice.exceptions.CodeSigningException: something went wrong during signing the file
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInline(SigningDirectImplTest.java:103)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInlineYubikey(SigningDirectImplTest.java:76)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:678)
	at java.base/java.security.Signature$Delegate.engineSign(Signature.java:1423)
	at java.base/java.security.Signature.sign(Signature.java:712)
	at net.jsign.bouncycastle.operator.jcajce.JcaContentSignerBuilder$1.getSignature(Unknown Source)
	at net.jsign.bouncycastle.cms.SignerInfoGenerator.generate(Unknown Source)
	at net.jsign.bouncycastle.cms.CMSSignedDataGenerator.generate(Unknown Source)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.getSignerInfo(AuthenticodeSignedDataGenerator.java:56)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.generate(AuthenticodeSignedDataGenerator.java:43)
	at net.jsign.AuthenticodeSigner.createSignedData(AuthenticodeSigner.java:395)
	at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:370)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInline(SigningDirectImplTest.java:101)
	... 4 more
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method)
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.C_SignFinal(PKCS11.java:1826)
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:628)
	... 14 more

Can you help to make at least one of the methods work with the next version?

Thanks in advance, Oli

@ebourg
Copy link
Owner

ebourg commented Jun 27, 2024

I'm unable to reproduce the "Bad type on operand stack" error with the 7.0 snapshot. Here's what I did:

You get this error only when running your code from IntelliJ, but not when running the Jsign PIV unit test with Maven from the command line?

@nauni77
Copy link
Author

nauni77 commented Jun 27, 2024

Interesting it seems there is something wrong with my SNAPSHOT ... creating the SNAPSHOT did not produce any error. Which JDK do you use creating the SNAPSHOT?

If I replace my SNAPSHOT with our SNAPSHOT the PIV signature is working. Even sign one file with YUBIKEY is working. But signing more than one file will still fail with an error. The stacktrace I postet above.

@ebourg
Copy link
Owner

ebourg commented Jun 27, 2024

Which JDK do you use creating the SNAPSHOT?

The snapshot build was generated by OpenJDK 8 (Temurin 8.0.412+8).

I've been able to reproduce the verification error. I suspect an issue with the minimization process with Proguard. In this case if you depend on net.jsign:jsign-core and not on net.jsign:jsign you should be fine.

Even sign one file with YUBIKEY is working. But signing more than one file will still fail with an error

Could you try again with the -Djava.security.debug=all parameter?

@nauni77
Copy link
Author

nauni77 commented Jun 27, 2024

Hi, building a SNAPSHOT with JDK 1.8 works. Thanks.

I used jsign-core but nothing changes.

Adding the java.security.debug results in this output:

SunPKCS11 loading --name=yubikey
library = "/usr/local/lib/libykcs11.dylib"
slot=0
sunpkcs11: Initializing PKCS#11 library /usr/local/lib/libykcs11.dylib
Information for provider SunPKCS11-yubikey
Library info:
  cryptokiVersion: 2.40
  manufacturerID: Yubico (www.yubico.com)         
  flags: 0
  libraryDescription: PKCS#11 PIV Library (SP-800-73) 
  libraryVersion: 2.52
All slots: 0
Slots with tokens: 0
Slot info for slot 0:
  slotDescription: Yubico YubiKey OTP+FIDO+CCID                                    
  manufacturerID: Yubico (www.yubico.com)         
  flags: CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT
  hardwareVersion: 1.00
  firmwareVersion: 1.00
Token info for token in slot 0:
  label: YubiKey PIV #29169391           
  manufacturerID: Yubico (www.yubico.com)         
  model: YubiKey YK5     
  serialNumber: 29169391        
  flags: CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED
  ulMaxSessionCount: 16
  ulSessionCount: 0
  ulMaxRwSessionCount: 16
  ulRwSessionCount: 2
  ulMaxPinLen: 64
  ulMinPinLen: 6
  ulTotalPublicMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION
  ulTotalPrivateMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION
  hardwareVersion: 1.00
  firmwareVersion: 5.71
  utcTime:                 
Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 65537 = CKF_HW | CKF_GENERATE_KEY_PAIR
Mechanism CKM_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 11009 = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY
Mechanism CKM_RSA_PKCS_PSS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_RSA_PKCS_OAEP:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 769 = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT
Mechanism CKM_RSA_X_509:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 11009 = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA1_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA256_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA384_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA512_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA1_RSA_PKCS_PSS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA256_RSA_PKCS_PSS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA384_RSA_PKCS_PSS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_SHA512_RSA_PKCS_PSS:
  ulMinKeySize: 1024
  ulMaxKeySize: 4096
  flags: 10241 = CKF_HW | CKF_SIGN | CKF_VERIFY
Mechanism CKM_EC_KEY_PAIR_GEN:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26279937 = CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA_SHA1:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA_SHA224:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA_SHA256:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA_SHA384:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDSA_SHA512:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26224641 = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_ECDH1_DERIVE:
  ulMinKeySize: 256
  ulMaxKeySize: 384
  flags: 26738689 = CKF_HW | CKF_DERIVE | CKF_EC_F_P | CKF_EC_UNCOMPRESS
Mechanism CKM_SHA_1:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA256:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA384:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA512:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyPairGenerator.EC -> sun.security.pkcs11.P11KeyPairGenerator
 (CKM_EC_KEY_PAIR_GEN)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyPairGenerator.RSA -> sun.security.pkcs11.P11KeyPairGenerator
  aliases: [OID.1.2.840.113549.1.1, 1.2.840.113549.1.1, 1.2.840.113549.1.1.1]
 (CKM_RSA_PKCS_KEY_PAIR_GEN)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA512withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.13, 1.2.840.113549.1.1.13]
 (CKM_SHA512_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.NONEwithECDSA -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.NONEwithECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Cipher.RSA/ECB/PKCS1Padding -> sun.security.pkcs11.P11RSACipher
  aliases: [RSA]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA1withRSASSA-PSS -> sun.security.pkcs11.P11PSSSignature
 (CKM_SHA1_RSA_PKCS_PSS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-256withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA384withRSASSA-PSS -> sun.security.pkcs11.P11PSSSignature
 (CKM_SHA384_RSA_PKCS_PSS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA256withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.10045.4.3.2, 1.2.840.10045.4.3.2]
 (CKM_ECDSA_SHA256)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyAgreement.ECDH -> sun.security.pkcs11.P11ECDHKeyAgreement
 (CKM_ECDH1_DERIVE)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-384withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.11, 2.16.840.1.101.3.4.3.11]
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.MD2withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.2, 1.2.840.113549.1.1.2]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA384withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.12, 1.2.840.113549.1.1.12]
 (CKM_SHA384_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyFactory.EC -> sun.security.pkcs11.P11ECKeyFactory
 (CKM_EC_KEY_PAIR_GEN)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA1withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA_SHA1)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA1withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.10045.4.1, 1.2.840.10045.4.1]
 (CKM_ECDSA_SHA1)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA512withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA_SHA512)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: MessageDigest.SHA-512 -> sun.security.pkcs11.P11Digest
  aliases: [OID.2.16.840.1.101.3.4.2.3, 2.16.840.1.101.3.4.2.3, SHA512]
 (CKM_SHA512)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA256withRSASSA-PSS -> sun.security.pkcs11.P11PSSSignature
 (CKM_SHA256_RSA_PKCS_PSS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA384withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.10045.4.3.3, 1.2.840.10045.4.3.3]
 (CKM_ECDSA_SHA384)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: MessageDigest.SHA-256 -> sun.security.pkcs11.P11Digest
  aliases: [OID.2.16.840.1.101.3.4.2.1, 2.16.840.1.101.3.4.2.1, SHA256]
 (CKM_SHA256)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: AlgorithmParameters.EC -> sun.security.util.ECParameters
  aliases: [OID.1.2.840.10045.2.1, 1.2.840.10045.2.1, EllipticCurve]
 (CKM_EC_KEY_PAIR_GEN)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA384withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA_SHA384)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-224withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.13, 2.16.840.1.101.3.4.3.13]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA224withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.10045.4.3.1, 1.2.840.10045.4.3.1]
 (CKM_ECDSA_SHA224)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA256withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA_SHA256)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA512withRSASSA-PSS -> sun.security.pkcs11.P11PSSSignature
 (CKM_SHA512_RSA_PKCS_PSS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-224withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.9, 2.16.840.1.101.3.4.3.9]
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA224withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.14, 1.2.840.113549.1.1.14]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-512withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.12, 2.16.840.1.101.3.4.3.12]
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.MD5withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.4, 1.2.840.113549.1.1.4]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA224withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA_SHA224)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-512withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: MessageDigest.SHA-1 -> sun.security.pkcs11.P11Digest
  aliases: [OID.1.3.14.3.2.26, 1.3.14.3.2.26, SHA, SHA1]
 (CKM_SHA_1)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA256withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.11, 1.2.840.113549.1.1.11]
 (CKM_SHA256_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-224withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-384withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.15, 2.16.840.1.101.3.4.3.15]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Cipher.RSA/ECB/NoPadding -> sun.security.pkcs11.P11RSACipher
 (CKM_RSA_X_509)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-512withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.16, 2.16.840.1.101.3.4.3.16]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA1withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.113549.1.1.5, 1.2.840.113549.1.1.5, 1.3.14.3.2.29]
 (CKM_SHA1_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.RSASSA-PSS -> sun.security.pkcs11.P11PSSSignature
  aliases: [OID.1.2.840.113549.1.1.10, 1.2.840.113549.1.1.10, PSS]
 (CKM_RSA_PKCS_PSS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA512withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.1.2.840.10045.4.3.4, 1.2.840.10045.4.3.4]
 (CKM_ECDSA_SHA512)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-256withECDSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.10, 2.16.840.1.101.3.4.3.10]
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-384withECDSAinP1363Format -> sun.security.pkcs11.P11Signature
 (CKM_ECDSA)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: MessageDigest.SHA-384 -> sun.security.pkcs11.P11Digest
  aliases: [OID.2.16.840.1.101.3.4.2.2, 2.16.840.1.101.3.4.2.2, SHA384]
 (CKM_SHA384)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyFactory.RSA -> sun.security.pkcs11.P11RSAKeyFactory
  aliases: [OID.1.2.840.113549.1.1, 1.2.840.113549.1.1, 1.2.840.113549.1.1.1]
 (CKM_RSA_PKCS_KEY_PAIR_GEN)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: Signature.SHA3-256withRSA -> sun.security.pkcs11.P11Signature
  aliases: [OID.2.16.840.1.101.3.4.3.14, 2.16.840.1.101.3.4.3.14]
 (CKM_RSA_PKCS)
Provider: SunPKCS11-yubikey.putService(): SunPKCS11-yubikey: KeyStore.PKCS11 -> sun.security.pkcs11.P11KeyStore
  aliases: [PKCS11-yubikey]
 (KeyStore)
Provider: KeyStore.PKCS11 type from: SunPKCS11-yubikey
sunpkcs11: user already logged in
pkcs11keystore: did not find match for private key with CKA_ID [0x01] (ignoring entry)
Token Alias Map:
  X.509 Certificate for Digital Signature	type=[private key]
	label=[X.509 Certificate for Digital Signature]
	id=0x02
	trusted=[false]
	matched=[true]
	cert=[	subject: CN=company SE - Test Zertifikat
		issuer: CN=company SE - Test Zertifikat
		serialNum: 705238770397581868373230520434335314024439656957]
  X.509 Certificate for PIV Attestation	type=[private key]
	label=[X.509 Certificate for PIV Attestation]
	id=0x19
	trusted=[false]
	matched=[true]
	cert=[	subject: CN=Yubico PIV Attestation
		issuer: CN=Yubico PIV Root CA Serial 263751
		serialNum: 10868241389019373434]
pkcs11keystore: P11KeyStore load. Entry count: 2
Provider: MessageDigest.SHA-256 algorithm from: SUN
Provider: Signature.SHA256WITHECDSA signing algorithm from: SunPKCS11-yubikey
Provider: MessageDigest.SHA-256 algorithm from: SUN

something went wrong during signing the file
de.company.codesignservice.exceptions.CodeSigningException: something went wrong during signing the file
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInline(SigningDirectImplTest.java:103)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInlineYubikey(SigningDirectImplTest.java:77)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:678)
	at java.base/java.security.Signature$Delegate.engineSign(Signature.java:1423)
	at java.base/java.security.Signature.sign(Signature.java:712)
	at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder$1.getSignature(Unknown Source)
	at org.bouncycastle.cms.SignerInfoGenerator.generate(Unknown Source)
	at org.bouncycastle.cms.CMSSignedDataGenerator.generate(Unknown Source)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.getSignerInfo(AuthenticodeSignedDataGenerator.java:56)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.generate(AuthenticodeSignedDataGenerator.java:43)
	at net.jsign.AuthenticodeSigner.createSignedData(AuthenticodeSigner.java:395)
	at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:370)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInline(SigningDirectImplTest.java:101)
	... 4 more
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method)
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.C_SignFinal(PKCS11.java:1826)
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:628)
	... 14 more


sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:678)
	at java.base/java.security.Signature$Delegate.engineSign(Signature.java:1423)
	at java.base/java.security.Signature.sign(Signature.java:712)
	at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder$1.getSignature(Unknown Source)
	at org.bouncycastle.cms.SignerInfoGenerator.generate(Unknown Source)
	at org.bouncycastle.cms.CMSSignedDataGenerator.generate(Unknown Source)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.getSignerInfo(AuthenticodeSignedDataGenerator.java:56)
	at net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.generate(AuthenticodeSignedDataGenerator.java:43)
	at net.jsign.AuthenticodeSigner.createSignedData(AuthenticodeSigner.java:395)
	at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:370)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInline(SigningDirectImplTest.java:101)
	at de.company.codesignservice.SigningDirectImplTest.testSigningTwoFilesInlineYubikey(SigningDirectImplTest.java:77)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method)
	at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.C_SignFinal(PKCS11.java:1826)
	at jdk.crypto.cryptoki/sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:628)
	... 14 more

@ebourg
Copy link
Owner

ebourg commented Jun 27, 2024

Ok I've figured it out: the fix for the CKR_USER_NOT_LOGGED_IN error was applied to the SignerHelper class which is purely internal to Jsign for now (that will probably change in the future). The AuthenticodeSigner class you use is missing the logout/login logic required for signing multiple times. You have to fetch the java.security.Provider of the keystore and explicitely logout/login before signing:

    Provider provider = keystore.getProvider();
    ((AuthProvider) provider).logout();
    ((AuthProvider) provider).login(null, callbacks -> {
        for (Callback callback : callbacks) {
            if (callback instanceof PasswordCallback) {
                ((PasswordCallback) callback).setPassword(storepass);
            }
        }
    });

If you want to avoid this hassle you can simply use the PIV storetype, it handles the authentication automatically before signing.

ebourg added a commit that referenced this issue Jun 28, 2024
@ebourg ebourg closed this as completed in 39a94c2 Jun 28, 2024
@ebourg
Copy link
Owner

ebourg commented Jun 28, 2024

@nauni77 I think I've found a solution that also works when signing multiple times with the API. Please give it a try.

@nauni77
Copy link
Author

nauni77 commented Jul 3, 2024

Hello, thanks for you changes - I builded a new snapshot release and tried it. But the error is still the same. I attached the error as a file:

output_fail_signing_more_files.log

I just thought about - why you don't add the logout/ login to the AuthenticodeSigner before signing - only if using YUBIKEY profile. I think the reasonn is you don't know the PIN for login - right? Do you have another idea to fix this for API requests?

@ebourg
Copy link
Owner

ebourg commented Jul 3, 2024

I just thought about - why you don't add the logout/ login to the AuthenticodeSigner before signing - only if using YUBIKEY profile. I think the reasonn is you don't know the PIN for login - right?

That's roughtly what I did. If you use KeyStoreBuilder to build the Yubikey keystore, you get a keystore that uses a modified security provider. This provider records the password used to initialize the keystore, and performs a logout/login before each signing operation.

Did you use KeyStoreBuilder, or did you build the Provider and the KeyStore yourself?

@nauni77
Copy link
Author

nauni77 commented Jul 3, 2024

Yes, I use the KeyStoreBuilder - but I think if I create the AuthenticodeSigner only the provider will be stored at AuthenticodeSigner and not the keyStoreSpi which is an instance of the AutoLoginProvider. I think there needs to be used the AutLoginProvider inside AuthenticodeSigner to make it work. I created a short version of the code I use to check multiple files encoding.

If the workaround code is executed it works. With useWorkaround=false it fails. KeyStoreType is YUBIKEY.

public void testSigningTwoFilesInline(KeyStoreType keyStoreType, String keyStoreAlias) throws Exception {

    String timeStampAuthority = "http://timestamp.sectigo.com";

    KeyStoreBuilder keyStoreBuilder = new KeyStoreBuilder().storetype(keyStoreType).storepass(keyStorePass);
    KeyStore keystore;
    AuthenticodeSigner signer;
    try {
      keystore = keyStoreBuilder.build();
      signer = new AuthenticodeSigner(keystore, keyStoreAlias, null);
      signer.withTimestamping(true)
          .withTimestampingAuthority(timeStampAuthority);
    } catch (KeyStoreException e) {
      throw new CodeSigningException("could not create keystore or signer", e);
    }

    try (Signable file = Signable.of(file1)) {

      // Workaround for not signed in exception:
      // https://github.com/ebourg/jsign/issues/230
      if (useWorkaround && keyStoreType.equals(KeyStoreType.YUBIKEY)) {
        Provider provider = keystore.getProvider();
        ((AuthProvider) provider).logout();
        ((AuthProvider) provider).login(null, callbacks -> {
          for (Callback callback : callbacks) {
            if (callback instanceof PasswordCallback) {
              ((PasswordCallback) callback).setPassword(keyStorePass.toCharArray());
            }
          }
        });
      }
      signer.sign(file);
    } catch (Exception e) {
      throw new CodeSigningException("something went wrong during signing the file", e);
    }

    log.info("file1 is signed successfully");

    try (Signable file = Signable.of(file2)) {
      // Workaround for not signed in exception:
      // https://github.com/ebourg/jsign/issues/230
      if (useWorkaround && keyStoreType.equals(KeyStoreType.YUBIKEY)) {
        Provider provider = keystore.getProvider();
        ((AuthProvider) provider).logout();
        ((AuthProvider) provider).login(null, callbacks -> {
          for (Callback callback : callbacks) {
            if (callback instanceof PasswordCallback) {
              ((PasswordCallback) callback).setPassword(keyStorePass.toCharArray());
            }
          }
        });
      }
      signer.sign(file);
    } catch (Exception e) {
      throw new CodeSigningException("something went wrong during signing the file", e);
    }

    log.info("file2 is signed successfully");
  }

@ebourg ebourg reopened this Jul 4, 2024
@ebourg ebourg closed this as completed in 08c1228 Jul 4, 2024
@ebourg
Copy link
Owner

ebourg commented Jul 4, 2024

Thank you for the example. Could you try again with the latest fix?

@nauni77
Copy link
Author

nauni77 commented Jul 8, 2024

Hi, yes. I already checked the new version and now it's running! Thanks a lot for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants