From 793122be606e2d4746f26b5f2ae256a0de41c862 Mon Sep 17 00:00:00 2001 From: Biagio Festa <15035284+BiagioFesta@users.noreply.github.com> Date: Tue, 19 Dec 2023 23:50:00 +0100 Subject: [PATCH] ensure default serial generation fits 20 bytes (#203) By default, s/n is generated taking digest of pub-key of the certificate. However, if the slice number representation is a negative number, then `write_bigint_bytes` is going to append an additional `0`-byte to ensure the positive sign. See: https://github.com/qnighy/yasna.rs/blob/b7e65f9a4c317494cce2d18ea02b3d6eaaea7985/src/writer/mod.rs#L493-L495 So it is possible the bigint encoding will take 21 bytes instead of 20. This CR sets MSB of digest to `0` to ensure encoding will take exactly 20 bytes Co-authored-by: est31 --- rcgen/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rcgen/src/lib.rs b/rcgen/src/lib.rs index d5eba9f4..cf89a9d3 100644 --- a/rcgen/src/lib.rs +++ b/rcgen/src/lib.rs @@ -937,8 +937,9 @@ impl CertificateParams { } else { let hash = digest::digest(&digest::SHA256, pub_key.raw_bytes()); // RFC 5280 specifies at most 20 bytes for a serial number - let sl = &hash.as_ref()[0..20]; - writer.next().write_bigint_bytes(sl, true); + let mut sl = hash.as_ref()[0..20].to_vec(); + sl[0] = sl[0] & 0x7f; // MSB must be 0 to ensure encoding bignum in 20 bytes + writer.next().write_bigint_bytes(&sl, true); }; // Write signature ca.params.alg.write_alg_ident(writer.next());