multithreaded: upgrade sha2 to 0.11 and hmac to 0.13
The two move together — hmac 0.12 is pinned to digest 0.10. The only API
break is new_from_slice, which moved from Mac to KeyInit, so KeyInit now
has to be in scope at both call sites.
The internal request signature is a cross-repo contract (the MNW server
signs, this verifies), and every existing test only checks it agrees
with itself. Pin it against an independent HMAC-SHA256 of the documented
message layout so a hasher swap has to reproduce a fixed string.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 files changed,
+19 insertions,
-6 deletions
| 2243 |
2243 |
|
"dotenvy",
|
| 2244 |
2244 |
|
"governor",
|
| 2245 |
2245 |
|
"hex",
|
| 2246 |
|
- |
"hmac 0.12.1",
|
|
2246 |
+ |
"hmac 0.13.0",
|
| 2247 |
2247 |
|
"http-body-util",
|
| 2248 |
2248 |
|
"mt-core",
|
| 2249 |
2249 |
|
"mt-db",
|
| 2255 |
2255 |
|
"s3-storage",
|
| 2256 |
2256 |
|
"serde",
|
| 2257 |
2257 |
|
"serde_json",
|
| 2258 |
|
- |
"sha2 0.10.9",
|
|
2258 |
+ |
"sha2 0.11.0",
|
| 2259 |
2259 |
|
"sqlx",
|
| 2260 |
2260 |
|
"tagtree",
|
| 2261 |
2261 |
|
"time",
|
| 33 |
33 |
|
# Pinned to the exact major reqwest resolves so the SSRF pre-check parses the
|
| 34 |
34 |
|
# host with the same parser reqwest connects through (link_preview::validate_url).
|
| 35 |
35 |
|
url = "2"
|
| 36 |
|
- |
sha2 = "0.10"
|
| 37 |
|
- |
hmac = "0.12"
|
|
36 |
+ |
sha2 = "0.11"
|
|
37 |
+ |
hmac = "0.13"
|
| 38 |
38 |
|
base64 = "0.22"
|
| 39 |
39 |
|
rand = "0.10"
|
| 40 |
40 |
|
|
| 22 |
22 |
|
http::StatusCode,
|
| 23 |
23 |
|
response::{IntoResponse, Response},
|
| 24 |
24 |
|
};
|
| 25 |
|
- |
use hmac::{Hmac, Mac};
|
|
25 |
+ |
use hmac::{Hmac, KeyInit, Mac};
|
| 26 |
26 |
|
use sha2::Sha256;
|
| 27 |
27 |
|
|
| 28 |
28 |
|
use crate::AppState;
|
| 267 |
267 |
|
}
|
| 268 |
268 |
|
|
| 269 |
269 |
|
#[test]
|
|
270 |
+ |
fn signature_matches_the_reference_hmac() {
|
|
271 |
+ |
// The signer lives in the MNW server and the verifier lives here, so
|
|
272 |
+ |
// the exact bytes are a cross-repo contract that no test in either
|
|
273 |
+ |
// repo can catch by agreeing with itself. Pinned against an
|
|
274 |
+ |
// independent HMAC-SHA256 over the documented message layout:
|
|
275 |
+ |
// key "secret", message "100\nPOST\n/x\nn\nbody".
|
|
276 |
+ |
assert_eq!(
|
|
277 |
+ |
v2("secret", "100", "POST", "/x", "n", b"body"),
|
|
278 |
+ |
"0e97f90cb4e4ca7aaa5499e67a22fb5b7ad45ad3cc966f37d225f39da2728098"
|
|
279 |
+ |
);
|
|
280 |
+ |
}
|
|
281 |
+ |
|
|
282 |
+ |
#[test]
|
| 270 |
283 |
|
fn signature_changes_with_secret() {
|
| 271 |
284 |
|
// Pins that the secret feeds into the MAC key.
|
| 272 |
285 |
|
assert_ne!(
|
| 4 |
4 |
|
use axum::body::Body;
|
| 5 |
5 |
|
use axum::extract::ConnectInfo;
|
| 6 |
6 |
|
use axum::http::{Method, Request, StatusCode};
|
| 7 |
|
- |
use hmac::{Hmac, Mac};
|
|
7 |
+ |
use hmac::{Hmac, KeyInit, Mac};
|
| 8 |
8 |
|
use http_body_util::BodyExt;
|
| 9 |
9 |
|
use sha2::Sha256;
|
| 10 |
10 |
|
use sqlx::PgPool;
|