Skip to content

der: fix X.680 tag order: compare class and number first - #1790

Merged
tarcieri merged 1 commit into
RustCrypto:masterfrom
dishmaker:dishmaker/der_cmp_tags_constructed
May 4, 2025
Merged

tarcieri merged 1 commit into
RustCrypto:masterfrom
dishmaker:dishmaker/der_cmp_tags_constructed

Conversation

@dishmaker

Copy link
Copy Markdown
Contributor

Fixes #1237

Constructed bit is compared last.

@tarcieri
tarcieri merged commit 4a63b69 into RustCrypto:master May 4, 2025
@tarcieri tarcieri mentioned this pull request Feb 13, 2026
tarcieri added a commit that referenced this pull request Feb 13, 2026
## Added
- Custom error types support to the `Decode` and `DecodeValue` traits (#1055)
- `EncodingRules` enum (#1321)
- `Decode::from_ber` (#1389)
- Documentation for field-level `tag_mode` attribute (#1401)
- `Hash` implementation for `AlgorithmIdentifier` (#1414)
- `SequenceRef::as_bytes` and `AsRef<[u8]>` impl (#1454)
- `Reader::peek_into` (#1478)
- `GeneralString` variant to `Tag` (#1512)
- Conversions from `OctetString(Ref)` to `Vec`/`Bytes` (#1540)
- Custom error types in derive macros (#1560)
- Support for tags beyond 30 (#1651)
- Const `::new` to `Length`, `BytesRef`, and `AnyRef` (#1713)
- Const `GeneralizedTime::from_date_time` (#1718)
- `Decode::from_der_partial` (#1725)
- Conversions between `BitStringRef`/`OctetStringRef` and `[u8; N]` (#1731)
- Add class bits consts for Application and Private tag support (#1721)
- conversions between `heapless:Vec<u8>` and `OctetStringRef` (#1735)
- `IsConstructed` trait, impl'ed on any `FixedTag` (#1744)
- Implement `Hash` for `SetOf` (#1764)
- Implement `Uint`/`Int` conversions from native types (#1762)
- Support for `APPLICATION`, `CONTEXT-SPECIFIC` and `PRIVATE` tags (#1819, #1825, #1944)
- Support `Cow<[u8]>` in `derive(Sequence)` (#1850)
- `diagnostic::on_unimplemented` attributes (#1876)
- `Reader::read_value`, auto-nest `DecodeValue` (#1877, #1895, #1897, #1901)
- Indefinite length support for BER (#1884, #1885, #1894, #1900, #1902, #1910)
- Constructed OctetString support (#1899, #1922)
- string conversions, predicate methods for EncodingRules (#1903, #1953)
- `Any::header` (#1935)
- `Tag::RelativeOid` (#1942)
- `ber` feature (#1948, #1950)
- Hash derive for `StringOwned` and `Ia5String` (#1973)
- Implement `DecodeValue/EncodeValue/Tagged` for `Cow` (#2093)
- Add doc examples for `EncodeValue`, `Encode`, `DecodeValue`, `Decode`, `Error`, `ErrorKind`, `Tagged`, `FixedTag`,
  `IsConstructed`, `Tag`, `Length`, `Header` (#2075, #2071, #2070, #2064, #2058, #2052, #2053, #2051)
- `SequenceRef::new` (#2224)

## Changed
- Return `Tag::Integer.length_error()` on empty ints (#1400)
- Allow all blanket impls on `?Sized` types (#1451)
- Refactor `Tag::peek` (#1479)
- Refactor `Header::peek` (#1480)
- Use `core::error::Error` (#1553)
- Use 2024 edition, bump MSRV to 1.85 (#1670)
- Bump `const-oid` to v0.10 (#1676)
- Reject zero lengths reads (#1716)
- Deprecate `TagNumber::new` (#1727)
- Use strict context-specific skipping condition (equal tag numbers only) (#1740)
- Const `Any::to_ref`, `BytesOwned::to_ref` (#1797)
- Return `ErrorKind::Noncanonical` in `EXPLICIT` when primitive (#1818)
- Use `read_nested` to check length of `IMPLICIT` types (#1739)
- Simplify `From<&UintRef<'a>>` for `Uint` (#1840)
- Make `ObjectIdentifier<MAX_SIZE>` impls generic (#1851)
- Extract `reader::position::Position` (#1880)
- Make `Reader` cloneable (#1883)
- Simplify `Header::peek` and `Tag::peek` (#1886)
- Improve constructed bit handling (#1919)
- Use fat pointer in `OctetStringRef`, consolidate bytes/string modules, improve internal ref types
  (#1920, #1921, #1998, #2040)
- Change constructor `Header::new`, add `Header::with_length`, tests for constructed octet string (#1931, #1930)
- Simplify `der_cmp` for `Length` (#1997)
- Rename variable encoder -> writer and improve example (#2078)
- Have `PemReader` decode to `Cow::Owned` (#2094)
- Only sort `SET OF` types with `EncodingRules::Der` (#2219)
- `SetOf` and `SequenceOf` now require `heapless` feature (#2220, #2229)

## Fixed
- Append in `Encode::encode_to_vec` (#1760)
- Derive optional OCTET/BIT STRING on `Option<&[u8]>` (#1737)
- X.680 tag order: compare class and number first (#1790)
- BMPString compatibility in derive macros (#1793)
- `Tag::peek_optional` for 6-byte and 7+ byte tags (#1804)
- `Header::peek` for 11-byte tag-lengths (#1828)
- Panic in `value_cmp`: add `Iterator::size_hint` (#1830)
- Error position tracking improvements (#1889, #2080, #2079)
- Bound `Decode(Value)::Error` on `core::error::Error` (#2137)
- Have `SetOf(Vec)::insert` check for duplicates (#2217)

## Removed
- `TagNumber::N0..N30` consts (#1724)
- 256MiB limit on `Length` (#1726)
- Generic `<T>` from `Reader::finish` (#1833)
- Deprecated `SetOf(Vec)::add` methods (#2232)
- `SequenceRef` lifetime (#2224)
tarcieri pushed a commit that referenced this pull request Oct 5, 2026
X.690 11.6 orders the components of a DER `SET OF` by their encodings
compared as octet strings. `DerOrd for Tag` compared class, then tag
number, then the constructed bit (#1790). That differs from octet order
whenever two components differ in the constructed bit (0x20 in the first
identifier octet), e.g. `PrintableString` (0x13) sorts after `SEQUENCE`
(0x30) because 19 > 16.

As a result `SetOfVec` encodes such sets in non-DER order, and `SetOfRef`
(which checks the order) rejects the correctly ordered encoding:

    SET OF { PrintableString "a", SEQUENCE {} }
    X.690 / OpenSSL / rust-asn1:  3105 130161 3000
    der 0.8:                      3105 3000 130161

`openssl asn1parse -genconf` produces the first encoding, and pyca's
rust-asn1 rejects the second with `InvalidSetOrdering`.

Compare the encoded identifier octets instead. `tag_order` assertions that
encoded the old order are updated, and new tests cover encode and decode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

der: tag ordering doesn't follow X.680

2 participants