cddl 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.