fix: replace CryptoAlgorithms audit wrap instanceof chain with Java 21

switch

Replace the AUDIT_MODE == WRAP dispatch in
zeroecho.core.CryptoAlgorithms#create(...) with an exhaustive Java 21
pattern switch over the sealed CryptoContext hierarchy. This removes the
repeated instanceof chain, keeps unchecked casts localized in a single
internal helper, and closes the missing audit-wrap gap for
AgreementContext.

Add focused JUnit 5 coverage for audited proxy wrapping using
Mockito-based tests for representative context interfaces and wrapper
lifecycle delegation.

Closes #20
Time-Spent: 45m
This commit is contained in:
2026-04-05 22:17:14 +02:00
parent a4b9eeffe1
commit 14fbf31989
3 changed files with 156 additions and 22 deletions

View File

@@ -49,6 +49,7 @@ import javax.crypto.SecretKey;
import zeroecho.core.audit.AuditListener;
import zeroecho.core.audit.AuditedContexts;
import zeroecho.core.context.AgreementContext;
import zeroecho.core.context.CryptoContext;
import zeroecho.core.context.DigestContext;
import zeroecho.core.context.EncryptionContext;
@@ -335,33 +336,39 @@ public final class CryptoAlgorithms {
if (AUDIT_MODE == AuditMode.WRAP) {
final AuditListener listener = AUDIT; // pass through the global listener
if (ctx instanceof SignatureContext) {
@SuppressWarnings("unchecked")
C out = (C) AuditedContexts.wrap(ctx, listener, role);
return out;
} else if (ctx instanceof EncryptionContext) {
@SuppressWarnings("unchecked")
C out = (C) AuditedContexts.wrap(ctx, listener, role);
return out;
} else if (ctx instanceof KemContext) {
@SuppressWarnings("unchecked")
C out = (C) AuditedContexts.wrap(ctx, listener, role);
return out;
} else if (ctx instanceof DigestContext) {
@SuppressWarnings("unchecked")
C out = (C) AuditedContexts.wrap(ctx, listener, role);
return out;
} else if (ctx instanceof MacContext) {
@SuppressWarnings("unchecked")
C out = (C) AuditedContexts.wrap(ctx, listener, role);
return out;
}
// Unknown context type: return as-is (no wrapping).
return switch (ctx) {
case SignatureContext signatureContext -> wrapForAudit(signatureContext, listener, role);
case EncryptionContext encryptionContext -> wrapForAudit(encryptionContext, listener, role);
case KemContext kemContext -> wrapForAudit(kemContext, listener, role);
case DigestContext digestContext -> wrapForAudit(digestContext, listener, role);
case MacContext macContext -> wrapForAudit(macContext, listener, role);
case AgreementContext agreementContext -> wrapForAudit(agreementContext, listener, role);
};
}
return ctx;
}
/**
* Returns the audited wrapper for the supplied context.
*
* <p>
* The returned context remains owned by the caller of the factory method. This
* helper does not acquire an additional resource requiring local cleanup.
* </p>
*
* @param <C> context type
* @param context source context
* @param listener audit listener
* @param role key usage role
* @return audited wrapper
*/
@SuppressWarnings("unchecked")
/* default */ static <C extends CryptoContext> C wrapForAudit(CryptoContext context, AuditListener listener,
KeyUsage role) {
return (C) AuditedContexts.wrap(context, listener, role);
}
/**
* Creates a {@link CryptoContext} using the algorithms default spec for the
* role.