diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a11747..57532969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +* Breaking: Upgraded the RustCrypto elliptic-curve stack to clear [RUSTSEC-2026-0387](https://rustsec.org/advisories/RUSTSEC-2026-0387) (non-constant-time arithmetic in `crypto-bigint` < 0.7.6, which the 0.13 stack pins at 0.5). `k256` and `p256` go to 0.14, `elliptic-curve` to 0.14, `ecdsa` to 0.17, `pkcs8` to 0.11, `sec1` to 0.8 and `sha2` to 0.11. Their types show up in the public API, for example `Secp256k1Identity::from_private_key` and `PemError::ErrorStack`, so downstream crates that name them have to move to the same versions. + ## [0.49.3] - 2026-10-22 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index d117c2f5..8005fd5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "base16ct" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64" @@ -340,6 +340,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -524,6 +533,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -574,6 +589,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "convert_case" version = "0.6.0" @@ -599,6 +620,12 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -649,12 +676,16 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" -version = "0.5.5" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "9c035cb64cba03dad2fb921f3e218785e8cf9a41790da5eb3a1400f62fa2be11" dependencies = [ - "generic-array", - "rand_core 0.6.4", + "cpubits", + "ctutils", + "getrandom 0.4.2", + "hybrid-array", + "num-traits", + "rand_core 0.10.0", "subtle", "zeroize", ] @@ -669,6 +700,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "getrandom 0.4.2", + "hybrid-array", + "rand_core 0.10.0", +] + +[[package]] +name = "ctutils" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3e9d21d39e6f39ff46e03d5b621424f88ee23d8a1672c6bfc9ccc7f2da4f6a" +dependencies = [ + "cmov", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -680,7 +732,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "group", + "group 0.13.0", "rand_core 0.6.4", "rustc_version", "subtle", @@ -758,8 +810,19 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", - "pem-rfc7468", + "const-oid 0.9.6", + "pem-rfc7468 0.7.0", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a996a108feb8b427a6e12fcf6af4aa83409b79d72c15337d7741368131ee004" +dependencies = [ + "const-oid 0.10.2", + "pem-rfc7468 1.0.0", "zeroize", ] @@ -819,11 +882,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", - "crypto-common", + "crypto-common 0.1.6", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -870,16 +944,17 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ecdsa" -version = "0.16.9" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +checksum = "c0681a4fc24c767085329728d8dfba959af91228aa4610cca4f8ce317ba46ae0" dependencies = [ - "der", - "digest 0.10.7", + "der 0.8.3", + "digest 0.11.3", "elliptic-curve", "rfc6979", - "signature", - "spki", + "signature 3.0.0", + "spki 0.8.1", + "zeroize", ] [[package]] @@ -888,8 +963,8 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", ] [[package]] @@ -919,7 +994,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "sha2 0.10.9", - "signature", + "signature 2.2.0", "subtle", "zeroize", ] @@ -932,19 +1007,20 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" -version = "0.13.8" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "900f37e7e18d74a2347389af6cd69e3a30d5cc9e697f40004865679aa75e9c7c" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pem-rfc7468", - "pkcs8", - "rand_core 0.6.4", + "crypto-common 0.2.2", + "digest 0.11.3", + "ff 0.14.0", + "group 0.14.0", + "hybrid-array", + "pem-rfc7468 1.0.0", + "pkcs8 0.11.0", + "rand_core 0.10.0", "sec1", "subtle", "zeroize", @@ -1027,6 +1103,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" +dependencies = [ + "rand_core 0.10.0", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -1151,7 +1237,6 @@ checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -1201,11 +1286,22 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", + "ff 0.13.1", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "group" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" +dependencies = [ + "ff 0.14.0", + "rand_core 0.10.0", + "subtle", +] + [[package]] name = "h2" version = "0.4.13" @@ -1291,7 +1387,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac", + "hmac 0.12.1", ] [[package]] @@ -1303,6 +1399,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "http" version = "1.4.0" @@ -1354,6 +1459,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" +[[package]] +name = "hybrid-array" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +dependencies = [ + "subtle", + "typenum", + "zeroize", +] + [[package]] name = "hyper" version = "1.8.1" @@ -1453,7 +1569,7 @@ dependencies = [ "mockito", "p256", "pem", - "pkcs8", + "pkcs8 0.11.0", "rand 0.10.1", "rangemap", "ref-tests", @@ -1465,7 +1581,7 @@ dependencies = [ "serde_cbor", "serde_json", "serde_repr", - "sha2 0.10.9", + "sha2 0.11.1", "stop-token", "thiserror 2.0.18", "time", @@ -1516,7 +1632,7 @@ dependencies = [ "hex", "ic-agent", "pkcs11", - "sha2 0.10.9", + "sha2 0.11.1", "simple_asn1", "thiserror 2.0.18", ] @@ -1603,7 +1719,7 @@ dependencies = [ "serde_cbor", "serde_json", "serde_repr", - "sha2 0.10.9", + "sha2 0.11.1", "thiserror 2.0.18", ] @@ -1622,7 +1738,7 @@ dependencies = [ "semver", "serde", "serde_bytes", - "sha2 0.10.9", + "sha2 0.11.1", "strum 0.28.0", "strum_macros 0.28.0", "thiserror 2.0.18", @@ -1674,8 +1790,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e828f9e804ccefe4b9b15b2195f474c60fd4f95ccd14fcb554eb6d7dfafde3" dependencies = [ "digest 0.10.7", - "ff", - "group", + "ff 0.13.1", + "group 0.13.0", "pairing", "rand_core 0.6.4", "subtle", @@ -1810,7 +1926,7 @@ dependencies = [ "serde", "serde_bytes", "serde_cbor", - "sha2 0.10.9", + "sha2 0.11.1", "time", ] @@ -1971,16 +2087,17 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.4" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +checksum = "93f50113171a713f4a4231ef82eb26703607139b35dcb56241f0ceab2ae1f7d8" dependencies = [ - "cfg-if", + "cpubits", "ecdsa", "elliptic-curve", - "once_cell", - "sha2 0.10.9", - "signature", + "primeorder", + "sha2 0.11.1", + "signature 3.0.0", + "wnaf", ] [[package]] @@ -2355,14 +2472,15 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "p256" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "d2c9239b2dbc807adbbe147e8cf72ea7450c3a0aabe62cb8e75ff4ec22e1f72a" dependencies = [ "ecdsa", "elliptic-curve", + "primefield", "primeorder", - "sha2 0.10.9", + "sha2 0.11.1", ] [[package]] @@ -2371,7 +2489,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" dependencies = [ - "group", + "group 0.13.0", ] [[package]] @@ -2428,6 +2546,15 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2530,8 +2657,18 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.3", + "spki 0.8.1", ] [[package]] @@ -2650,13 +2787,31 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "primefield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4" +dependencies = [ + "crypto-bigint", + "crypto-common 0.2.2", + "ff 0.14.0", + "rand_core 0.10.0", + "subtle", + "zeroize", +] + [[package]] name = "primeorder" -version = "0.13.6" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "5c9f42978c78a00e3d68f69fc03e57a234debae69da4020a4fb588fcdcd07b06" dependencies = [ "elliptic-curve", + "once_cell", + "primefield", + "serdect", + "wnaf", ] [[package]] @@ -2885,7 +3040,7 @@ dependencies = [ "serde", "serde_bytes", "serde_cbor", - "sha2 0.10.9", + "sha2 0.11.1", "tokio", ] @@ -3008,12 +3163,12 @@ dependencies = [ [[package]] name = "rfc6979" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "b4a459cddafb3fe76b31fd8f1108007566c40301feb64dc7b54656eb7388172b" dependencies = [ - "hmac", - "subtle", + "crypto-bigint", + "hmac 0.13.0", ] [[package]] @@ -3196,14 +3351,14 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sec1" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" dependencies = [ "base16ct", - "der", - "generic-array", - "pkcs8", + "ctutils", + "der 0.8.3", + "hybrid-array", "subtle", "zeroize", ] @@ -3347,6 +3502,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3371,6 +3536,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3406,6 +3582,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest 0.11.3", + "rand_core 0.10.0", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -3477,7 +3663,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" +dependencies = [ + "base64ct", + "der 0.8.3", ] [[package]] @@ -4013,9 +4209,9 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -4705,6 +4901,18 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wnaf" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795ca18b3fdb5e62bf982199278341ddcf7ebf7d32e25e212ad05d496e95f6fa" +dependencies = [ + "ff 0.14.0", + "group 0.14.0", + "hybrid-array", + "primefield", +] + [[package]] name = "writeable" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index 6436eedd..4859fad8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,9 +59,9 @@ candid = "0.10.10" candid_parser = "0.3.0" clap = { version = "4.5.21", features = ["derive", "cargo", "color"] } # icx, icx-cert der = "0.8.0" -ecdsa = "0.16" +ecdsa = "0.17" ed25519-consensus = "2.1.0" -elliptic-curve = "0.13" +elliptic-curve = "0.14" futures-util = "0.3.31" getrandom = "0.4" # getrandom 0.2 is pulled in only transitively (via rand_core 0.6, used by the @@ -80,14 +80,14 @@ ic-management-canister-types = "0.8.0" ic_principal = { version = "0.1.2", features = ["rangemap"] } ic-verify-bls-signature = "0.6" js-sys = "0.3" -k256 = "0.13.4" +k256 = "0.14" leb128 = "0.2.5" mockito = "1.0.2" once_cell = "1.10.0" -p256 = "0.13.2" +p256 = "0.14" pem = "3" pkcs11 = "0.5.0" -pkcs8 = "0.10.2" +pkcs8 = "0.11" # Used by integration tests (ref-tests, ic-utils-bindgen-tests) only. The git # rev is pinned to the same IC commit as the pocket-ic server binary downloaded # by scripts/download_reftest_assets.sh, so the client lib and server stay in @@ -100,14 +100,14 @@ rand = "0.10.1" rangemap = "1.7" reqwest = { version = "0.13.2", default-features = false } ring = "0.17" -sec1 = "0.7.2" +sec1 = "0.8" semver = "1.0.7" serde = "1.0.215" serde_bytes = "0.11.15" serde_cbor = "0.11.2" serde_json = "1.0.133" serde_repr = "0.1.19" -sha2 = "0.10.8" +sha2 = "0.11" simple_asn1 = "0.6.0" stop-token = "0.7" strum = "0.28.0" diff --git a/ic-agent/src/identity/basic.rs b/ic-agent/src/identity/basic.rs index 64667cdf..4e2df718 100644 --- a/ic-agent/src/identity/basic.rs +++ b/ic-agent/src/identity/basic.rs @@ -36,7 +36,7 @@ impl BasicIdentity { #[cfg(feature = "pem")] pub fn from_pem>(pem_contents: B) -> Result { use pkcs8::der::{asn1::OctetString, Decode, ErrorKind, SliceReader, Tag, TagNumber}; - use pkcs8::PrivateKeyInfo; + use pkcs8::PrivateKeyInfoRef as PrivateKeyInfo; let bytes = pem_contents.as_ref(); let pem = pem::parse(bytes)?; @@ -49,7 +49,7 @@ impl BasicIdentity { == (ErrorKind::Noncanonical { tag: Tag::ContextSpecific { constructed: true, - number: TagNumber::new(1), + number: TagNumber(1), }, }) { @@ -68,7 +68,7 @@ impl BasicIdentity { } } }; - let decoded_key = OctetString::from_der(pki.private_key)?; // ed25519 uses an octet string within another octet string + let decoded_key = OctetString::from_der(pki.private_key.as_bytes())?; // ed25519 uses an octet string within another octet string let key_len = decoded_key.as_bytes().len(); if key_len != 32 { Err(PemError::InvalidPrivateKey(format!( diff --git a/ic-agent/src/identity/delegated.rs b/ic-agent/src/identity/delegated.rs index 1a44e90c..bf305cce 100644 --- a/ic-agent/src/identity/delegated.rs +++ b/ic-agent/src/identity/delegated.rs @@ -182,7 +182,7 @@ fn verify_delegation_link( if curve == Secp256k1::OID { let pt = EncodedPoint::from_bytes(spki.subject_public_key.raw_bytes()) .map_err(|_| DelegationError::Parse)?; - let vk = k256::ecdsa::VerifyingKey::from_encoded_point(&pt) + let vk = k256::ecdsa::VerifyingKey::from_sec1_point(&pt) .map_err(|_| DelegationError::Parse)?; let sig = k256::ecdsa::Signature::try_from(signature).map_err(|_| DelegationError::Parse)?; @@ -194,7 +194,7 @@ fn verify_delegation_link( } else if curve == NistP256::OID { let pt = EncodedPoint::from_bytes(spki.subject_public_key.raw_bytes()) .map_err(|_| DelegationError::Parse)?; - let vk = p256::ecdsa::VerifyingKey::from_encoded_point(&pt) + let vk = p256::ecdsa::VerifyingKey::from_sec1_point(&pt) .map_err(|_| DelegationError::Parse)?; let sig = p256::ecdsa::Signature::try_from(signature).map_err(|_| DelegationError::Parse)?; diff --git a/ic-agent/src/identity/mod.rs b/ic-agent/src/identity/mod.rs index 5e14a835..8ab8acf6 100644 --- a/ic-agent/src/identity/mod.rs +++ b/ic-agent/src/identity/mod.rs @@ -147,7 +147,7 @@ fn parse_ec_pkcs8_key_bytes( ) -> Result, error::PemError> { use pkcs8::{ der::{Decode, Encode}, - PrivateKeyInfo, + PrivateKeyInfoRef as PrivateKeyInfo, }; let mut truncated: Vec; @@ -177,12 +177,12 @@ fn parse_ec_pkcs8_key_bytes( let curve_oid = pki .algorithm .parameters_oid() - .map_err(|_| pkcs8::Error::KeyMalformed)?; + .map_err(|_| pkcs8::Error::KeyMalformed(pkcs8::KeyError::Invalid))?; if curve_oid != expected_curve { return Err(error::PemError::UnsupportedKeyCurve( curve_name.to_string(), curve_oid.to_der().unwrap_or_default(), )); } - Ok(pki.private_key.to_vec()) + Ok(pki.private_key.as_bytes().to_vec()) } diff --git a/ic-agent/src/identity/prime256v1.rs b/ic-agent/src/identity/prime256v1.rs index d30512fe..c40e4ff3 100644 --- a/ic-agent/src/identity/prime256v1.rs +++ b/ic-agent/src/identity/prime256v1.rs @@ -35,7 +35,7 @@ impl Prime256v1Identity { /// Accepts keys in SEC1 ("EC PRIVATE KEY") or PKCS#8 ("PRIVATE KEY") format. #[cfg(feature = "pem")] pub fn from_pem>(pem_contents: B) -> Result { - use pkcs8::{AssociatedOid, PrivateKeyInfo}; + use pkcs8::{AssociatedOid, PrivateKeyInfoRef as PrivateKeyInfo}; use sec1::{pem::PemLabel, EcPrivateKey}; const EC_PARAMETERS: &str = "EC PARAMETERS"; @@ -54,7 +54,7 @@ impl Prime256v1Identity { if pem.tag() == EcPrivateKey::PEM_LABEL { // SEC1 "EC PRIVATE KEY" format let private_key = SecretKey::from_sec1_der(pem.contents()) - .map_err(|_| pkcs8::Error::KeyMalformed)?; + .map_err(|_| pkcs8::Error::KeyMalformed(pkcs8::KeyError::Invalid))?; return Ok(Self::from_private_key(private_key)); } @@ -65,8 +65,8 @@ impl Prime256v1Identity { p256::NistP256::OID, "prime256v1", )?; - let private_key = - SecretKey::from_sec1_der(&key_bytes).map_err(|_| pkcs8::Error::KeyMalformed)?; + let private_key = SecretKey::from_sec1_der(&key_bytes) + .map_err(|_| pkcs8::Error::KeyMalformed(pkcs8::KeyError::Invalid))?; return Ok(Self::from_private_key(private_key)); } } diff --git a/ic-agent/src/identity/secp256k1.rs b/ic-agent/src/identity/secp256k1.rs index 215c13c3..944b2ce1 100644 --- a/ic-agent/src/identity/secp256k1.rs +++ b/ic-agent/src/identity/secp256k1.rs @@ -35,7 +35,7 @@ impl Secp256k1Identity { /// Accepts keys in SEC1 ("EC PRIVATE KEY") or PKCS#8 ("PRIVATE KEY") format. #[cfg(feature = "pem")] pub fn from_pem>(pem_contents: B) -> Result { - use pkcs8::{AssociatedOid, PrivateKeyInfo}; + use pkcs8::{AssociatedOid, PrivateKeyInfoRef as PrivateKeyInfo}; use sec1::{pem::PemLabel, EcPrivateKey}; const EC_PARAMETERS: &str = "EC PARAMETERS"; @@ -54,7 +54,7 @@ impl Secp256k1Identity { if pem.tag() == EcPrivateKey::PEM_LABEL { // SEC1 "EC PRIVATE KEY" format let private_key = SecretKey::from_sec1_der(pem.contents()) - .map_err(|_| pkcs8::Error::KeyMalformed)?; + .map_err(|_| pkcs8::Error::KeyMalformed(pkcs8::KeyError::Invalid))?; return Ok(Self::from_private_key(private_key)); } @@ -65,8 +65,8 @@ impl Secp256k1Identity { k256::Secp256k1::OID, "secp256k1", )?; - let private_key = - SecretKey::from_sec1_der(&key_bytes).map_err(|_| pkcs8::Error::KeyMalformed)?; + let private_key = SecretKey::from_sec1_der(&key_bytes) + .map_err(|_| pkcs8::Error::KeyMalformed(pkcs8::KeyError::Invalid))?; return Ok(Self::from_private_key(private_key)); } } diff --git a/ic-transport-types/src/request_id.rs b/ic-transport-types/src/request_id.rs index 446f5d41..5420a48c 100644 --- a/ic-transport-types/src/request_id.rs +++ b/ic-transport-types/src/request_id.rs @@ -15,8 +15,7 @@ use serde::{ }; use sha2::{Digest, Sha256}; use std::{ - fmt::{self, Display, Formatter}, - io::Write, + fmt::{self, Display, Formatter, Write}, ops::Deref, str::FromStr, }; @@ -306,9 +305,19 @@ impl Serializer for RequestIdSerializer { } // Optimized version of serialize_str for types that serialize by rendering themselves to strings. fn collect_str(self, value: &T) -> Result { - let mut hasher = Sha256::new(); + let mut hasher = HashWriter(Sha256::new()); write!(hasher, "{value}").map_err(|e| RequestIdError::CustomSerdeError(format!("{e}")))?; - Ok(Some(hasher.finalize().into())) + Ok(Some(hasher.0.finalize().into())) + } +} + +/// Feeds formatted output straight into a hasher, without an intermediate `String`. +struct HashWriter(Sha256); + +impl Write for HashWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0.update(s.as_bytes()); + Ok(()) } } @@ -932,4 +941,40 @@ mod tests { "c2b325a8f7633df8054e9bd538ac8d26dc85cba4ad542cdbfca7109e1a60cf0c" ); } + + #[test] + fn structural_equivalence_collect_str() { + // Writes its text in several fragments, so the hasher sees more than one `write_str`. + struct Fragmented; + impl Display for Fragmented { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "héllo")?; + f.write_str(", ")?; + write!(f, "wörld-{}", 6 * 7)?; + f.write_char('🦀') + } + } + impl Serialize for Fragmented { + fn serialize(&self, serializer: S) -> Result { + serializer.collect_str(self) + } + } + + #[derive(Serialize)] + struct ViaCollectStr { + x: Fragmented, + } + #[derive(Serialize)] + struct ViaStr { + x: &'static str, + } + assert_eq!( + to_request_id(&ViaCollectStr { x: Fragmented }).unwrap(), + to_request_id(&ViaStr { + x: "héllo, wörld-42🦀" + }) + .unwrap(), + "collect_str hashed identically to the equivalent str" + ); + } }