security(lib): enforce single-use encryption contexts

This commit is contained in:
2026-07-29 17:28:32 +02:00
parent 8af75a9508
commit 9bbcab7522
18 changed files with 673 additions and 160 deletions

View File

@@ -154,7 +154,7 @@ public final class Guard {
final Option OPT_TAG_BITS = Option.builder().longOpt("tag-bits").hasArg().argName("96..128")
.desc("AES-GCM tag length in bits (default 128)").get();
final Option OPT_NONCE_HEX = Option.builder().longOpt("nonce-hex").hasArg().argName("hex")
.desc("ChaCha nonce (12-byte hex)").get();
.desc("ChaCha decryption nonce (12-byte hex; rejected for encryption)").get();
final Option OPT_INIT_CTR = Option.builder().longOpt("init-ctr").hasArg().argName("int")
.desc("ChaCha stream initial counter (default 1)").get();
final Option OPT_CTR = Option.builder().longOpt("ctr").hasArg().argName("int")
@@ -303,7 +303,7 @@ public final class Guard {
chacha.withHeader();
}
if (chachaNonce != null) {
chacha.withNonce(chachaNonce);
chacha.withDecryptionNonce(chachaNonce);
}
if (ctrOverride != null || initCtr != null) {
// providing counters together with AAD would be conflicting; builder enforces
@@ -323,7 +323,7 @@ public final class Guard {
chacha.withHeader();
}
if (chachaNonce != null) {
chacha.withNonce(chachaNonce);
chacha.withDecryptionNonce(chachaNonce);
}
if (initCtr != null) {
chacha.initialCounter(initCtr);

View File

@@ -181,7 +181,7 @@ public final class Kem { // NOPMD
/** AES IV: --aes-iv <hex> */
public static final Option OPT_AES_IV = Option.builder().longOpt("aes-iv").hasArg().argName("hex")
.desc("AES IV/nonce (hex)").get();
.desc("AES decryption IV/nonce (hex; rejected for encryption)").get();
/** AES tag bits: --aes-tag-bits <int> */
public static final Option OPT_AES_TAG_BITS = Option.builder().longOpt("aes-tag-bits").hasArg().argName("int")
@@ -189,7 +189,7 @@ public final class Kem { // NOPMD
/** ChaCha nonce: --chacha-nonce <hex> */
public static final Option OPT_CHACHA_NONCE = Option.builder().longOpt("chacha-nonce").hasArg().argName("hex")
.desc("ChaCha nonce (hex, usually 12 bytes)").get();
.desc("ChaCha decryption nonce (hex, usually 12 bytes; rejected for encryption)").get();
/** ChaCha counter value: --chacha-counter <int> */
public static final Option OPT_CHACHA_COUNTER = Option.builder().longOpt("chacha-counter").hasArg().argName("int")
@@ -283,7 +283,7 @@ public final class Kem { // NOPMD
}
byte[] iv = parseHexOpt(cmd, OPT_AES_IV);
if (iv != null) {
aes = aes.withIv(iv);
aes = aes.withDecryptionIv(iv);
}
if (aad != null && aad.length > 0) {
aes = aes.withAad(aad);
@@ -299,7 +299,7 @@ public final class Kem { // NOPMD
ChaChaDataContentBuilder cc = ChaChaDataContentBuilder.builder(session);
byte[] nonce = parseHexOpt(cmd, OPT_CHACHA_NONCE);
if (nonce != null) {
cc = cc.withNonce(nonce);
cc = cc.withDecryptionNonce(nonce);
}
// counter is an integer, not bytes; use typed parsed option
Integer counter = parsedIntOpt(cmd, OPT_CHACHA_COUNTER);