v2 / vlib / x / encoding / asn1 / sequence_test.v
371 lines · 294 sloc · 9.64 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
2// Use of this source code is governed by a MIT License
3// that can be found in the LICENSE file.
4module asn1
5
6import math.big
7
8fn test_sequence_with_multi_items() ! {
9 mut seq := Sequence{}
10
11 o1 := Boolean.new(true) // 3
12 o2 := UtcTime.new('191215190210Z')! // 15
13 o3 := GeneralizedTime.new('20100102030405Z')! // 17
14
15 // we are going to add with add_element to allow adding element with the same tag
16 seq.add_element(o1)!
17 seq.add_element(o2)!
18 seq.add_element(o3)!
19
20 assert seq.payload()!.len == 3 + 15 + 17 // 35
21 assert encoded_len(seq) == 2 + 35
22
23 out := encode(seq)!
24 exp := [u8(0x30), 35, u8(0x01), 0x01, 0xff, u8(0x17), 0x0D, 49, 57, 49, 50, 49, 53, 49, 57,
25 48, 50, 49, 48, 90, u8(0x18), 0x0f, 50, 48, 49, 48, 48, 49, 48, 50, 48, 51, 48, 52, 48,
26 53, 90]
27
28 assert out == exp
29}
30
31fn test_sequence_contains_other_seq() ! {
32 // lets create first sequence
33 mut seq1 := Sequence{}
34 // add two primitive elements to the sequence
35 seq1.add_element(Boolean.new(true))!
36 seq1.add_element(Null{})!
37 seq1.add_element(Boolean.new(false))!
38
39 // lets create another sequences, where it contains primitive element and first sequence created above.
40 mut seq2 := Sequence{}
41 seq2.add_element(Boolean.new(false))!
42 seq2.add_element(seq1)!
43 // you should force add element to allow add second Boolean, by default its not allowed
44 seq2.add_element(Boolean.new(true))!
45
46 // lets serialize it to bytes
47
48 out := encode(seq2)!
49
50 expected := [u8(0x30), 16, u8(0x01), 0x01, 0x00, u8(0x30), 8, 0x01, 0x01, 0xff, u8(0x05), 0x00,
51 u8(0x01), 0x01, 0x00, u8(0x01), 0x01, 0xff]
52 // assert for right value
53 assert seq2.payload()!.len == 16
54 assert encoded_len(seq2) == 18
55 assert out == expected
56
57 seq2_back, _ := Sequence.decode(expected)!
58 assert seq2_back.fields()[1] is Sequence
59}
60
61fn test_sequence_der_decode() ! {
62 data := [u8(0x30), 16, u8(0x01), 0x01, 0x00, u8(0x30), 8, u8(0x01), 0x01, 0xff, u8(0x05), 0x00,
63 u8(0x01), 0x01, 0x00, u8(0x01), 0x01, 0xff]
64
65 seq, n := Sequence.decode(data)!
66 assert seq.tag().is_constructed() == true
67 assert seq.tag().tag_number() == int(TagType.sequence)
68 assert n == 18
69 assert seq.fields().len == 3
70 els := seq.fields()
71
72 assert els[0].tag() == Tag.new(.universal, false, int(TagType.boolean))!
73 assert els[0].payload()! == [u8(0x00)]
74
75 el1 := els[1] as Sequence
76 assert el1.fields().len == 3 // [true, null, false]
77 el10 := el1.fields()[0] as Boolean
78 assert el10.value() == true
79 el11 := el1.fields()[1] as Null
80 assert el11 == Null{}
81 el12 := el1.fields()[2] as Boolean
82 assert el12.value() == false
83
84 el2 := els[2] as Boolean
85 assert el2.value() == true
86}
87
88fn test_sequence_add_and_encode_boolean() {
89 o1 := Boolean.new(false)
90 o2 := Boolean.new(true)
91 o3 := Null{}
92 mut seq := Sequence{}
93 seq.add_element(o1)!
94 seq.add_element(o2)!
95 seq.add_element(o3)!
96
97 length := seq.payload()!.len
98 assert length == 8
99
100 size := encoded_len(seq)
101 assert size == 10
102
103 out := encode(seq)!
104
105 exp := [u8(0x30), 0x08, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0x05, 0x00]
106
107 assert out == exp
108 assert exp.len == size
109
110 back, n := Sequence.decode(out)!
111 assert n == exp.len
112
113 assert back.fields().len == 3
114
115 assert back.tag().number == 0x10
116 assert back.tag().constructed == true
117 assert back.tag().class == .universal
118
119 assert back.fields()[0].tag().class == .universal
120 assert back.fields()[0].tag().constructed == false
121 assert back.fields()[0].tag().number == 0x01
122
123 assert back.fields()[1].tag().class == .universal
124 assert back.fields()[1].tag().constructed == false
125 assert back.fields()[1].tag().number == 0x01
126
127 assert back.fields()[2].tag().number == 0x05
128 assert back.fields()[2].tag().constructed == false
129}
130
131fn test_sequence_add_encode_oid() ! {
132 mut seq := Sequence{}
133
134 o1 := ObjectIdentifier.new('1.2.3')! // size = 4
135 o2 := ObjectIdentifier.new('1.2.4')! // size = 4
136 o3 := Boolean.new(true) // size = 3
137
138 seq.add_element(o1)!
139 seq.add_element(o2)!
140 seq.add_element(o3)!
141
142 assert seq.tag() == Tag.new(.universal, true, int(TagType.sequence))!
143 assert seq.payload()!.len == 11
144 assert encoded_len(seq) == 13
145
146 mut out := encode(seq)!
147 exp := [u8(0x30), 0x0b, u8(0x06), 0x02, 0x2a, 0x03, u8(0x06), 0x02, 0x2a, 0x04, u8(0x01), 0x01,
148 0xff]
149
150 assert out == exp
151
152 back, n := Sequence.decode(out)!
153 assert n == exp.len
154 //(back)
155
156 assert back.fields().len == 3
157 assert back.tag().constructed == true
158 //
159 out.clear()
160 out = encode(back.fields()[0])!
161 assert out == [u8(0x06), 0x02, 0x2a, 0x03]
162 //
163 out.clear()
164 out = encode(back.fields()[1])!
165 assert out == [u8(0x06), 0x02, 0x2a, 0x04]
166 //
167 out.clear()
168 out = encode(back.fields()[2])!
169 assert out == [u8(0x01), 0x01, 0xff]
170}
171
172fn test_sequence_add_encode_integer() ! {
173 mut seq := Sequence.new()!
174
175 o1 := Integer.from_i64(127)
176 o2 := Boolean.new(true)
177 o3 := Integer.from_i64(max_i64)
178 seq.add_element(o1)!
179 seq.add_element(o2)!
180 seq.add_element(o3)!
181
182 assert seq.tag() == Tag.new(.universal, true, int(TagType.sequence))!
183 assert seq.payload()!.len == 16
184 assert encoded_len(seq) == 18
185
186 mut out := encode(seq)!
187 // math.max_i64 serialize to 02087fffffffffffffff
188 exp := [u8(0x30), 0x10, u8(0x02), 0x01, 0x7f, u8(0x01), 0x01, 0xff, u8(0x02), 0x08, 0x7f, 0xff,
189 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
190
191 assert out == exp
192
193 back, n := Sequence.decode(out)!
194 assert n == exp.len
195
196 assert back.fields().len == 3
197 assert back.tag().number == 16
198 assert back.tag().constructed == true
199}
200
201fn test_sequence_integer_bigint() ! {
202 inp :=
203 big.integer_from_string('84885164052257330097714121751630835360966663883732297726369399')!
204 mut seq := Sequence.new()!
205
206 o1 := Integer.from_bigint(inp)
207 o2 := Boolean.new(true)
208 o3 := Null{}
209 seq.add_element(o1)!
210 seq.add_element(o2)!
211 seq.add_element(o3)!
212
213 mut out := encode(seq)!
214
215 assert seq.payload()!.len == 28 + 3 + 2
216 assert encoded_len(seq) == 2 + 28 + 3 + 2
217 exp := [u8(0x30), 33, u8(0x02), 26, 52, 210, 252, 160, 105, 66, 145, 88, 8, 53, 227, 150, 221,
218 98, 149, 87, 146, 121, 109, 20, 162, 246, 230, 65, 30, 119, u8(0x01), 0x01, 0xff, u8(0x05),
219 0x00]
220
221 assert out == exp
222
223 back, n := Sequence.decode(out)! // Sequence
224 assert n == exp.len
225
226 // clear out
227 out.clear()
228 out = encode(back)!
229 assert out == exp
230
231 assert back.fields().len == 3
232 assert back.tag().number == 16
233 assert back.tag().constructed == true
234
235 // clear out
236 out.clear()
237 out = encode(back.fields()[1])!
238 assert out == [u8(0x01), 0x01, 0xff]
239}
240
241fn test_sequence_of_string() ! {
242 str := 'iloveyou' // 8
243 mut seq := Sequence.new()!
244 o1 := Null{}
245 o2 := Utf8String.new(str)!
246 o3 := IA5String.new(str)!
247 seq.add_element(o1)!
248 seq.add_element(o2)!
249 seq.add_element(o3)!
250
251 assert seq.payload()!.len == 22
252 assert seq.encoded_len() == 24
253
254 mut out := encode(seq)!
255 exp := [u8(0x30), 22, u8(0x05), 0x00, u8(12), 8, u8(105), 108, 111, 118, 101, 121, 111, 117,
256 u8(22), 8, u8(105), 108, 111, 118, 101, 121, 111, 117]
257 assert out == exp
258
259 back, n := Sequence.decode(out)!
260 assert n == exp.len
261 // clears out
262 out.clear()
263 out = encode(back)!
264 assert out == exp
265}
266
267fn test_sequnce_of_sequence() {
268 mut seq := Sequence.new()!
269
270 seq.add_element(Null{})!
271 seq.add_element(Boolean.new(false))!
272
273 mut out := encode(seq)!
274 assert out == [u8(0x30), 5, 5, 0, 1, 1, 0]
275
276 mut seq2 := Sequence.new()!
277 seq2.add_element(Integer.from_i64(5))!
278 seq2.add_element(Integer.from_i64(i64(86424278346)))!
279
280 // clear out
281 out.clear()
282 out = encode(seq2)!
283 assert out == [u8(0x30), 10, 2, 1, 5, 2, 5, 0x14, 0x1f, 0x49, 0xd5, 0x4a]
284
285 seq.add_element(seq2)!
286 // clear out
287 out.clear()
288 out = encode(seq)!
289 assert out == [u8(0x30), 17, 5, 0, 1, 1, 0, u8(0x30), 10, 2, 1, 5, 2, 5, 0x14, 0x1f, 0x49,
290 0xd5, 0x4a]
291
292 back_seq := decode(out)!
293 assert back_seq.equal(seq)
294
295 back := back_seq.into_object[Sequence]()!
296 assert back.fields().len == 3
297 assert back.fields()[0] is Null
298 assert back.fields()[1] is Boolean
299 assert back.fields()[2] is Sequence
300
301 two := back.fields()[2]
302 if two is Sequence {
303 assert two.fields()[0] is Integer
304 assert two.fields()[1] is Integer
305 assert two.fields()[1].payload()!.len == 5
306 }
307}
308
309// Taken from https://letsencrypt.org/id/docs/a-warm-welcome-to-asn1-and-der/
310//
311// As an example, RFC 5280 defines AlgorithmIdentifier as a SEQUENCE:
312//
313// AlgorithmIdentifier ::= SEQUENCE {
314// algorithm OBJECT IDENTIFIER,
315// parameters ANY DEFINED BY algorithm OPTIONAL
316// }
317// Here’s the encoding of the AlgorithmIdentifier containing 1.2.840.113549.1.1.11.
318// RFC 8017 says “parameters” should have the type NULL for this algorithm.
319// was serialized into: 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00
320struct AlgorithmIdentifier {
321 algorithm ObjectIdentifier
322 parameters AnyDefinedBy
323}
324
325fn (a AlgorithmIdentifier) tag() Tag {
326 return default_sequence_tag
327}
328
329fn (a AlgorithmIdentifier) payload() ![]u8 {
330 mut out := []u8{}
331 out << encode(a.algorithm)!
332 out << encode(a.parameters)!
333
334 return out
335}
336
337fn test_sequence_algorithm_identifier() ! {
338 expected := [u8(0x30), 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
339 0x05, 0x00]
340 algo := AlgorithmIdentifier{
341 algorithm: ObjectIdentifier.new('1.2.840.113549.1.1.11')!
342 parameters: AnyDefinedBy.new(Null{})
343 }
344 out := encode(algo)!
345 assert out == expected
346
347 sback := decode(out)!
348 seq := sback as Sequence
349 s0 := seq.fields[0] as ObjectIdentifier
350 assert s0 == algo.algorithm
351
352 s1 := seq.fields[1] as Null
353 prm := algo.parameters.params as Null
354 assert s1 == prm
355}
356
357// Here is the encoding of a SEQUENCE OF INTEGER containing the numbers 7, 8, and 9:
358//
359// encoded into: 30 09 02 01 07 02 01 08 02 01 09
360fn test_sequence_of_integer() ! {
361 expected := [u8(0x30), 0x09, 0x02, 0x01, 0x07, 0x02, 0x01, 0x08, 0x02, 0x01, 0x09]
362
363 mut els := []Integer{}
364 els << Integer.from_int(7)
365 els << Integer.from_int(8)
366 els << Integer.from_int(9)
367
368 seqof := SequenceOf.from_list[Integer](els)!
369 out := encode(seqof)!
370 assert out == expected
371}
372