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

Allow using GenericSecret for HmacSHA* #935

Merged
merged 2 commits into from Apr 22, 2024

Conversation

mnylen
Copy link
Contributor

@mnylen mnylen commented Apr 16, 2024

Extend the pre-existing check for SUN PKCS11 generic secret to allow all SecretKeys where getAlgorithm() returns "GenericSecret" to bypass the algorithm validation.

This matches at least with AWS CloudHSM JCE provider, but likely others as well.

Relates to discussion #934

Let me know if more tests are needed. I didn't find a test that would've tested the existing Sun PKCS#11 generic secret case, and not sure how to test that when the class doesn't exist in the classpath.

@mnylen mnylen force-pushed the allow-generic-secret-with-hmac branch 3 times, most recently from 9039f6c to 74c90ab Compare April 16, 2024 07:34
@@ -36,6 +36,7 @@ public final class KeysBridge {

private static final String SUNPKCS11_GENERIC_SECRET_CLASSNAME = "sun.security.pkcs11.P11Key$P11SecretKey";
private static final String SUNPKCS11_GENERIC_SECRET_ALGNAME = "Generic Secret"; // https://github.com/openjdk/jdk/blob/4f90abaf17716493bad740dcef76d49f16d69379/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java#L1292
private static final String GENERIC_SECRET_ALGNAME = "GenericSecret";
Copy link
Member

Choose a reason for hiding this comment

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

@mnylen Can you add a comment here about where this string comes from.

You have a great description in the conversation, but adding it inline in the code will help future viewers 😄

@lhazlewood any idea if this should be made more generic somehow? I'm not sure how often we would come across this type of problem. (but I'm guessing it was a PITA to troubleshoot?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can add the comment. I also agree that it'd be great to be able to have this support for generic secrets a bit more generic, but not sure how to do that. As far as I'm aware, there's no standard for these HSM-backed JCE providers to follow.

One option of course would be to wrap the key with some kind of additional metadata (such as algorithm), and then unwrap it in the algorithms before passing it to the provider. There's existing ProviderKey already, but that is unwrapped way before the key hits the algorithm implementations.

Or perhaps add a mechanism for registering the secret class names that should not be treated as strictly in validations.

Copy link
Member

Choose a reason for hiding this comment

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

Awesome! Thanks for the quick update!

Copy link
Contributor

Choose a reason for hiding this comment

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

@bdemers @mnylen I'm wondering if this should be made to handle both names, something along the lines of:

if (algName.contains("Generic") && algName.contains("Secret")) ....

or

if (algName.startsWith("Generic") && algName.endsWith("Secret"))...

whichever is faster. (I'm mostly sure the .startsWith/.endsWith approach is faster)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't mind doing the change. Wonder if just startsWith("Generic") would be enough though?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hrm, maybe? 🤔

I tend to be a little tighter on restrictions like this, but I think checking for just Generic makes sense because we're already checking for instanceof SecretKey before this step.

Extend the pre-existing check for SUN PKCS11 generic secret to allow all
SecretKeys where getAlgorithm() returns "GenericSecret" to bypass the
algorithm validation.

This matches at least with AWS CloudHSM JCE provider, but likely others
as well.
@mnylen mnylen force-pushed the allow-generic-secret-with-hmac branch from 74c90ab to eb703c3 Compare April 16, 2024 16:52
public static boolean isGenericSecret(Key key) {
if (!(key instanceof SecretKey)) {
return false;
} else if (key.getClass().getName().equals(SUNPKCS11_GENERIC_SECRET_CLASSNAME) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor nit:

We tend to prefer pre-emptive returns in their own statement to help with readability, so putting the instanceof check in its own if/return is a little nicer than chaining else if logic. For example, I might rewrite this as:

public static isGenericSecret(Key key) {

    if (!(key instanceof SecretKey) {
        return false;
    }

    String algName = Assert.hasText(key.getAlgorithm(), "Key algorithm cannot be null or empty.");
    return algName.startsWith(GENERIC_PREFIX) && algName.endsWith(SECRET_SUFFIX);
}

def genericSecret = new SecretKey() {
@Override
String getAlgorithm() {
return "GenericSecret" ;
Copy link
Contributor

Choose a reason for hiding this comment

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

We'd probably want another test/tests with a space between 'Generic' and 'Secret' if we go with the .startsWith/.endsWith approach.

@mnylen
Copy link
Contributor Author

mnylen commented Apr 22, 2024

Made the requested changes. Been a bit busy, so it's somewhat slow going. :)

@lhazlewood
Copy link
Contributor

Excellent stuff @mnylen, thanks! Once CI passes, we can merge 😄

@lhazlewood lhazlewood merged commit 23d9a33 into jwtk:master Apr 22, 2024
24 checks passed
@lhazlewood lhazlewood added this to the 0.12.6 milestone Apr 22, 2024
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

Successfully merging this pull request may close these issues.

None yet

3 participants