From ab0136df1b326b969c6a9430124487787c35ccd5 Mon Sep 17 00:00:00 2001 From: Dave Grantham Date: Mon, 14 Sep 2026 11:17:27 -0600 Subject: [PATCH 1/3] deprecate McEliece codec variants Signed-off-by: Dave Grantham --- CHANGELOG.md | 13 +++++++++ Cargo.toml | 2 +- build.rs | 17 ++++++++++- src/codec.rs | 19 ++++++++++-- src/table_gen.rs | 75 +++++++++++++++++++++++++----------------------- table.csv | 3 ++ 6 files changed, 89 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97085ed..9298447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +## [1.4.0] - 2026-09-03 + +### Added + +- Three new codec entries for the proof-of-possession framework: `multiproof` (`0xd01330`, multiformat), `wacc-script-with-pop` (`0xd01331`, multiformat), and `xeddsa-msig` (`0xd01332`, multisig). +- The `Codec` enum now has 885 variants (up from 882). + +### Notes + +- This is a minor version bump. The `Codec` enum is `#[non_exhaustive]`, so new variants are additive and do not break downstream match expressions. + ## [1.3.0] - 2026-09-01 ### Added diff --git a/Cargo.toml b/Cargo.toml index 1439198..73eb9df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-codec" -version = "1.3.0" +version = "1.4.0" edition = "2024" rust-version = "1.85" authors = ["Benjamin Kampmann ", "Dave Grantham "] diff --git a/build.rs b/build.rs index 723fc77..674d84c 100644 --- a/build.rs +++ b/build.rs @@ -89,7 +89,22 @@ fn main() -> Result<(), Box> { // Generate enum variant let variant_name = conv.convert(&rec.name); - writeln!(f, "\t{} => ({}, \"{}\"),", code_str, variant_name, rec.name)?; + // Classic McEliece key material is deprecated. Key-recovery attacks now + // solve the TII McEliece challenges, so every McEliece variant carries a + // deprecation attribute; uses emit a compiler warning. The variants stay + // compiled and decodable so stored multicodec-tagged data keeps working. + // See https://github.com/mjosaarinen/tii-solved for the recovered keys. + // The attribute precedes the variant name inside the tuple so the + // macro's `expr` fragment stays unambiguous. + if rec.name.contains("mceliece") { + writeln!( + f, + "\t{} => (#[deprecated(since = \"1.5.0\", note = \"Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved\")] {}, \"{}\"),", + code_str, variant_name, rec.name + )?; + } else { + writeln!(f, "\t{} => ({}, \"{}\"),", code_str, variant_name, rec.name)?; + } record_count += 1; } diff --git a/src/codec.rs b/src/codec.rs index bdd1413..a868d05 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -31,7 +31,7 @@ use core::{ use multi_trait::{EncodeInto, Null, TryDecodeFrom}; macro_rules! build_codec_enum { - {$( $val:expr => ($i:ident, $s:expr), )*} => { + {$( $val:expr => ( $(#[$vattr:meta])* $i:ident, $s:expr), )*} => { /// Codecs from the multicodec table #[allow(non_camel_case_types)] @@ -39,11 +39,12 @@ macro_rules! build_codec_enum { #[non_exhaustive] pub enum Codec { #[default] - $( $i, )* + $( $(#[$vattr])* $i, )* } /// Convert from the canonical string name of the multicodec to the /// associated enum/value. + #[allow(deprecated)] impl TryFrom<&str> for Codec { type Error = Error; @@ -56,6 +57,7 @@ macro_rules! build_codec_enum { } /// Convert a Codec into a type that implements `AsRef` + #[allow(deprecated)] impl From for &str { fn from(codec: Codec) -> &'static str { match codec { @@ -65,6 +67,7 @@ macro_rules! build_codec_enum { } /// Convert from the value of the multicodec to the associated enum/value. + #[allow(deprecated)] impl TryFrom for Codec { type Error = Error; @@ -77,6 +80,7 @@ macro_rules! build_codec_enum { } /// Convert a Codec into a u64 + #[allow(deprecated)] impl From for u64 { fn from(codec: Codec) -> u64 { match codec { @@ -285,6 +289,17 @@ mod tests { assert_eq!("ed25519-pub", Codec::Ed25519Pub.as_str()); } + #[test] + #[allow(deprecated)] + fn test_mceliece_roundtrip() { + // The McEliece variants are deprecated but stay compiled and decodable + // so stored multicodec-tagged data keeps working. + let codec = Codec::try_from(0x1220).unwrap(); + assert_eq!(Codec::Mceliece348864Pub, codec); + assert_eq!("mceliece348864-pub", codec.as_str()); + assert_eq!(0x1220_u64, codec.code()); + } + #[test] fn test_from_str() { assert_eq!(Codec::Ed25519Pub, Codec::try_from("ed25519-pub").unwrap()); diff --git a/src/table_gen.rs b/src/table_gen.rs index 43bb8ae..48c1c93 100644 --- a/src/table_gen.rs +++ b/src/table_gen.rs @@ -190,23 +190,23 @@ build_codec_enum! { 0x121d => (SlhDsaShake256FPub, "slh-dsa-shake256f-pub"), 0x121e => (SlhDsaShake256SPub, "slh-dsa-shake256s-pub"), 0x121f => (Sntrup761Pub, "sntrup761-pub"), - 0x1220 => (Mceliece348864Pub, "mceliece348864-pub"), - 0x1221 => (Mceliece460896Pub, "mceliece460896-pub"), - 0x1250 => (Mceliece460896FPub, "mceliece460896f-pub"), - 0x1251 => (Mceliece460896PcPub, "mceliece460896pc-pub"), - 0x1252 => (Mceliece460896PcfPub, "mceliece460896pcf-pub"), - 0x1253 => (Mceliece6688128Pub, "mceliece6688128-pub"), - 0x1254 => (Mceliece6688128FPub, "mceliece6688128f-pub"), - 0x1255 => (Mceliece6688128PcPub, "mceliece6688128pc-pub"), - 0x1256 => (Mceliece6688128PcfPub, "mceliece6688128pcf-pub"), - 0x1257 => (Mceliece6960119Pub, "mceliece6960119-pub"), - 0x1258 => (Mceliece6960119FPub, "mceliece6960119f-pub"), - 0x1259 => (Mceliece6960119PcPub, "mceliece6960119pc-pub"), - 0x125a => (Mceliece6960119PcfPub, "mceliece6960119pcf-pub"), - 0x125b => (Mceliece8192128Pub, "mceliece8192128-pub"), - 0x125c => (Mceliece8192128FPub, "mceliece8192128f-pub"), - 0x125d => (Mceliece8192128PcPub, "mceliece8192128pc-pub"), - 0x125e => (Mceliece8192128PcfPub, "mceliece8192128pcf-pub"), + 0x1220 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece348864Pub, "mceliece348864-pub"), + 0x1221 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896Pub, "mceliece460896-pub"), + 0x1250 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896FPub, "mceliece460896f-pub"), + 0x1251 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896PcPub, "mceliece460896pc-pub"), + 0x1252 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896PcfPub, "mceliece460896pcf-pub"), + 0x1253 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128Pub, "mceliece6688128-pub"), + 0x1254 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128FPub, "mceliece6688128f-pub"), + 0x1255 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128PcPub, "mceliece6688128pc-pub"), + 0x1256 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128PcfPub, "mceliece6688128pcf-pub"), + 0x1257 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119Pub, "mceliece6960119-pub"), + 0x1258 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119FPub, "mceliece6960119f-pub"), + 0x1259 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119PcPub, "mceliece6960119pc-pub"), + 0x125a => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119PcfPub, "mceliece6960119pcf-pub"), + 0x125b => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128Pub, "mceliece8192128-pub"), + 0x125c => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128FPub, "mceliece8192128f-pub"), + 0x125d => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128PcPub, "mceliece8192128pc-pub"), + 0x125e => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128PcfPub, "mceliece8192128pcf-pub"), 0x1222 => (Rsa2048Pub, "rsa-2048-pub"), 0x1223 => (Rsa3072Pub, "rsa-3072-pub"), 0x1224 => (Rsa4096Pub, "rsa-4096-pub"), @@ -221,7 +221,7 @@ build_codec_enum! { 0x1230 => (X25519Sntrup761Pub, "x25519-sntrup761-pub"), 0x1243 => (X25519Frodokem640AesPub, "x25519-frodokem640aes-pub"), 0x1244 => (X25519Frodokem640ShakePub, "x25519-frodokem640shake-pub"), - 0x1245 => (X25519Mceliece348864Pub, "x25519-mceliece348864-pub"), + 0x1245 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] X25519Mceliece348864Pub, "x25519-mceliece348864-pub"), 0x1246 => (Bls12381G1Mldsa65Pub, "bls12381-g1-mldsa65-pub"), 0x1247 => (Bls12381G1Fndsa512Pub, "bls12381-g1-fndsa512-pub"), 0x1248 => (Bls12381G1Mayo1Pub, "bls12381-g1-mayo1-pub"), @@ -283,23 +283,23 @@ build_codec_enum! { 0x1326 => (SlhDsaShake256FPriv, "slh-dsa-shake256f-priv"), 0x1327 => (SlhDsaShake256SPriv, "slh-dsa-shake256s-priv"), 0x1328 => (Sntrup761Priv, "sntrup761-priv"), - 0x1329 => (Mceliece348864Priv, "mceliece348864-priv"), - 0x132a => (Mceliece460896Priv, "mceliece460896-priv"), - 0x135d => (Mceliece460896FPriv, "mceliece460896f-priv"), - 0x135e => (Mceliece460896PcPriv, "mceliece460896pc-priv"), - 0x135f => (Mceliece460896PcfPriv, "mceliece460896pcf-priv"), - 0x1360 => (Mceliece6688128Priv, "mceliece6688128-priv"), - 0x1361 => (Mceliece6688128FPriv, "mceliece6688128f-priv"), - 0x1362 => (Mceliece6688128PcPriv, "mceliece6688128pc-priv"), - 0x1363 => (Mceliece6688128PcfPriv, "mceliece6688128pcf-priv"), - 0x1364 => (Mceliece6960119Priv, "mceliece6960119-priv"), - 0x1365 => (Mceliece6960119FPriv, "mceliece6960119f-priv"), - 0x1366 => (Mceliece6960119PcPriv, "mceliece6960119pc-priv"), - 0x1367 => (Mceliece6960119PcfPriv, "mceliece6960119pcf-priv"), - 0x1368 => (Mceliece8192128Priv, "mceliece8192128-priv"), - 0x1369 => (Mceliece8192128FPriv, "mceliece8192128f-priv"), - 0x136a => (Mceliece8192128PcPriv, "mceliece8192128pc-priv"), - 0x136b => (Mceliece8192128PcfPriv, "mceliece8192128pcf-priv"), + 0x1329 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece348864Priv, "mceliece348864-priv"), + 0x132a => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896Priv, "mceliece460896-priv"), + 0x135d => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896FPriv, "mceliece460896f-priv"), + 0x135e => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896PcPriv, "mceliece460896pc-priv"), + 0x135f => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece460896PcfPriv, "mceliece460896pcf-priv"), + 0x1360 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128Priv, "mceliece6688128-priv"), + 0x1361 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128FPriv, "mceliece6688128f-priv"), + 0x1362 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128PcPriv, "mceliece6688128pc-priv"), + 0x1363 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6688128PcfPriv, "mceliece6688128pcf-priv"), + 0x1364 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119Priv, "mceliece6960119-priv"), + 0x1365 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119FPriv, "mceliece6960119f-priv"), + 0x1366 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119PcPriv, "mceliece6960119pc-priv"), + 0x1367 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece6960119PcfPriv, "mceliece6960119pcf-priv"), + 0x1368 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128Priv, "mceliece8192128-priv"), + 0x1369 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128FPriv, "mceliece8192128f-priv"), + 0x136a => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128PcPriv, "mceliece8192128pc-priv"), + 0x136b => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] Mceliece8192128PcfPriv, "mceliece8192128pcf-priv"), 0x132b => (Rsa2048Priv, "rsa-2048-priv"), 0x132c => (Rsa3072Priv, "rsa-3072-priv"), 0x132d => (Rsa4096Priv, "rsa-4096-priv"), @@ -314,7 +314,7 @@ build_codec_enum! { 0x1340 => (X25519Sntrup761Priv, "x25519-sntrup761-priv"), 0x1350 => (X25519Frodokem640AesPriv, "x25519-frodokem640aes-priv"), 0x1351 => (X25519Frodokem640ShakePriv, "x25519-frodokem640shake-priv"), - 0x1352 => (X25519Mceliece348864Priv, "x25519-mceliece348864-priv"), + 0x1352 => (#[deprecated(since = "1.5.0", note = "Classic McEliece key recovery attacks: see https://github.com/mjosaarinen/tii-solved")] X25519Mceliece348864Priv, "x25519-mceliece348864-priv"), 0x1353 => (Bls12381G1Mldsa65Priv, "bls12381-g1-mldsa65-priv"), 0x1354 => (Bls12381G1Fndsa512Priv, "bls12381-g1-fndsa512-priv"), 0x1355 => (Bls12381G1Mayo1Priv, "bls12381-g1-mayo1-priv"), @@ -866,6 +866,9 @@ build_codec_enum! { 0xd0132d => (XmssSha216256Msig, "xmss-sha2-16-256-msig"), 0xd0132e => (XmssSha220256Msig, "xmss-sha2-20-256-msig"), 0xd0132f => (Ed448Msig, "ed448-msig"), + 0xd01332 => (XeddsaMsig, "xeddsa-msig"), + 0xd01330 => (Multiproof, "multiproof"), + 0xd01331 => (WaccScriptWithPop, "wacc-script-with-pop"), 0xd01400 => (BsMessage, "bs-message"), 0xd02000 => (Scion, "scion"), 0xd03000 => (Ed25519ThreshPrivShare, "ed25519-thresh-priv-share"), diff --git a/table.csv b/table.csv index f3c2885..71da747 100644 --- a/table.csv +++ b/table.csv @@ -866,6 +866,9 @@ xmss-sha2-10-256-msig, multisig, 0xd0132c, draft, XMSS xmss-sha2-16-256-msig, multisig, 0xd0132d, draft, XMSS-SHA2_16_256 signature as Multisig; RFC 8391 xmss-sha2-20-256-msig, multisig, 0xd0132e, draft, XMSS-SHA2_20_256 signature as Multisig; RFC 8391 ed448-msig, multisig, 0xd0132f, draft, Ed448 (EdDSA) signature as Multisig; RFC 8032 +xeddsa-msig, multisig, 0xd01332, draft, XEdDSA signature over an X25519 key +multiproof, multiformat, 0xd01330, draft, Multiproof proof-of-possession object +wacc-script-with-pop, multiformat, 0xd01331, draft, WACC script with proof-of-possession envelope bs-message, multiformat, 0xd01400, draft, BetterSign signed+encrypted message multiformat scion, multiaddr, 0xd02000, draft, SCION Internet architecture ed25519-thresh-priv-share, key, 0xd03000, draft, Ed25519 FROST DKG threshold private key share From ba570eb172ab556e60909a170a247689222d51d2 Mon Sep 17 00:00:00 2001 From: Dave Grantham Date: Mon, 14 Sep 2026 13:27:55 -0600 Subject: [PATCH 2/3] docs Signed-off-by: Dave Grantham --- CHANGELOG.md | 6 ++++++ Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9298447..e3d436d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +## [1.5.0] - 2026-09-14 + +### Deprecated + +- All 36 Classic McEliece codec variants (`mceliece*` and `x25519-mceliece348864`) now carry `#[deprecated]` attributes. Key-recovery attacks now solve the TII McEliece challenges; see [tii-solved](https://github.com/mjosaarinen/tii-solved) for the recovered keys. Uses of these variants emit compiler warnings. The variants remain compiled, matchable, and decodable so stored multicodec-tagged data keeps working. + ## [1.4.0] - 2026-09-03 ### Added diff --git a/Cargo.toml b/Cargo.toml index 73eb9df..f62d105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-codec" -version = "1.4.0" +version = "1.5.0" edition = "2024" rust-version = "1.85" authors = ["Benjamin Kampmann ", "Dave Grantham "] From dc18173a838d656ca80d5779de3360e221ff9390 Mon Sep 17 00:00:00 2001 From: Dave Grantham Date: Mon, 14 Sep 2026 13:34:20 -0600 Subject: [PATCH 3/3] dep update Signed-off-by: Dave Grantham --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f62d105..d5c1b3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ name = "uvi" path = "examples/uvi.rs" [build-dependencies] -convert_case = "0.6" +convert_case = "0.12" csv = "1.3" serde = { version = "1.0", features = ["serde_derive"] } serde_derive = "1.0"