cddl 0.10.2 → 0.10.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33adef2ddb191ca70e7ad3742684cea679e675fe0169a139c9fa5bcc59abfaa6
4
- data.tar.gz: 7b7b7d2cd0623645d6dca87c5c7a8a3d40540e7eec390411e9cbf3adcc6f7c9d
3
+ metadata.gz: 9e60b48882767d7e76926473b44c79369891e4203326d4e31f5693a3819f391d
4
+ data.tar.gz: 6ed2f45e7fa8468557e73c96a4dbfdd142d65fdebeeb362efeebec8007b7948f
5
5
  SHA512:
6
- metadata.gz: b4a8ccd11e9dbf1b0ebf2541c03691a94a8430538fbe81db3bd178a2fab1732626114689d305048e88fb54c3336f0e95853c86f8336586d722df90639f82efa6
7
- data.tar.gz: 1c6494a0fa4ead8ea548f61f3af5595dde99707359ce8aa8695c074288248334849f2452cae52620541bb762c9cf3979b159f415a1b787009d1061df54d849b5
6
+ metadata.gz: 2124a4fc046c3dc03d007ca949e4f9191497b359fe19fafe307ed2227c4b5654d909815575504e452add310dfc8487bfc13db94794d4b6c06a7af0bb2701e55f
7
+ data.tar.gz: 8a223332d81282eb9ad651dad887579ceb7b44a01d05ccff6458e271ea999a3c5fad5f81c87a6a2ccf927307b3bb9c4e06075361b0f8fc8b02005926a3d9a5b7
data/cddl.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.10.2'
3
+ s.version = '0.10.3'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2022 Weihang Jian <https://tonytonyjan.net>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # An implementation of draft-faltstrom-base45-10, see
24
+ # https://datatracker.ietf.org/doc/draft-faltstrom-base45/
25
+ module Base45Lite
26
+ class Error < ::StandardError; end
27
+ class OverflowError < Error; end
28
+ class InvalidCharacterError < Error; end
29
+ class ForbiddenLengthError < Error; end
30
+
31
+ MAX_UINT18 = 2**16 - 1
32
+ SQUARED_45 = 45**2
33
+ MAPPING = [
34
+ *'0'..'9',
35
+ *'A'..'Z',
36
+ ' ', '$', '%', '*', '+', '-', '.', '/', ':'
37
+ ].map!.with_index { |x, i| [i, x] }.to_h.freeze
38
+ REVERSE_MAPPING = MAPPING.invert.freeze
39
+
40
+ def self.encode(input)
41
+ sequence = []
42
+ input.unpack('n*').map! do |uint16|
43
+ i, c = uint16.divmod(45)
44
+ i, d = i.divmod(45)
45
+ _, e = i.divmod(45)
46
+ sequence.push(c, d, e)
47
+ end
48
+ if input.bytesize.odd?
49
+ i, c = input.getbyte(-1).divmod(45)
50
+ _, d = i.divmod(45)
51
+ sequence.push(c, d)
52
+ end
53
+ sequence.map!{ |n| MAPPING[n] }.join
54
+ end
55
+
56
+ def self.decode(input)
57
+ input
58
+ .chars.map! { |c| REVERSE_MAPPING[c] || raise(InvalidCharacterError) }
59
+ .each_slice(3).map do |slice|
60
+ c, d, e = slice
61
+ raise ForbiddenLengthError if d.nil?
62
+
63
+ sum = c + d * 45
64
+ sum += e * SQUARED_45 if e
65
+ raise OverflowError if sum > MAX_UINT18
66
+
67
+ sum
68
+ end
69
+ .pack((input.length % 3).zero? ? 'n*' : "n#{input.length / 3}C")
70
+ end
71
+ end
data/lib/cddl.rb CHANGED
@@ -2,11 +2,13 @@ require 'abnc'
2
2
  require 'pp'
3
3
  require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
+ require 'cbor-deterministic'
5
6
  require 'regexp-examples'
6
7
  require 'abnftt'
7
8
  require 'colorize'
8
9
  require 'base64'
9
10
  require 'base32'
11
+ require 'base45_lite'
10
12
 
11
13
  module CDDL
12
14
 
@@ -267,6 +269,21 @@ module CDDL
267
269
  l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
268
270
  end
269
271
 
272
+ def unpack_array_to_sequence(content, where)
273
+ # remove the first head
274
+ n = case content.getbyte(0) - (4 << 5)
275
+ when 0..23; 1
276
+ when 24; 2
277
+ when 25; 3
278
+ when 26; 5
279
+ when 27; 9 # unlikely :-)
280
+ else fail ".cborseq sequence for #{where} not an array"
281
+ end
282
+ content[0...n] = ''
283
+ content
284
+ end
285
+
286
+
270
287
  # Memoize a bit here
271
288
 
272
289
  REGEXP_FOR_STRING = Hash.new {|h, k|
@@ -561,22 +578,18 @@ module CDDL
561
578
  end
562
579
  enc = bytes ? Encoding::BINARY : Encoding::UTF_8
563
580
  out.force_encoding(enc)
564
- when :cbor, :cborseq
581
+ when :cbor, :cborseq, :cbordet, :cborseqdet
565
582
  unless target == [:prim, 2]
566
583
  fail "Don't know yet how to generate #{where}"
567
584
  end
568
- content = CBOR::encode(generate1(control))
569
- if conop == :cborseq
585
+ input = generate1(control)
586
+ if conop == :cbordet || conop == :cborseqdet
587
+ input = input.cbor_prepare_deterministic
588
+ end
589
+ content = CBOR::encode(input)
590
+ if conop == :cborseq || conop == :cborseqdet
570
591
  # remove the first head
571
- n = case content.getbyte(0) - (4 << 5)
572
- when 0..23; 1
573
- when 24; 2
574
- when 25; 3
575
- when 26; 5
576
- when 27; 9 # unlikely :-)
577
- else fail "Generated .cborseq sequence for #{where} not an array"
578
- end
579
- content[0...n] = ''
592
+ content = unpack_array_to_sequence(content, where)
580
593
  end
581
594
  content
582
595
  when :json
@@ -601,16 +614,19 @@ module CDDL
601
614
  end
602
615
  content = content.join
603
616
  content
604
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
617
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
618
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc
605
619
  content = generate1(control)
606
620
  unless String === content
607
621
  fail "Don't know yet how to generate #{where}"
608
622
  end
609
623
  content = case conop
610
- when :b64u
624
+ when :b64u, :"b64u-sloppy"
611
625
  Base64.urlsafe_encode64(content, padding: false)
612
- when :b64c
626
+ when :b64c, :"b64c-sloppy"
613
627
  Base64.strict_encode64(content)
628
+ when :b45
629
+ Base45Lite.encode(content)
614
630
  when :b32
615
631
  Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
616
632
  Base32.encode(content).gsub("=", "")
@@ -1040,6 +1056,22 @@ module CDDL
1040
1056
  ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
1041
1057
  when :cborseq
1042
1058
  ann if validate1((CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR), control)
1059
+ when :cbordet
1060
+ decoded = CBOR::decode(d) rescue :BAD_CBOR
1061
+ if d != decoded.to_deterministic_cbor
1062
+ @last_message = "CBOR #{d.inspect} not deterministically encoded"
1063
+ nil
1064
+ else
1065
+ ann if validate1(decoded, control)
1066
+ end
1067
+ when :cborseqdet
1068
+ decoded = CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR
1069
+ if d != unpack_array_to_sequence(decoded.to_deterministic_cbor, d.inspect)
1070
+ @last_message = "CBOR Sequence #{d.inspect} not deterministically encoded"
1071
+ nil
1072
+ else
1073
+ ann if validate1(decoded, control)
1074
+ end
1043
1075
  when :json
1044
1076
  ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
1045
1077
  when :decimal
@@ -1060,19 +1092,26 @@ module CDDL
1060
1092
  else
1061
1093
  fail "Don't know yet how to validate against #{where}"
1062
1094
  end
1063
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
1095
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy", :b45, :b32, :h32, :hex, :hexlc, :hexuc
1064
1096
  ann if (
1065
1097
  String === d && (
1066
1098
  decoded = case conop
1067
1099
  when :b64u
1068
1100
  /=/ !~ d &&
1069
1101
  Base64.urlsafe_decode64(d)
1102
+ when :"b64u-sloppy"
1103
+ /[-_=]/ !~ d &&
1104
+ Base64.decode64(d.tr("+/", "-_"))
1070
1105
  when :b64c
1071
1106
  Base64.strict_decode64(d)
1107
+ when :"b64c-sloppy"
1108
+ Base64.decode64(d)
1072
1109
  when :b32
1073
1110
  /=/ !~ d &&
1074
1111
  (Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") &&
1075
1112
  Base32.decode(d)
1113
+ when :b45
1114
+ Base45Lite.decode(d)
1076
1115
  when :h32
1077
1116
  /=/ !~ d &&
1078
1117
  (Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV") &&
@@ -1441,11 +1480,14 @@ module CDDL
1441
1480
 
1442
1481
  BRACE = {"{" => :map, "[" => :array}
1443
1482
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1444
- SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1483
+ SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
1484
+ :cbor, :cborseq, :cbordet, :cborseqdet,
1485
+ :within, :and,
1445
1486
  :default, :lt, :le, :gt, :ge, :eq, :ne,
1446
1487
  :feature, :abnf, :abnfb, :det, :cat, :plus,
1447
1488
  :json, :decimal, :join,
1448
- :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc,
1489
+ :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
1490
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc,
1449
1491
  ]
1450
1492
 
1451
1493
  def type1(n, canbegroup = false)
@@ -0,0 +1 @@
1
+ a = text .b64c-sloppy 'mnoabcdue=='
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-25 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -119,6 +119,7 @@ files:
119
119
  - cddl.gemspec
120
120
  - data/cddl.abnf
121
121
  - data/prelude.cddl
122
+ - lib/base45_lite.rb
122
123
  - lib/cbor-pp-play.rb
123
124
  - lib/cbor-pp.rb
124
125
  - lib/cddl.rb
@@ -133,6 +134,7 @@ files:
133
134
  - test-data/abnf3.cddl
134
135
  - test-data/ambig.cddl
135
136
  - test-data/b.cddl
137
+ - test-data/b64c-sloppy.cddl
136
138
  - test-data/b64c.cddl
137
139
  - test-data/b64u.cddl
138
140
  - test-data/badaddr.cddl
@@ -245,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
247
  - !ruby/object:Gem::Version
246
248
  version: '0'
247
249
  requirements: []
248
- rubygems_version: 3.4.2
250
+ rubygems_version: 3.4.6
249
251
  signing_key:
250
252
  specification_version: 4
251
253
  summary: CDDL generator and validator.