encode arbitrary-precision integers in declarative asn1#15008
Conversation
alex
left a comment
There was a problem hiding this comment.
Please take a look at the CI results as well.
Thank you!
| }); | ||
| } | ||
|
|
||
| #[test] |
There was a problem hiding this comment.
We don't need to add rust tests (except when that's the only way to test something) -- python tests only are fine.
| Type::PyInt() => { | ||
| let val: i64 = value.extract()?; | ||
| let int_value = value.cast::<pyo3::types::PyInt>()?; | ||
| let bytes = crate::asn1::py_int_to_der_bytes(py, int_value.clone())?; |
There was a problem hiding this comment.
| let bytes = crate::asn1::py_int_to_der_bytes(py, int_value.clone())?; | |
| let bytes = crate::asn1::py_int_to_der_bytes(py, int_value)?; |
there's no need to clone since this is the only user of this value.
| let val = asn1::BigInt::new(&bytes).ok_or_else(|| { | ||
| CryptographyError::Py(pyo3::exceptions::PyValueError::new_err( | ||
| "invalid value for INTEGER", | ||
| )) | ||
| })?; |
There was a problem hiding this comment.
This or-else should be unreachable -- we should never be computing an invalid encoding. Therefore it should be an unwrap()
| .extract::<usize>()?; | ||
| // One extra octet leaves room for the sign bit and yields the minimal | ||
| // DER length once the high bit is accounted for. | ||
| let length = bit_length / 8 + 1; |
There was a problem hiding this comment.
I need to think a bit harder to ensure this is correct, but one note to self: a part of this correctness is that if the high bit is set in hte value, then bit_length becomes divisible by 8, otherwise its no (and / 8 rounds down)
the declarative asn1 decoder reads INTEGER fields as arbitrary-precision values, but the encoder narrows them to an i64, so an integer outside the signed 64-bit range that round-trips through decode_der cannot be re-encoded and instead raises OverflowError. this trips up otherwise valid structures whose integers exceed 64 bits, like RSA moduli or large serial numbers. i've changed the INTEGER arm to emit minimal two's-complement bytes through a BigInt, matching what the decoder already accepts.