Skip to content

reject non-zero unused bits in public key bit strings#15064

Open
dxbjavid wants to merge 1 commit into
pyca:mainfrom
dxbjavid:pubkey-bitstring-unused-bits
Open

reject non-zero unused bits in public key bit strings#15064
dxbjavid wants to merge 1 commit into
pyca:mainfrom
dxbjavid:pubkey-bitstring-unused-bits

Conversation

@dxbjavid

Copy link
Copy Markdown
Contributor

load_der_public_key and the EC private key loader read the subjectPublicKey and EC publicKey BIT STRINGs with as_bytes() but never look at the unused-bits count, so DER that declares a non-zero number of unused bits in those octet-aligned key bit strings is accepted even though it is malformed. parse_spki_for_data already rejects exactly this for the same field, so the two paths disagree on what a valid public key encoding is. This adds the same padding_bits check to both loaders, with regression tests that craft an Ed25519 SPKI and an EC private key carrying a bogus unused-bits count.

@alex

alex commented Jun 18, 2026

Copy link
Copy Markdown
Member

Is there some spec that dictates this behavior? Do other libraries enforce this?

@dxbjavid

Copy link
Copy Markdown
Contributor Author

there isn't a single clause that says "reject a non-zero count" outright. it falls out of the per-algorithm content definitions: for the key types we load the subjectPublicKey always holds a whole number of octets, so the bit length is a multiple of eight and the unused-bits count can only be zero. for the edwards/montgomery keys rfc 8410 carries the raw key bytes, ec carries the SEC1 point octet string (rfc 5480), and the rsa case wraps a der-encoded RSAPublicKey. a non-zero count contradicts that, and x.690 11.2 also requires the trailing unused bits themselves be zero under der.

honestly the strongest argument is internal consistency rather than a survey of other libraries. parse_spki_for_data already rejects exactly this for the same field, so right now load_der_public_key and that helper disagree on whether the same bytes are a valid public key, and the ec private key loader reads the point bit string the same loose way. i haven't done a broad survey across other libraries, so if you'd rather not tighten this at parse time i'm happy to drop it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants