Skip to content
This repository was archived by the owner on Oct 31, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ In the current version following encryption and signing operations are supported
1. Symmetric encryption (AES based).
1. Classes: `com.nimbusds.jose.aws.kms.crypto.KmsSymmetricEncrypter`
and `com.nimbusds.jose.aws.kms.crypto.KmsSymmetricDecrypter`
1. Asymmetric or Symmetric encryption (RSA or ECDSA based for asymmetric keys and AES based for symmetric keys).
2. Asymmetric or Symmetric encryption (RSA or ECDSA based for asymmetric keys and AES based for symmetric keys).
1. Classes: `com.nimbusds.jose.aws.kms.crypto.KmsDefaultEncrypter`
and `com.nimbusds.jose.aws.kms.crypto.KmsDefaultDecrypter`
1. Asymmetric signing (RSA or ECDSA based).
3. Asymmetric signing (RSA or ECDSA based).
Comment on lines -14 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unnecessary change and should be avoided.

1. Classes: `com.nimbusds.jose.aws.kms.crypto.KmsAsymmetricSigner`
and `com.nimbusds.jose.aws.kms.crypto.KmsAsymmetricVerifier`

Expand Down
8 changes: 5 additions & 3 deletions nimbus-jose-jwt_aws-kms-extension/build.gradle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a backward incompatible change, please also bump up the major version in this file.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ java {
withSourcesJar()
}

tasks.withType(JavaCompile) {
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}

Expand All @@ -32,13 +32,15 @@ dependencies {
api 'com.nimbusds:nimbus-jose-jwt:[9,9.31]'

// These dependencies is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.amazonaws:aws-java-sdk-kms:[1.12, 2)'
implementation 'commons-cli:commons-cli:[1.4, 2)'
implementation 'software.amazon.awssdk:kms:2.30.18'
implementation 'commons-cli:commons-cli:1.9.0'
implementation 'commons-codec:commons-codec:1.18.0'
Comment on lines +35 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using exact versions, can we use ranges here?

implementation 'com.google.guava:guava:[32,)'

// Use JUnit Jupiter for testing.
testImplementation 'org.junit.jupiter:junit-jupiter:5.+'
testImplementation 'org.assertj:assertj-core:[3,4)'
testImplementation 'org.junit.platform:junit-platform-launcher:1.11.4'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? Usually we shouldn't use the junit-platform-* dependencies directly.


// Mockito
testImplementation 'org.mockito:mockito-core:[3,4)'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
package com.nimbusds.jose.aws.kms.crypto;


import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.model.MessageType;
import com.nimbusds.jose.aws.kms.crypto.impl.KmsAsymmetricRSASSAProvider;
import javax.annotation.concurrent.ThreadSafe;
import lombok.NonNull;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.MessageType;

import javax.annotation.concurrent.ThreadSafe;


/**
Expand All @@ -37,7 +38,7 @@
public class KmsAsymmetricRSASSASigner extends KmsAsymmetricSigner {

public KmsAsymmetricRSASSASigner(
@NonNull final AWSKMS kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
@NonNull final KmsClient kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
super(kms, privateKeyId, messageType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
package com.nimbusds.jose.aws.kms.crypto;


import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.model.MessageType;
import com.nimbusds.jose.aws.kms.crypto.impl.KmsAsymmetricRSASSAProvider;
import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
import lombok.NonNull;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.MessageType;

import javax.annotation.concurrent.ThreadSafe;
import java.util.Set;

/**
* Sign verifier implementation for RSA-SSA signing with public/private key stored in AWS KMS.
Expand All @@ -37,12 +38,12 @@
public class KmsAsymmetricRSASSAVerifier extends KmsAsymmetricVerifier {

public KmsAsymmetricRSASSAVerifier(
@NonNull final AWSKMS kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
@NonNull final KmsClient kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
super(kms, privateKeyId, messageType);
}

public KmsAsymmetricRSASSAVerifier(
@NonNull final AWSKMS kms, @NonNull String privateKeyId, @NonNull final MessageType messageType,
@NonNull final KmsClient kms, @NonNull String privateKeyId, @NonNull final MessageType messageType,
@NonNull final Set<String> defCritHeaders) {
super(kms, privateKeyId, messageType, defCritHeaders);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,20 @@
package com.nimbusds.jose.aws.kms.crypto;


import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.model.DependencyTimeoutException;
import com.amazonaws.services.kms.model.DisabledException;
import com.amazonaws.services.kms.model.InvalidGrantTokenException;
import com.amazonaws.services.kms.model.InvalidKeyUsageException;
import com.amazonaws.services.kms.model.KMSInternalException;
import com.amazonaws.services.kms.model.KMSInvalidStateException;
import com.amazonaws.services.kms.model.KeyUnavailableException;
import com.amazonaws.services.kms.model.MessageType;
import com.amazonaws.services.kms.model.NotFoundException;
import com.amazonaws.services.kms.model.SignRequest;
import com.amazonaws.services.kms.model.SignResult;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.RemoteKeySourceException;
import com.nimbusds.jose.aws.kms.crypto.impl.KmsAsymmetricSigningCryptoProvider;
import com.nimbusds.jose.aws.kms.exceptions.TemporaryJOSEException;
import com.nimbusds.jose.util.Base64URL;
import javax.annotation.concurrent.ThreadSafe;
import lombok.NonNull;
import lombok.var;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid using * imports in source files.


import javax.annotation.concurrent.ThreadSafe;


/**
Expand All @@ -51,28 +43,29 @@
public class KmsAsymmetricSigner extends KmsAsymmetricSigningCryptoProvider implements JWSSigner {

public KmsAsymmetricSigner(
@NonNull final AWSKMS kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
@NonNull final KmsClient kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
super(kms, privateKeyId, messageType);
}

@Override
public Base64URL sign(@NonNull final JWSHeader header, @NonNull final byte[] signingInput) throws JOSEException {

final var message = getMessage(header, signingInput);
SignResult signResult;
SignResponse signResponse;
try {
signResult = getKms().sign(new SignRequest()
.withKeyId(getPrivateKeyId())
.withMessageType(getMessageType())
.withMessage(message)
.withSigningAlgorithm(JWS_ALGORITHM_TO_SIGNING_ALGORITHM_SPEC.get(header.getAlgorithm()).toString()));
signResponse = getKms().sign(SignRequest.builder()
.keyId(getPrivateKeyId())
.messageType(getMessageType())
.message(SdkBytes.fromByteBuffer(message))
.signingAlgorithm(JWS_ALGORITHM_TO_SIGNING_ALGORITHM_SPEC.get(header.getAlgorithm()).toString())
.build());
} catch (NotFoundException | DisabledException | KeyUnavailableException | InvalidKeyUsageException
| KMSInvalidStateException e) {
| KmsInvalidStateException e) {
throw new RemoteKeySourceException("An exception was thrown from KMS due to invalid key.", e);
} catch (DependencyTimeoutException | InvalidGrantTokenException | KMSInternalException e) {
} catch (DependencyTimeoutException | InvalidGrantTokenException | KmsInternalException e) {
throw new TemporaryJOSEException("A temporary exception was thrown from KMS.", e);
}

return Base64URL.encode(signResult.getSignature().array());
return Base64URL.encode(signResponse.signature().asByteArray());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,20 @@
package com.nimbusds.jose.aws.kms.crypto;


import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.model.DependencyTimeoutException;
import com.amazonaws.services.kms.model.DisabledException;
import com.amazonaws.services.kms.model.InvalidGrantTokenException;
import com.amazonaws.services.kms.model.InvalidKeyUsageException;
import com.amazonaws.services.kms.model.KMSInternalException;
import com.amazonaws.services.kms.model.KMSInvalidSignatureException;
import com.amazonaws.services.kms.model.KMSInvalidStateException;
import com.amazonaws.services.kms.model.KeyUnavailableException;
import com.amazonaws.services.kms.model.MessageType;
import com.amazonaws.services.kms.model.NotFoundException;
import com.amazonaws.services.kms.model.VerifyRequest;
import com.amazonaws.services.kms.model.VerifyResult;
import com.nimbusds.jose.CriticalHeaderParamsAware;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.RemoteKeySourceException;
import com.nimbusds.jose.*;
import com.nimbusds.jose.aws.kms.crypto.impl.KmsAsymmetricSigningCryptoProvider;
import com.nimbusds.jose.aws.kms.exceptions.TemporaryJOSEException;
import com.nimbusds.jose.crypto.impl.CriticalHeaderParamsDeferral;
import com.nimbusds.jose.util.Base64URL;
import java.nio.ByteBuffer;
import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
import lombok.NonNull;
import lombok.var;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.*;

import javax.annotation.concurrent.ThreadSafe;
import java.nio.ByteBuffer;
import java.util.Set;

/**
* Sign verifier implementation for asymmetric signing with public/private key stored in AWS KMS.
Expand All @@ -52,9 +39,7 @@
* constructor parameters.
*/
@ThreadSafe
public class KmsAsymmetricVerifier
extends KmsAsymmetricSigningCryptoProvider
implements JWSVerifier, CriticalHeaderParamsAware {
public class KmsAsymmetricVerifier extends KmsAsymmetricSigningCryptoProvider implements JWSVerifier, CriticalHeaderParamsAware {

/**
* The critical header policy.
Expand All @@ -63,13 +48,13 @@ public class KmsAsymmetricVerifier


public KmsAsymmetricVerifier(
@NonNull final AWSKMS kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
@NonNull final KmsClient kms, @NonNull final String privateKeyId, @NonNull final MessageType messageType) {
super(kms, privateKeyId, messageType);
}


public KmsAsymmetricVerifier(
@NonNull final AWSKMS kms, @NonNull String privateKeyId, @NonNull final MessageType messageType,
@NonNull final KmsClient kms, @NonNull String privateKeyId, @NonNull final MessageType messageType,
@NonNull final Set<String> defCritHeaders) {
super(kms, privateKeyId, messageType);
critPolicy.setDeferredCriticalHeaderParams(defCritHeaders);
Expand Down Expand Up @@ -101,24 +86,25 @@ public boolean verify(

var message = getMessage(header, signedContent);

VerifyResult verifyResult;
VerifyResponse verifyResponse;
try {
verifyResult = getKms().verify(new VerifyRequest()
.withKeyId(getPrivateKeyId())
.withSigningAlgorithm(JWS_ALGORITHM_TO_SIGNING_ALGORITHM_SPEC.get(header.getAlgorithm()).toString())
.withMessageType(getMessageType())
.withMessage(message)
.withSignature(ByteBuffer.wrap(signature.decode())));
} catch (KMSInvalidSignatureException e) {
verifyResponse = getKms().verify(VerifyRequest.builder()
.keyId(getPrivateKeyId())
.signingAlgorithm(JWS_ALGORITHM_TO_SIGNING_ALGORITHM_SPEC.get(header.getAlgorithm()).toString())
.messageType(getMessageType())
.message(SdkBytes.fromByteBuffer(message))
.signature(SdkBytes.fromByteBuffer(ByteBuffer.wrap(signature.decode())))
.build());
} catch (KmsInvalidSignatureException e) {
return false;
} catch (NotFoundException | DisabledException | KeyUnavailableException | InvalidKeyUsageException
| KMSInvalidStateException e) {
| KmsInvalidStateException e) {
throw new RemoteKeySourceException("An exception was thrown from KMS due to invalid key.", e);
} catch (DependencyTimeoutException | InvalidGrantTokenException | KMSInternalException e) {
} catch (DependencyTimeoutException | InvalidGrantTokenException | KmsInternalException e) {
throw new TemporaryJOSEException("A temporary exception was thrown from KMS.", e);
}

return verifyResult.isSignatureValid();
return verifyResponse.signatureValid();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.nimbusds.jose.aws.kms.crypto;

import com.amazonaws.services.kms.AWSKMS;
import com.nimbusds.jose.CriticalHeaderParamsAware;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEDecrypter;
Expand All @@ -25,9 +24,11 @@
import com.nimbusds.jose.aws.kms.crypto.utils.JWEDecrypterUtil;
import com.nimbusds.jose.crypto.impl.CriticalHeaderParamsDeferral;
import com.nimbusds.jose.util.Base64URL;
import lombok.NonNull;
import software.amazon.awssdk.services.kms.KmsClient;

import java.util.Map;
import java.util.Set;
import lombok.NonNull;

/**
* Decrypter implementation for a symmetric or asymmetric key stored in AWS KMS.
Expand All @@ -43,25 +44,25 @@ public class KmsDefaultDecrypter extends KmsDefaultEncryptionCryptoProvider impl
*/
private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral();

public KmsDefaultDecrypter(@NonNull final AWSKMS kms,
public KmsDefaultDecrypter(@NonNull final KmsClient kms,
@NonNull final String keyId,
@NonNull final Map<String, String> encryptionContext) {
super(kms, keyId, encryptionContext);
}

public KmsDefaultDecrypter(@NonNull final AWSKMS kms,
public KmsDefaultDecrypter(@NonNull final KmsClient kms,
@NonNull final String keyId) {
super(kms, keyId);
}

public KmsDefaultDecrypter(@NonNull final AWSKMS kms,
public KmsDefaultDecrypter(@NonNull final KmsClient kms,
@NonNull final String keyId,
@NonNull final Set<String> defCritHeaders) {
this(kms, keyId);
critPolicy.setDeferredCriticalHeaderParams(defCritHeaders);
}

public KmsDefaultDecrypter(@NonNull final AWSKMS kms,
public KmsDefaultDecrypter(@NonNull final KmsClient kms,
@NonNull final String keyId,
@NonNull final Map<String, String> encryptionContext,
@NonNull final Set<String> defCritHeaders) {
Expand Down
Loading