move things to an SPI pattern#372
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request refactors the hybrid post-quantum key wrapping implementation by extracting it into a separate module (sdk-hybrid-bouncycastle) and introducing the HybridKeyWrapProvider Service Provider Interface (SPI). This decouples the core sdk module from a compile-time dependency on BouncyCastle, resolving implementations at runtime via ServiceLoader. The review feedback recommends adding defensive null checks for keyType and other parameters across several methods (such as wrapDEK, unwrapDEK, HybridKeyWrapResolver.get, and HybridTestKeys.generate) to prevent potential NullPointerExceptions when switching on enum values or processing null arguments.
| public byte[] wrapDEK(KeyType keyType, String publicKeyPem, byte[] dek) { | ||
| switch (keyType) { | ||
| case HybridXWingKey: | ||
| return XWingKeyPair.wrapDEK(XWingKeyPair.pubKeyFromPem(publicKeyPem), dek); | ||
| case HybridSecp256r1MLKEM768Key: | ||
| return HybridNISTKeyPair.P256_MLKEM768.wrapDEK( | ||
| HybridNISTKeyPair.P256_MLKEM768.pubKeyFromPem(publicKeyPem), dek); | ||
| case HybridSecp384r1MLKEM1024Key: | ||
| return HybridNISTKeyPair.P384_MLKEM1024.wrapDEK( | ||
| HybridNISTKeyPair.P384_MLKEM1024.pubKeyFromPem(publicKeyPem), dek); | ||
| default: | ||
| throw new SDKException("unsupported hybrid key type: " + keyType); | ||
| } | ||
| } |
There was a problem hiding this comment.
In Java, switching on a null reference throws a NullPointerException. To prevent runtime failures, add defensive null checks for keyType, publicKeyPem, and dek before executing the switch statement.
public byte[] wrapDEK(KeyType keyType, String publicKeyPem, byte[] dek) {
if (keyType == null) {
throw new SDKException("keyType cannot be null");
}
if (publicKeyPem == null) {
throw new SDKException("publicKeyPem cannot be null");
}
if (dek == null) {
throw new SDKException("dek cannot be null");
}
switch (keyType) {
case HybridXWingKey:
return XWingKeyPair.wrapDEK(XWingKeyPair.pubKeyFromPem(publicKeyPem), dek);
case HybridSecp256r1MLKEM768Key:
return HybridNISTKeyPair.P256_MLKEM768.wrapDEK(
HybridNISTKeyPair.P256_MLKEM768.pubKeyFromPem(publicKeyPem), dek);
case HybridSecp384r1MLKEM1024Key:
return HybridNISTKeyPair.P384_MLKEM1024.wrapDEK(
HybridNISTKeyPair.P384_MLKEM1024.pubKeyFromPem(publicKeyPem), dek);
default:
throw new SDKException("unsupported hybrid key type: " + keyType);
}
}| public byte[] unwrapDEK(KeyType keyType, String privateKeyPem, byte[] wrappedDek) { | ||
| switch (keyType) { | ||
| case HybridXWingKey: | ||
| return XWingKeyPair.unwrapDEK(XWingKeyPair.privateKeyFromPem(privateKeyPem), wrappedDek); | ||
| case HybridSecp256r1MLKEM768Key: | ||
| return HybridNISTKeyPair.P256_MLKEM768.unwrapDEK( | ||
| HybridNISTKeyPair.P256_MLKEM768.privateKeyFromPem(privateKeyPem), wrappedDek); | ||
| case HybridSecp384r1MLKEM1024Key: | ||
| return HybridNISTKeyPair.P384_MLKEM1024.unwrapDEK( | ||
| HybridNISTKeyPair.P384_MLKEM1024.privateKeyFromPem(privateKeyPem), wrappedDek); | ||
| default: | ||
| throw new SDKException("unsupported hybrid key type: " + keyType); | ||
| } | ||
| } |
There was a problem hiding this comment.
In Java, switching on a null reference throws a NullPointerException. To prevent runtime failures, add defensive null checks for keyType, privateKeyPem, and wrappedDek before executing the switch statement.
public byte[] unwrapDEK(KeyType keyType, String privateKeyPem, byte[] wrappedDek) {
if (keyType == null) {
throw new SDKException("keyType cannot be null");
}
if (privateKeyPem == null) {
throw new SDKException("privateKeyPem cannot be null");
}
if (wrappedDek == null) {
throw new SDKException("wrappedDek cannot be null");
}
switch (keyType) {
case HybridXWingKey:
return XWingKeyPair.unwrapDEK(XWingKeyPair.privateKeyFromPem(privateKeyPem), wrappedDek);
case HybridSecp256r1MLKEM768Key:
return HybridNISTKeyPair.P256_MLKEM768.unwrapDEK(
HybridNISTKeyPair.P256_MLKEM768.privateKeyFromPem(privateKeyPem), wrappedDek);
case HybridSecp384r1MLKEM1024Key:
return HybridNISTKeyPair.P384_MLKEM1024.unwrapDEK(
HybridNISTKeyPair.P384_MLKEM1024.privateKeyFromPem(privateKeyPem), wrappedDek);
default:
throw new SDKException("unsupported hybrid key type: " + keyType);
}
}| static HybridKeyWrapProvider get(KeyType keyType) { | ||
| for (HybridKeyWrapProvider p : Holder.PROVIDERS) { | ||
| if (p.supports(keyType)) { | ||
| return p; | ||
| } | ||
| } | ||
| throw new SDKException("No HybridKeyWrapProvider registered for " + keyType | ||
| + ". Add io.opentdf.platform:sdk-hybrid-bouncycastle to your classpath."); | ||
| } |
There was a problem hiding this comment.
Add a defensive null check for keyType at the beginning of the get method to prevent potential NullPointerException or unexpected behavior during resolution.
static HybridKeyWrapProvider get(KeyType keyType) {
if (keyType == null) {
throw new SDKException("keyType cannot be null");
}
for (HybridKeyWrapProvider p : Holder.PROVIDERS) {
if (p.supports(keyType)) {
return p;
}
}
throw new SDKException("No HybridKeyWrapProvider registered for " + keyType
+ ". Add io.opentdf.platform:sdk-hybrid-bouncycastle to your classpath.");
}| public static PemPair generate(KeyType keyType) { | ||
| switch (keyType) { |
There was a problem hiding this comment.
No description provided.