kca-core: fix CSR attribute DER encoding and conformant decoding

- Generated attributes are now explicitly tagged as UTF8String via
  CertificateSigningRequestBuilder.add_attribute(_tag=_ASN1Type.UTF8String),
  so values include proper DER TLV instead of raw bytes.
- The attribute decoder first attempts DER string parsing (UTF8String, PrintableString,
  IA5String, BMPString, long-form lengths), falling back to legacy raw UTF-8 decode for
  previously generated nonconformant CSRs.
- Regression tests verify DER encoding, Unicode round-tripping, supported string types,
  long values (>127 bytes), and legacy raw UTF-8 attributes.
- Mypy passes cleanly (no issues in 42 source files).
This commit is contained in:
KCA
2026-10-25 22:09:22 +00:00
parent 419a340e8d
commit 830dd64012
2 changed files with 54 additions and 18 deletions
+24 -2
View File
@@ -353,12 +353,34 @@ class RequestTest(unittest.TestCase):
subject=_name("CSR"),
private_key=key,
extension_spec=_ca_spec(),
attributes={requests.CHALLENGE_PASSWORD_OID: "secret"},
attributes={
requests.CHALLENGE_PASSWORD_OID: "secret",
requests.UNSTRUCTURED_NAME_OID: "KCA ☃",
},
)
self.assertTrue(requests.verify_csr(csr))
loaded = requests.parse_csr(requests.csr_der(csr))
self.assertEqual(requests.request_info(loaded).subject, csr.subject)
self.assertEqual(requests.attribute_values(loaded)[requests.CHALLENGE_PASSWORD_OID], "secret")
der = requests.csr_der(loaded)
self.assertIn(b"\x0c\x06secret", der)
self.assertIn(b"\x0c\x07KCA \xe2\x98\x83", der)
values = requests.attribute_values(loaded)
self.assertEqual(values[requests.CHALLENGE_PASSWORD_OID], "secret")
self.assertEqual(values[requests.UNSTRUCTURED_NAME_OID], "KCA ☃")
def test_decode_attribute_der_strings(self) -> None:
long_value = "x" * 128
cases = [
(b"\x0c\x06secret", "secret"),
(b"\x13\x04name", "name"),
(b"\x16\x0bexample.com", "example.com"),
(b"\x1e\x04\x00a\x00b", "ab"),
(b"\x0c\x81\x80" + long_value.encode("ascii"), long_value),
(b"legacy", "legacy"),
]
for encoded, expected in cases:
with self.subTest(encoded=encoded):
self.assertEqual(requests._decode_attribute_value(encoded), expected)
class CrlTest(unittest.TestCase):