pub struct Integer { /* private fields */ }Expand description
ASN.1 INTEGER with arbitrary precision
Uses SmallVec to store up to 16 bytes inline (covers i128/u128), spilling to heap only for truly large integers.
Implementations§
Source§impl Integer
impl Integer
Sourcepub fn from_bytes(bytes: &[u8]) -> Self
pub fn from_bytes(bytes: &[u8]) -> Self
Create an integer from raw big-endian two’s complement bytes.
The bytes are accepted as-is without validation. In particular:
- No minimal-encoding check is performed; a caller could pass a
non-minimal encoding (e.g. unnecessary leading
0x00bytes) that DER’s decoder would normally reject. - An empty slice is interpreted as zero (
as_i64()returnsOk(0)).
Prefer the typed constructors (from_i64, from_u64, from_i128)
unless you are re-wrapping bytes that have already been validated by
the decoder.
Sourcepub fn from_unsigned_bytes(bytes: &[u8]) -> Self
pub fn from_unsigned_bytes(bytes: &[u8]) -> Self
Create an integer from raw big-endian unsigned bytes.
Treats bytes as an unsigned (non-negative) big-endian integer:
strips leading zero bytes and prepends a 0x00 sign byte when the
most-significant bit is set, so the result is always a valid DER
two’s-complement positive integer.
Use this constructor when building certificate serial numbers from random or externally-sourced byte arrays (e.g. 20-byte / 160-bit random serials) where the caller does not want to reason about DER sign encoding.
Sourcepub fn as_bytes(&self) -> &[u8] ⓘ
pub fn as_bytes(&self) -> &[u8] ⓘ
Get the raw bytes (big-endian two’s complement)
Examples found in repository?
49fn decode_and_display(label: &str, data: &[u8]) {
50 println!("{}:", label);
51 println!(" Raw bytes: {:02X?}", data);
52
53 match Integer::from_der(data) {
54 Ok(integer) => {
55 match integer.as_i64() {
56 Ok(value) => println!(" Decoded value: {}", value),
57 Err(_) => println!(" Value too large for i64"),
58 }
59 println!(" Raw bytes: {:02X?}", integer.as_bytes());
60 }
61 Err(e) => println!(" Error: {:?}", e),
62 }
63 println!();
64}More examples
87fn parse_tbs_certificate(tbs_elements: &[Element<'_>]) {
88 // TBSCertificate has many fields, we'll show a few
89 for (i, element) in tbs_elements.iter().enumerate() {
90 match element {
91 Element::Integer(version) if i == 0 => {
92 // Version is usually [0] EXPLICIT
93 println!(" - Version/Field {}: {:?} bytes", i, version.as_bytes());
94 }
95 Element::Integer(serial) => {
96 println!(" - Serial Number: {} bytes", serial.as_bytes().len());
97 }
98 Element::Sequence(seq) => {
99 let len = seq.iter().count();
100 println!(" - SEQUENCE at position {}: {} elements", i, len);
101 }
102 _ => {}
103 }
104 }
105}Sourcepub fn as_i64(&self) -> Result<i64>
pub fn as_i64(&self) -> Result<i64>
Convert to i64 if possible
Examples found in repository?
9fn main() {
10 println!("=== ASN.1 Integer Decoding Example ===\n");
11
12 // Example 1: Small positive integer (42)
13 let data1 = vec![0x02, 0x01, 0x2A]; // INTEGER 42
14 decode_and_display("Small positive (42)", &data1);
15
16 // Example 2: Larger positive integer (1000)
17 let data2 = vec![0x02, 0x02, 0x03, 0xE8]; // INTEGER 1000
18 decode_and_display("Larger positive (1000)", &data2);
19
20 // Example 3: Negative integer (-1)
21 let data3 = vec![0x02, 0x01, 0xFF]; // INTEGER -1
22 decode_and_display("Negative (-1)", &data3);
23
24 // Example 4: Large integer (i64::MAX)
25 let data4 = vec![0x02, 0x08, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
26 decode_and_display("Large (i64::MAX)", &data4);
27
28 // Example 5: Zero
29 let data5 = vec![0x02, 0x01, 0x00]; // INTEGER 0
30 decode_and_display("Zero", &data5);
31
32 println!("\n=== Encoding Example ===\n");
33
34 // Encode an integer
35 let value = 12345;
36 println!("Encoding integer: {}", value);
37
38 let integer = Integer::from(value);
39 let encoded = integer.to_der().unwrap();
40
41 println!("Encoded bytes: {:02X?}", encoded);
42 println!("Length: {} bytes", encoded.len());
43
44 // Verify by decoding
45 let decoded = Integer::from_der(&encoded).unwrap();
46 println!("Decoded back: {}", decoded.as_i64().unwrap());
47}
48
49fn decode_and_display(label: &str, data: &[u8]) {
50 println!("{}:", label);
51 println!(" Raw bytes: {:02X?}", data);
52
53 match Integer::from_der(data) {
54 Ok(integer) => {
55 match integer.as_i64() {
56 Ok(value) => println!(" Decoded value: {}", value),
57 Err(_) => println!(" Value too large for i64"),
58 }
59 println!(" Raw bytes: {:02X?}", integer.as_bytes());
60 }
61 Err(e) => println!(" Error: {:?}", e),
62 }
63 println!();
64}More examples
68fn roundtrip_example() {
69 println!("Example 3: Roundtrip Encoding/Decoding");
70 println!("--------------------------------------");
71
72 // Create a complex structure
73 let mut seq = Sequence::new();
74 seq.push(Element::Integer(Integer::from(12345)));
75 seq.push(Element::Boolean(Boolean::new(false)));
76 seq.push(Element::Integer(Integer::from(-67890)));
77
78 println!("Original sequence:");
79 println!(" Element 1: Integer(12345)");
80 println!(" Element 2: Boolean(false)");
81 println!(" Element 3: Integer(-67890)");
82
83 // Encode
84 let encoded = seq.to_der().unwrap();
85 println!("\nEncoded: {} bytes", encoded.len());
86
87 // Decode — Sequence<'_> borrows from the input buffer, so use Decoder directly
88 let mut decoder = Decoder::new(&encoded, Encoding::Der);
89 let decoded: Sequence = decoder.decode().unwrap();
90
91 println!("\nDecoded sequence:");
92 for (i, element) in decoded.into_elements().unwrap().iter().enumerate() {
93 match element {
94 Element::Integer(int) => {
95 println!(" Element {}: Integer({})", i + 1, int.as_i64().unwrap())
96 }
97 Element::Boolean(b) => println!(" Element {}: Boolean({})", i + 1, b.value()),
98 _ => println!(" Element {}: {:?}", i + 1, element),
99 }
100 }
101
102 println!("\nRoundtrip successful!");
103 println!();
104}11fn main() {
12 use std::str::FromStr;
13 use synta::{
14 BitString, FromDer, Integer, ObjectIdentifier, OctetString, PrintableString, ToDer, UtcTime,
15 };
16 use synta_derive::{Asn1Choice, Asn1Sequence};
17
18 println!("=== Derive Macro Usage Example ===\n");
19
20 // Define ASN.1 structures using derive macros
21
22 /// AlgorithmIdentifier ::= SEQUENCE {
23 /// algorithm OBJECT IDENTIFIER,
24 /// parameters ANY (optional)
25 /// }
26 #[derive(Asn1Sequence, Debug, Clone)]
27 struct AlgorithmIdentifier {
28 algorithm: ObjectIdentifier,
29 parameters: Option<OctetString>,
30 }
31
32 /// Validity ::= SEQUENCE {
33 /// not_before Time,
34 /// not_after Time
35 /// }
36 #[derive(Asn1Sequence, Debug, Clone)]
37 struct Validity {
38 not_before: UtcTime,
39 not_after: UtcTime,
40 }
41
42 /// Name ::= SEQUENCE {
43 /// common_name PrintableString
44 /// }
45 /// (Simplified for this example)
46 #[derive(Asn1Sequence, Debug, Clone)]
47 struct Name {
48 common_name: PrintableString,
49 }
50
51 /// TBSCertificate ::= SEQUENCE {
52 /// version [0] EXPLICIT INTEGER OPTIONAL,
53 /// serial_number INTEGER,
54 /// signature AlgorithmIdentifier,
55 /// issuer Name,
56 /// validity Validity,
57 /// subject Name
58 /// }
59 #[derive(Asn1Sequence, Debug, Clone)]
60 struct TBSCertificate {
61 #[asn1(tag(0, explicit))]
62 version: Option<Integer>,
63 serial_number: Integer,
64 signature: AlgorithmIdentifier,
65 issuer: Name,
66 validity: Validity,
67 subject: Name,
68 }
69
70 /// Certificate ::= SEQUENCE {
71 /// tbs_certificate TBSCertificate,
72 /// signature_algorithm AlgorithmIdentifier,
73 /// signature_value BIT STRING
74 /// }
75 #[derive(Asn1Sequence, Debug, Clone)]
76 struct Certificate {
77 tbs_certificate: TBSCertificate,
78 signature_algorithm: AlgorithmIdentifier,
79 signature_value: BitString,
80 }
81
82 /// Time ::= CHOICE {
83 /// utc_time UTCTime,
84 /// generalized_time GeneralizedTime
85 /// }
86 /// Dispatch uses each variant type's Tagged::tag() — no tag attribute needed.
87 #[derive(Asn1Choice, Debug, Clone)]
88 enum Time {
89 Utc(UtcTime),
90 // A second variant (e.g. Generalized(GeneralizedTime)) would be
91 // disambiguated automatically via GeneralizedTime's Tagged::tag().
92 }
93
94 println!("1. Creating Certificate Structure\n");
95
96 // Create a certificate using our derived types
97 let alg_id = AlgorithmIdentifier {
98 algorithm: ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(), // SHA-256 with RSA
99 parameters: None,
100 };
101
102 let validity = Validity {
103 not_before: UtcTime::new(2024, 1, 1, 0, 0, 0).unwrap(),
104 not_after: UtcTime::new(2025, 1, 1, 0, 0, 0).unwrap(),
105 };
106
107 let issuer = Name {
108 common_name: PrintableString::new("Example CA".to_string()).unwrap(),
109 };
110
111 let subject = Name {
112 common_name: PrintableString::new("example.com".to_string()).unwrap(),
113 };
114
115 let tbs = TBSCertificate {
116 version: Some(Integer::from(2)), // v3
117 serial_number: Integer::from(123456),
118 signature: alg_id.clone(),
119 issuer: issuer.clone(),
120 validity,
121 subject,
122 };
123
124 let cert = Certificate {
125 tbs_certificate: tbs,
126 signature_algorithm: alg_id,
127 signature_value: BitString::new(vec![0xDE, 0xAD, 0xBE, 0xEF], 0).unwrap(),
128 };
129
130 println!("Created certificate with:");
131 println!(" - Version: v3");
132 println!(" - Serial: 123456");
133 println!(" - Algorithm: SHA-256 with RSA (1.2.840.113549.1.1.11)");
134 println!(" - Issuer: Example CA");
135 println!(" - Subject: example.com");
136
137 println!("\n2. Encoding Certificate\n");
138
139 // Encode the certificate - the Encode trait was automatically derived!
140 let encoded = cert.to_der().expect("Failed to encode certificate");
141
142 println!("Encoded certificate: {} bytes", encoded.len());
143 println!(
144 "First 32 bytes: {:02X?}...",
145 &encoded[..32.min(encoded.len())]
146 );
147
148 println!("\n3. Decoding Certificate\n");
149
150 // Decode the certificate - the Decode trait was automatically derived!
151 let decoded_cert = Certificate::from_der(&encoded).expect("Failed to decode certificate");
152
153 println!("Successfully decoded certificate!");
154 println!(
155 " - Serial number matches: {}",
156 decoded_cert.tbs_certificate.serial_number.as_i64().unwrap() == 123456
157 );
158 println!(
159 " - Version matches: {}",
160 decoded_cert.tbs_certificate.version.is_some()
161 );
162
163 println!("\n4. Tagged Fields Example\n");
164
165 // The version field uses EXPLICIT tagging [0]
166 // This is automatically handled by the derive macro
167 println!("Version field uses [0] EXPLICIT tag");
168 println!("This wrapping is automatic with #[asn1(tag(0, explicit))]");
169
170 println!("\n5. CHOICE Type Example\n");
171
172 // Create a Time CHOICE
173 let time = Time::Utc(UtcTime::new(2024, 6, 15, 12, 30, 0).unwrap());
174
175 let encoded_time = time.to_der().expect("Failed to encode time");
176 println!("Encoded CHOICE (Time): {} bytes", encoded_time.len());
177
178 let decoded_time = Time::from_der(&encoded_time).expect("Failed to decode time");
179
180 match decoded_time {
181 Time::Utc(utc) => println!("Decoded UTC time: {:?}", utc),
182 }
183
184 println!("\n=== Summary ===\n");
185 println!("Derive macros eliminate ~150 lines of boilerplate per struct!");
186 println!("No manual Encode/Decode/Tagged implementations needed.");
187 println!("Tagged fields (#[asn1(tag(...))]) are handled automatically.");
188 println!("CHOICE types work seamlessly with enums.");
189}Sourcepub fn as_u128(&self) -> Result<u128>
pub fn as_u128(&self) -> Result<u128>
Convert to u128 if the value is non-negative and fits in 128 bits.
Handles the DER positive-integer convention: a leading 0x00 byte is
stripped before checking the length, so a correctly-encoded 128-bit
serial number (17 bytes: 0x00 prefix + 16 data bytes) is returned as
the expected positive u128. Returns Err for negative values (high
bit set without a 0x00 prefix) or values that would overflow u128.
Trait Implementations§
impl Eq for Integer
impl StructuralPartialEq for Integer
Auto Trait Implementations§
impl Freeze for Integer
impl RefUnwindSafe for Integer
impl Send for Integer
impl Sync for Integer
impl Unpin for Integer
impl UnsafeUnpin for Integer
impl UnwindSafe for Integer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> TagForOptional for Twhere
T: Tagged,
impl<T> TagForOptional for Twhere
T: Tagged,
Source§fn optional_tag() -> Option<Tag>
fn optional_tag() -> Option<Tag>
None if
the type accepts multiple tags (CHOICE) or any tag (ANY / Element<'a>).