ebourg / jsign

Java implementation of Microsoft Authenticode for signing Windows executables, installers & scripts
https://ebourg.github.io/jsign
Apache License 2.0
250 stars 107 forks source link

Unable to sign with Yubikey on Windows #134

Closed rearden-steel closed 1 year ago

rearden-steel commented 1 year ago

Hi. I have Windows 10, Yubikey 4 FIPS with SSL.com code signing certificate installed. Yubico-piv-tool is also installed, but I still get error:

c:\build\sign>"c:\Program Files\Java\jre1.8.0_341\bin\java.exe" -Djava.security.debug=sunpkcs11 -jar jsign-4.1.jar --storetype=YUBIKEY test.exe
jsign: Couldn't sign test.exe
java.security.ProviderException: java.io.IOException: The specified module could not be found.
C:\Program Files\Yubico\Yubico PIV Tool\bin\libykcs11.dll
        at net.jsign.YubiKey.getSunPKCS11Configuration(YubiKey.java:65)
        at net.jsign.YubiKey.getProvider(YubiKey.java:44)
        at net.jsign.SignerHelper.build(SignerHelper.java:361)
        at net.jsign.SignerHelper.sign(SignerHelper.java:562)
        at net.jsign.JsignCLI.execute(JsignCLI.java:117)
        at net.jsign.JsignCLI.main(JsignCLI.java:40)
Caused by: java.io.IOException: The specified module could not be found.
C:\Program Files\Yubico\Yubico PIV Tool\bin\libykcs11.dll
        at sun.security.pkcs11.wrapper.PKCS11.connect(Native Method)
        at sun.security.pkcs11.wrapper.PKCS11.<init>(PKCS11.java:144)
        at sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.<init>(PKCS11.java:1583)
        at sun.security.pkcs11.wrapper.PKCS11.getInstance(PKCS11.java:159)
        at net.jsign.YubiKey.getTokenSlot(YubiKey.java:76)
        at net.jsign.YubiKey.getSunPKCS11Configuration(YubiKey.java:60)
        ... 5 more
Try `java -jar jsign.jar --help' for more information.

I've tried a lot, including @ebourg recommendations from https://github.com/ebourg/jsign/issues/122 Can anyone help? Thanks.

ebourg commented 1 year ago

Does it work any better if you specify the storepass (--storepass=<PIN>) ?

rearden-steel commented 1 year ago

No, forgot to mention :( Seems that it is unable to load libykcs11.dll

ebourg commented 1 year ago

Maybe the Yubikey is locked? Did you check with yubico-piv-tool -a status ?

rearden-steel commented 1 year ago

Hi. Not sure what I did, but now it sees Yubikey, but seems that there is some problem with slot selection. FYI there is EV cert in 9a slot.

C:\build\sign>"c:\Program Files\Java\jre1.8.0_341\bin\java.exe" -Djava.security.debug=sunpkcs11 -jar jsign-4.1.jar --storetype=YUBIKEY --storepass=123456 test.exe
SunPKCS11 loading --name=yubikey
library = "C:\\Program Files\\Yubico\\Yubico PIV Tool\\bin\\libykcs11.dll"
slotListIndex=3
sunpkcs11: Initializing PKCS#11 library C:\Program Files\Yubico\Yubico PIV Tool\bin\libykcs11.dll
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.30
All slots: 0, 1, 2, 3
Slots with tokens: 3
jsign: Couldn't sign test.exe
java.security.ProviderException: Failed to create a SunPKCS11 provider from the configuration --name=yubikey
library = "C:\\Program Files\\Yubico\\Yubico PIV Tool\\bin\\libykcs11.dll"
slotListIndex=3
        at net.jsign.ProviderUtils.createSunPKCS11Provider(ProviderUtils.java:52)
        at net.jsign.YubiKey.getProvider(YubiKey.java:44)
        at net.jsign.SignerHelper.build(SignerHelper.java:361)
        at net.jsign.SignerHelper.sign(SignerHelper.java:562)
        at net.jsign.JsignCLI.execute(JsignCLI.java:117)
        at net.jsign.JsignCLI.main(JsignCLI.java:40)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at net.jsign.ProviderUtils.createSunPKCS11Provider(ProviderUtils.java:49)
        ... 5 more
Caused by: java.security.ProviderException: Initialization failed
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:377)
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:104)
        ... 10 more
Caused by: java.security.ProviderException: slotListIndex is 3 but token only has 1 slots
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:358)
        ... 11 more
Try `java -jar jsign.jar --help' for more information.
C:\build\sign>yubico-piv-tool -a status
Version:        4.4.5
Serial Number:  10251488
CHUID: <data>
CCC:    No data available
Slot 9a:
        Algorithm:      ECCP384
        Subject DN:     <DN>
        Issuer DN:      C=US, ST=Texas, L=Houston, O=SSL Corp, CN=SSL.com EV Code Signing Intermediate CA RSA R3
        Fingerprint:    <hash>
        Not Before:     <date>
        Not After:      <date>
rearden-steel commented 1 year ago

I was able to sign with the following:

C:\build\sign>"c:\Program Files\Java\jre1.8.0_341\bin\java.exe" -Djava.security.debug=sunpkcs11 -jar jsign-4.1.jar --storetype=PKCS11 --keystore=yubikey.conf --storepass=123456 --alias "X.509 Certificate for PIV Authentication" test.exe

and yubikey.conf:

name=yubikey
library="C:\\Program\ Files\\Yubico\\Yubico\ PIV\ Tool\\bin\\libykcs11\.dll"
slot = 3
ebourg commented 1 year ago

Interesting, does it work if you replace slot=3 with slotListIndex=3 in the configuration file? If so, try this syntax:

java -Djava.security.debug=sunpkcs11 -jar jsign-4.1.jar --storetype=YUBIKEY --storepass=123456 --alias "X.509 Certificate for PIV Authentication" test.exe
rearden-steel commented 1 year ago

No, does not work:

SunPKCS11 loading c:\build\sign\yubikey.conf
sunpkcs11: Initializing PKCS#11 library C:\Program Files\Yubico\Yubico PIV Tool\bin\libykcs11.dll
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.30
All slots: 0, 1, 2, 3
Slots with tokens: 3
jsign: Couldn't sign test.exe
java.security.ProviderException: Failed to create a SunPKCS11 provider from the configuration c:\build\sign\yubikey.conf
        at net.jsign.ProviderUtils.createSunPKCS11Provider(ProviderUtils.java:52)
        at net.jsign.SignerHelper.build(SignerHelper.java:351)
        at net.jsign.SignerHelper.sign(SignerHelper.java:562)
        at net.jsign.JsignCLI.execute(JsignCLI.java:117)
        at net.jsign.JsignCLI.main(JsignCLI.java:40)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at net.jsign.ProviderUtils.createSunPKCS11Provider(ProviderUtils.java:49)
        ... 4 more
Caused by: java.security.ProviderException: Initialization failed
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:377)
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:104)
        ... 9 more
Caused by: java.security.ProviderException: slotListIndex is 3 but token only has 1 slots
        at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:358)
        ... 10 more
Try `java -jar jsign.jar --help' for more information.
ebourg commented 1 year ago

Funny, I get the same error with my Yubikey (with a different slot layout though), and it goes away when -Djava.security.debug=sunpkcs11 is removed from the command line.

Could you try this:

java -jar jsign-4.1.jar --storetype=YUBIKEY --storepass=123456 --alias "X.509 Certificate for PIV Authentication" test.exe
rearden-steel commented 1 year ago

Strange but it works 🤷‍♂️ 😆

ebourg commented 1 year ago

Good! I think Jsign could be improved to automatically select the X.509 Certificate for PIV Authentication if it's the only one available (this seems to be the case when certification authorities deliver an EV certificate on a Yubikey). For now it only looks for X.509 Certificate for Digital Signature by default, and at some point, before setting the java.security.debug property, you should have gotten this error message indicating that the alias was wrong:

No certificate found under the alias 'X.509 Certificate for Digital Signature' in the keystore SunPKCS11-yubikey
(available aliases: X.509 Certificate for PIV Attestation, X.509 Certificate for PIV Authentication)