)]}'
{
  "commit": "cfee8fd9fbd971bc214cfb887289766ceca35306",
  "tree": "ff02269afcdea9e8883c6f5c620764721e5bdb81",
  "parents": [
    "f9c845e317b0793da705d1c4bc0f72f9a96e105e"
  ],
  "author": {
    "name": "Ben Collins",
    "email": "bcollins@libjwt.io",
    "time": "Mon Jun 15 20:17:07 2026 -0400"
  },
  "committer": {
    "name": "Ben Collins",
    "email": "bcollins@libjwt.io",
    "time": "Mon Jun 15 20:17:07 2026 -0400"
  },
  "message": "feat: add experimental ML-DSA (FIPS 204 / RFC 9964) signing\n\nAdd support for the post-quantum ML-DSA signature algorithms (ML-DSA-44,\nML-DSA-65, ML-DSA-87) registered for JOSE by RFC 9964. ML-DSA keys use the\nnew \"AKP\" (Algorithm Key Pair) JWK key type with a \"pub\" member and a \"priv\"\nmember holding the 32-byte FIPS-204 seed; \"alg\" is required on every AKP key.\n\nThe feature is experimental and off by default: build with -DWITH_ML_DSA\u003dON.\nIt is only enabled when a backend that implements ML-DSA is present (OpenSSL\n\u003e\u003d 3.5 today), and the public header then defines LIBJWT_HAVE_ML_DSA so\ndownstream code can detect it. The JWT_ALG_ML_DSA_* and JWK_KEY_TYPE_AKP enum\nvalues are always present (ABI), but all behavior is gated on the macro.\n\n- OpenSSL: real sign/verify (one-shot, like EdDSA), AKP JWK parse via the\n  seed, and native-key -\u003e JWK export. A seedless private key (one with no\n  retained FIPS-204 seed) downgrades to a clean public export rather than a\n  private JWK with no private material.\n- GnuTLS / MbedTLS: cleanly reject AKP keys at parse time via a null-guard on\n  jwt_ops-\u003eprocess_mldsa (a real GnuTLS implementation is tracked in #301).\n- Anti algorithm-confusion: ML-DSA maps to JWK_KEY_TYPE_AKP only, and the\n  variant is pinned to the key, so a 44 key cannot be used for an 87 token.\n\nTests cover sign/verify and the emitted header alg for all three variants,\nAKP parse-error branches, the non-OpenSSL reject path, native PEM/DER -\u003e JWK\nexport (including the seedless downgrade), public-export priv-stripping, and\nthe CLI tools, under both Jansson and json-c.\n\ncloses #227\n\nCo-Authored-By: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e\nSigned-off-by: Ben Collins \u003cbcollins@libjwt.io\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "1d5fb6c0a75ec5b97f4857c089c3dbeaec4114b1",
      "old_mode": 33188,
      "old_path": "CMakeLists.txt",
      "new_id": "15558f8ce34f8c151390432fc612b19dea7916a4",
      "new_mode": 33188,
      "new_path": "CMakeLists.txt"
    },
    {
      "type": "modify",
      "old_id": "aeb2d3d78843a89aa495792db857b3d47d962704",
      "old_mode": 33188,
      "old_path": "README.md",
      "new_id": "3bfce875f9c6e84dfa0ec8b5f13954b4fc52418c",
      "new_mode": 33188,
      "new_path": "README.md"
    },
    {
      "type": "modify",
      "old_id": "bcf253f97c0a93da9f8405eb5bfd2e831f99b555",
      "old_mode": 33188,
      "old_path": "include/jwt.h",
      "new_id": "f15c324dfe9cb41c4197b274d1aa0f6cc99cf2e1",
      "new_mode": 33188,
      "new_path": "include/jwt.h"
    },
    {
      "type": "modify",
      "old_id": "324c9908fc3e4820ba536ad306d74777b64fdf79",
      "old_mode": 33188,
      "old_path": "include/jwt_export.h.in",
      "new_id": "212c129d85505252b6374ec072d4a1c527d2854c",
      "new_mode": 33188,
      "new_path": "include/jwt_export.h.in"
    },
    {
      "type": "modify",
      "old_id": "ad30f228f243055089f2c92c8f02278d1e514f7d",
      "old_mode": 33188,
      "old_path": "libjwt/jwk-export.c",
      "new_id": "0df31ce32ec0c31794bdb0d928e59a48f737b534",
      "new_mode": 33188,
      "new_path": "libjwt/jwk-export.c"
    },
    {
      "type": "modify",
      "old_id": "4acf146321a95839e25744ba7ac3cd4b9c45b1ca",
      "old_mode": 33188,
      "old_path": "libjwt/jwks.c",
      "new_id": "3c7fa502378244e50503fa10e10bb2d6f00c1c8e",
      "new_mode": 33188,
      "new_path": "libjwt/jwks.c"
    },
    {
      "type": "modify",
      "old_id": "67b6dd1efbdb0a5dd58cc7a5b763c0ed13c43b1d",
      "old_mode": 33188,
      "old_path": "libjwt/jwt-private.h",
      "new_id": "b134d0317009b05a8056e78d5fb28d7fc3d86c14",
      "new_mode": 33188,
      "new_path": "libjwt/jwt-private.h"
    },
    {
      "type": "modify",
      "old_id": "84cd557f5f424c53455df0ea491dfaea36132041",
      "old_mode": 33188,
      "old_path": "libjwt/jwt.c",
      "new_id": "6cf6c9095ef54f6246360e8f04acf321e09d63f3",
      "new_mode": 33188,
      "new_path": "libjwt/jwt.c"
    },
    {
      "type": "modify",
      "old_id": "e9f9ca1fb49930eee9fd2ace9e77fc7c105e722c",
      "old_mode": 33188,
      "old_path": "libjwt/openssl/jwk-export.c",
      "new_id": "1fd0033c4eca6dc0599e2bbe34884ac280b60dc9",
      "new_mode": 33188,
      "new_path": "libjwt/openssl/jwk-export.c"
    },
    {
      "type": "modify",
      "old_id": "f4d9c635add83b4d398af5991e492c987fcbd82a",
      "old_mode": 33188,
      "old_path": "libjwt/openssl/jwk-parse.c",
      "new_id": "6b5cc63ecc363de69bfa5f8eba2ff4b6f835fa98",
      "new_mode": 33188,
      "new_path": "libjwt/openssl/jwk-parse.c"
    },
    {
      "type": "modify",
      "old_id": "e493624a7dcf2200285d04e99a772de3cbdc91ca",
      "old_mode": 33188,
      "old_path": "libjwt/openssl/jwt-openssl.h",
      "new_id": "1495bbb7a70a2a87090b9bd0e5c7749aacc28d00",
      "new_mode": 33188,
      "new_path": "libjwt/openssl/jwt-openssl.h"
    },
    {
      "type": "modify",
      "old_id": "001886dcd9dbfcd24ff60c91057ffbdd82e598fc",
      "old_mode": 33188,
      "old_path": "libjwt/openssl/sign-verify.c",
      "new_id": "7c68e56d081c98961e19a6c411d8787ed5183137",
      "new_mode": 33188,
      "new_path": "libjwt/openssl/sign-verify.c"
    },
    {
      "type": "modify",
      "old_id": "31329dd08bcc9eed511e823ce32f133318d61dea",
      "old_mode": 33261,
      "old_path": "tests/jwt-cli.bats",
      "new_id": "14b4970ef410162af7fe6a263b9ee05ff1a35f3c",
      "new_mode": 33261,
      "new_path": "tests/jwt-cli.bats"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d51306acba9145a35d0571c82b1b40ce52462a73",
      "new_mode": 33188,
      "new_path": "tests/jwt_mldsa.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "889ad7c8f01a32ed233abb9068a28671fbaeaa47",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_44.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1ff55ffaffbfe0efd6229392fbd62a6acfe55784",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_44.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "74fae0ec7e3d2a5e60e82c7933054b8914362e93",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_44_pub.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "4bb4491ef4b4de7098bfbddab0e255e9979a8196",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_44_pub.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7b8ed8b170d2bc08b82827ca680e982f8c8e6197",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_44_seedless.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "57aa45eb1c950d87ffd104c7b1b6f89287db6387",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_65.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "c4ed7be3ed7a3c2a36b40e2449633c3b065ee9d7",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_65.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "3d5202be67e9341f199f96b951cd8d35161f14c7",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_65_pub.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1aaa092b27ed54caa4f4b10e7955ce151303bcda",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_65_pub.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "cfd4c4f22c0457b01854c5138f403e5bbb6ab5a7",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_87.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "0ea00f5a6429c5eb05084f51c652b16b7b622db6",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_87.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "ce92cb7948f60e5e6a23143e682da0ef062aaeb1",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_87_pub.der"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "de7d78bc443cbb4cd401aaf985102c6bc4719b9a",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa-pem/mldsa_key_87_pub.pem"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "b6d44a5a695bc81baae998a4ccc9b8ab9bceac04",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_44.json"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d020394f3a0d3193b8334cf5d35e310386d5c753",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_44_pub.json"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "9edcd76fc457783518874046d0ae59f02f146704",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_65.json"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "79d046895256b5bc0607ab5d91c47fc957648857",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_65_pub.json"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7818d1f9c910fcb43a3315e07f472bb0f1d24033",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_87.json"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "be1ef0888266d2db386558f314f46258718f51fa",
      "new_mode": 33188,
      "new_path": "tests/keys/mldsa_key_87_pub.json"
    },
    {
      "type": "modify",
      "old_id": "f95ae0dd505021657534b045517b451c27456ae2",
      "old_mode": 33188,
      "old_path": "tools/jwk2key.c",
      "new_id": "b2598aaf42560c18d074c32b287b309c9143553c",
      "new_mode": 33188,
      "new_path": "tools/jwk2key.c"
    },
    {
      "type": "modify",
      "old_id": "818a34de4501d0d6a39bdd8eb160064e05ca46f4",
      "old_mode": 33188,
      "old_path": "tools/jwt-generate.c",
      "new_id": "51bd4b6bb33b1931ec6b1c1518450e2e552527a5",
      "new_mode": 33188,
      "new_path": "tools/jwt-generate.c"
    },
    {
      "type": "modify",
      "old_id": "47188f1cb9909dea7a1a63f55cae217c1cc14feb",
      "old_mode": 33188,
      "old_path": "tools/jwt-verify.c",
      "new_id": "35a4eec3568e81e62bf0e82c2f7b4357532c354a",
      "new_mode": 33188,
      "new_path": "tools/jwt-verify.c"
    },
    {
      "type": "modify",
      "old_id": "c96fc96d20570e1eae35fd908aec142a539dc783",
      "old_mode": 33188,
      "old_path": "tools/key2jwk.c",
      "new_id": "83f1c2e40325d282e1308a70bdf0bfe25e00c8f5",
      "new_mode": 33188,
      "new_path": "tools/key2jwk.c"
    }
  ]
}
