Skip to content

[BUG] jarsigner sign failed when using certs with non-exportable key #39590

Description

@grant-arqit

Describe the bug
I have an issue using signing jars with the com.azure.security.keyvault.jca.KeyVaultJcaProvider provider using a certificate with a non-exportable key

Exception or Stack Trace
Using the jarsigner cli tool I get the following error

jarsigner: unable to sign jar: java.security.InvalidKeyException: No installed provider supports this key: com.azure.security.keyvault.jca.implementation.KeyVaultPrivateKey

From the coded solution

Error signing jar: Error in signer materials
java.lang.RuntimeException: jdk.security.jarsigner.JarSignerException: Error in signer materials
	at uk.arqit.support.service.SignerService.signJar(SignerService.kt:28)
	at uk.arqit.support.SignerCommand.run(SignerCommand.kt:25)
	at picocli.CommandLine.executeUserObject(CommandLine.java:2026)
	at picocli.CommandLine.access$1500(CommandLine.java:148)
	at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2461)
	at picocli.CommandLine$RunLast.handle(CommandLine.java:2453)
	at picocli.CommandLine$RunLast.handle(CommandLine.java:2415)
	at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2273)
	at picocli.CommandLine$RunLast.execute(CommandLine.java:2417)
	at picocli.CommandLine.execute(CommandLine.java:2170)
	at io.micronaut.configuration.picocli.PicocliRunner.run(PicocliRunner.java:137)
	at io.micronaut.configuration.picocli.PicocliRunner.run(PicocliRunner.java:114)
	at uk.arqit.support.SignerCommand$Companion.main(SignerCommand.kt:30)
	at uk.arqit.support.SignerCommand.main(SignerCommand.kt)
Caused by: jdk.security.jarsigner.JarSignerException: Error in signer materials
	at jdk.jartool/jdk.security.jarsigner.JarSigner.sign(JarSigner.java:564)
	at uk.arqit.support.service.SignerService.signJar(SignerService.kt:25)
	... 13 more
Caused by: java.security.InvalidKeyException: No installed provider supports this key: com.azure.security.keyvault.jca.implementation.KeyVaultPrivateKey
	at java.base/java.security.Signature$Delegate.chooseProvider(Signature.java:1303)
	at java.base/java.security.Signature$Delegate.engineInitSign(Signature.java:1388)
	at java.base/java.security.Signature.initSign(Signature.java:684)
	at java.base/java.security.Signature$1.initSign(Signature.java:147)
	at java.base/sun.security.util.SignatureUtil.initSignWithParam(SignatureUtil.java:189)
	at java.base/sun.security.util.SignatureUtil.autoInitInternal(SignatureUtil.java:372)
	at java.base/sun.security.util.SignatureUtil.fromKey(SignatureUtil.java:364)
	at java.base/sun.security.pkcs.PKCS7.generateNewSignedData(PKCS7.java:750)
	at jdk.jartool/jdk.security.jarsigner.JarSigner.sign0(JarSigner.java:848)
	at jdk.jartool/jdk.security.jarsigner.JarSigner.sign(JarSigner.java:554)
	... 14 more

To Reproduce
Following the steps documented in https://github.com/backwind1233/AzureDocs/blob/main/AzureJavaSDK/JCA/integrate_keyvault_JCA_provider_with_jarsigner.md

jarsigner -verbose -J-Djava.security.debug=jar \
-keystore NONE \
-storetype AzureKeyVault \
-signedjar appsigned.jar app.jar "redacted" \
-storepass ' ' \
-sigalg SHA256withRSA \
-tsa http://timestamp.entrust.net/rfc3161ts2 \
-providerName AzureKeyVault \
-providerClass com.azure.security.keyvault.jca.KeyVaultJcaProvider \
-J--module-path="/home/grant/projects/cosign/azure-security-keyvault-jca-2.8.1.jar" \
-J--add-modules="com.azure.security.keyvault.jca" \
-J-Dazure.keyvault.uri=redacted \
-J-Dazure.keyvault.tenant-id=redacted \
-J-Dazure.keyvault.client-id=redacted \
-J-Dazure.keyvault.client-secret=redacted

I'm using the SHA256withRSA signature algorithm

See the same issue in JDK 17 and 21

I see the same error with the coded solution (snippet below).

Debugging this code, it would appear that the KeyVaultPrivateKey is not a supported key type. The method supportsKeyClass inside the java.security.Provider module of the JDK expects keys to implement one of the following interfaces

interface java.security.interfaces.RSAPrivateKey
interface java.security.interfaces.RSAPublicKey

Code Snippet
Test code

@Singleton
class SignerService(private val keyVaultClient: KeyVaultClient) : ISignerService {
    override fun signJar(alias: String, inputFilePath: String, outputFilePath: String) {
        val privateKey = keyVaultClient.getKey(alias, null)
        val certificate = keyVaultClient.getCertificate(alias)

        val jarSigner = JarSigner.Builder(KeyStore.PrivateKeyEntry(privateKey as PrivateKey, arrayOf(certificate)))
            .digestAlgorithm("SHA-256")
            .signatureAlgorithm("SHA256withRSA")
            .build()

        try {
            val inZip = ZipFile(inputFilePath)
            val outputStream = FileOutputStream(outputFilePath)
            jarSigner.sign(inZip, outputStream)
        } catch(e: Throwable) {
            println("Error signing jar: ${e.message}")
            throw RuntimeException(e)
        }
    }
}

Expected behavior
I would expect KeyValutPrivateKey to be recognised as a valid key class and for signing inside the key vault to be actioned.

Screenshots
If applicable, add screenshots to help explain your problem.

Setup (please complete the following information):

  • OS: Ubuntu 22.04 (WSL)
  • IDE: Intellij / bash console
  • Library/Libraries: com.azure:azure-security-keyvault-jca:2.8.1
  • Java version: Tested with 17 and 21
  • App Server/Environment: N/A
  • Frameworks: Micronaut in test code

Additional context
N/A

Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added

Metadata

Metadata

Labels

ClientThis issue points to a problem in the data-plane of the library.azure-springAll azure-spring related issuesazure-spring-jcacustomer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamquestionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

Type

No type

Projects

Status
Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions