Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ab1e729
feat(signing): add core L1 signing SPI interfaces (AdcpUse, SigningCo…
Jun 17, 2026
3b3ad10
feat(signing): add RFC 9421 canonicalizer, signer, verifier, and conf…
Jun 17, 2026
2f4e923
feat(signing): add InProcessSigningProvider, WebhookSigner seam, and …
Jun 17, 2026
8bfda3b
feat(signing): add KMS provider module skeletons and BouncyCastle stub
Jun 17, 2026
19ed167
docs(signing): add RFC 9421 canonicalizer design spec
Jun 17, 2026
28697e5
feat(signing): implement AWS KMS SigningProvider with lazy-init, trip…
Jun 17, 2026
3578adf
feat(signing): implement GCP KMS SigningProvider with lazy-init, trip…
Jun 17, 2026
57fbd1e
feat(signing): add JWKS VerificationKeyResolver with caching, SSRF va…
Jun 17, 2026
689d122
feat(signing): add InMemoryReplayStore and InMemoryRevocationStore fo…
Jun 17, 2026
82802fa
feat(signing): add pre-deploy KMS probe CLI command
Jun 17, 2026
3ce0955
feat(signing): add SigningKeyGenerator for Ed25519/ES256/ES384 keypai…
Jun 17, 2026
d98cf3e
feat(signing): add IDNA hostname canonicalization to Rfc9421Canonical…
Jun 17, 2026
15ebe32
feat(signing): add key origin consistency check and eTLD+1 utility
Jun 17, 2026
7147c61
feat(signing): add JWS verification for revocation lists
Jun 17, 2026
fada93f
feat(signing): add CachingRevocationChecker with JWS verification
Jun 17, 2026
9d4f17d
feat(signing): add legacy HMAC-SHA256 webhook verification (deprecated)
Jun 17, 2026
f3d9c7b
feat(signing): add Standard Webhooks v1 interop verifier
Jun 17, 2026
5ee26c1
feat(signing): add webhook challenge proof-of-control
Jun 17, 2026
7165a40
chore: add gitguardian config to ignore test key fixtures
Jun 17, 2026
a15e3f6
chore: add gitguardian config to ignore test key fixtures
Jun 17, 2026
125b8a5
chore: remove gitguardian config (paths-ignore requires default branc…
Jun 17, 2026
f53b5a5
fix(signing): address P1/P2 review findings — malformed input safety,…
Jun 19, 2026
1747db0
Merge branch 'main' into feat/l1-signing-track4
MichielDean Jun 21, 2026
4d09593
fix(config): correct ggshield config shape, filename, and ignore patt…
Jun 21, 2026
6ea9036
fix(signing): address P1/P2 review feedback — parser differential, JW…
Jun 21, 2026
fcecf25
fix(changeset): use empty frontmatter for gradle-only repo
Jun 21, 2026
3f47af0
fix(signing): public probe methods, Rfc9421Signer empty-body/P-384, r…
Jun 21, 2026
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: 4 additions & 0 deletions .changeset/l1-signing-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

L1 signing hardening: RFC 9421 verification fixes for parser differential, JWK alg/kty/crv validation, error taxonomy, P-384 allowlist, empty-body webhook digest, and GCP KMS digest branching. See commit 6ea9036 for details.
33 changes: 33 additions & 0 deletions .gitguardian.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# GitGuardian / ggshield configuration for adcp-sdk-java
#
# Test key material in the compliance vectors is intentionally public.
# The _private_d_for_test_only fields in keys.json expose the full private
# key on every entry so SDK signer/verifier round-trips can be exercised
# against the same material. These keys are valid ONLY for grading against
# the AdCP conformance vectors and MUST NOT be used in production. The
# keys.json files carry explicit _WARNING and $comment banners.
#
# See:
# adcp-server/src/test/resources/compliance/webhook-signing/README.md
# adcp-server/src/test/resources/compliance/request-signing/README.md
#
# NOTE: This file configures the ggshield CLI (local scans, pre-commit,
# future CI integration). It is NOT consumed by the "GitGuardian Security
# Checks" GitHub App check-run, which is driven by the GitGuardian
# dashboard. To suppress that check-run for these fixtures, a workspace
# admin must add matching filepath exclusions under
# GitGuardian dashboard > Secrets Detection > Exclusion rules > Filepath
# The exact paths below should be mirrored there. See:
# https://docs.gitguardian.com/secrets-detection/customize-detection/exclusion-rules#filepath-exclusions
#
# Config schema: ggshield v2 (https://docs.gitguardian.com/ggshield-docs/configuration)
# Required: version: 2 — without it ggshield treats the file as v1.
version: 2

secret:
# Exclude only the exact public test-vector key files. Do not use a
# broad glob like **/*hmac* — no fixture is named *hmac* today, and a
# name-based bypass would silently exclude unrelated future files.
ignored_paths:
- 'adcp-server/src/test/resources/compliance/request-signing/keys.json'
- 'adcp-server/src/test/resources/compliance/webhook-signing/keys.json'
118 changes: 113 additions & 5 deletions adcp-cli/src/main/java/org/adcontextprotocol/adcp/cli/Main.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
package org.adcontextprotocol.adcp.cli;

import org.adcontextprotocol.adcp.signing.AdcpUse;

import java.util.ArrayList;
import java.util.List;

/**
* Entry point for the {@code adcp} CLI. Commands land here as the CLI track
* is implemented; today this is a placeholder that prints a usage stub.
* Entry point for the {@code adcp} CLI.
*
* <p>Subcommands:
* <ul>
* <li>{@code signing-probe} — pre-deploy KMS connectivity and key usability check</li>
* </ul>
*/
public final class Main {

Expand All @@ -11,7 +20,106 @@ private Main() {
}

public static void main(String[] args) {
System.out.println("adcp <not yet implemented>");
System.out.println("see ROADMAP.md track 13 (cli) for the planned surface");
if (args.length == 0) {
printUsage();
System.exit(1);
}

String command = args[0];
String[] subArgs = new String[args.length - 1];
System.arraycopy(args, 1, subArgs, 0, subArgs.length);

switch (command) {
case "signing-probe" -> runSigningProbe(subArgs);
default -> {
System.err.println("Unknown command: " + command);
printUsage();
System.exit(1);
}
}
}

private static void runSigningProbe(String[] args) {
SigningProbeCommand probe = new SigningProbeCommand();
List<String> errors = new ArrayList<>();

int i = 0;
while (i < args.length) {
String arg = args[i];
switch (arg) {
case "--aws-key" -> {
if (i + 3 >= args.length) {
errors.add("--aws-key requires <use> <key-arn> <region>");
i = args.length;
} else {
try {
AdcpUse use = AdcpUse.fromWireName(args[i + 1]);
probe.addAwsKey(use, args[i + 2], args[i + 3]);
} catch (IllegalArgumentException e) {
errors.add("Invalid adcp_use for --aws-key: " + args[i + 1]
+ ". Valid values: adcp_req, adcp_whk");
}
i += 4;
}
}
case "--gcp-key" -> {
if (i + 3 >= args.length) {
errors.add("--gcp-key requires <use> <key-version-path> <credentials-path>");
i = args.length;
} else {
try {
AdcpUse use = AdcpUse.fromWireName(args[i + 1]);
probe.addGcpKey(use, args[i + 2], args[i + 3]);
} catch (IllegalArgumentException e) {
errors.add("Invalid adcp_use for --gcp-key: " + args[i + 1]
+ ". Valid values: adcp_req, adcp_whk");
}
i += 4;
}
}
default -> {
errors.add("Unknown option: " + arg);
i++;
}
}
}

if (!errors.isEmpty()) {
for (String error : errors) {
System.err.println("Error: " + error);
}
System.err.println();
printSigningProbeUsage();
System.exit(1);
}

try {
int exitCode = probe.call();
System.exit(exitCode);
} catch (Exception e) {
System.err.println("Probe failed: " + e.getMessage());
System.exit(1);
}
}

private static void printUsage() {
System.out.println("Usage: adcp <command> [options]");
System.out.println();
System.out.println("Commands:");
System.out.println(" signing-probe Pre-deploy KMS connectivity and key usability check");
System.out.println();
System.out.println("Run 'adcp <command> --help' for command details.");
}

private static void printSigningProbeUsage() {
System.out.println("Usage: adcp signing-probe [options]");
System.out.println();
System.out.println("Options:");
System.out.println(" --aws-key <use> <key-arn> <region>");
System.out.println(" Probe an AWS KMS key. <use> is adcp_req or adcp_whk.");
System.out.println(" --gcp-key <use> <key-version-path> <credentials-path>");
System.out.println(" Probe a GCP KMS key. <use> is adcp_req or adcp_whk.");
System.out.println();
System.out.println("Exit code: 0 if all probes pass, 1 if any fail.");
}
}
}
Loading
Loading