moxml 0.1.25 → 0.2.0

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.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +9 -0
  3. data/.github/workflows/windows.yml +62 -0
  4. data/Gemfile +3 -1
  5. data/README.adoc +133 -6
  6. data/docs/signature/algorithms.md +108 -0
  7. data/docs/signature/architecture.md +148 -0
  8. data/docs/signature/c14n.md +110 -0
  9. data/docs/signature/examples.md +109 -0
  10. data/docs/signature/flows.md +132 -0
  11. data/docs/signature/quick-reference.md +115 -0
  12. data/docs/signature/security.md +143 -0
  13. data/examples/signature/auto_key_extraction.rb +24 -0
  14. data/examples/signature/enveloped_rsa.rb +45 -0
  15. data/examples/signature/hmac.rb +33 -0
  16. data/lib/compat/opal/moxml_boot.rb +5 -0
  17. data/lib/moxml/adapter/base.rb +53 -49
  18. data/lib/moxml/adapter/customized_leptris/declaration.rb +32 -0
  19. data/lib/moxml/adapter/customized_leptris/doctype.rb +31 -0
  20. data/lib/moxml/adapter/customized_leptris/entity_reference.rb +12 -0
  21. data/lib/moxml/adapter/customized_leptris/text_segment.rb +26 -0
  22. data/lib/moxml/adapter/customized_leptris.rb +16 -0
  23. data/lib/moxml/adapter/customized_libxml/cdata.rb +3 -12
  24. data/lib/moxml/adapter/customized_libxml/comment.rb +2 -9
  25. data/lib/moxml/adapter/customized_libxml/declaration.rb +1 -10
  26. data/lib/moxml/adapter/customized_libxml/node.rb +8 -0
  27. data/lib/moxml/adapter/customized_libxml/processing_instruction.rb +2 -10
  28. data/lib/moxml/adapter/customized_libxml/text.rb +2 -9
  29. data/lib/moxml/adapter/customized_oga/entity_decoder.rb +37 -0
  30. data/lib/moxml/adapter/customized_oga/raw_value_override.rb +52 -0
  31. data/lib/moxml/adapter/customized_oga/xml_generator.rb +4 -34
  32. data/lib/moxml/adapter/customized_oga.rb +2 -0
  33. data/lib/moxml/adapter/customized_ox/entity_reference.rb +1 -17
  34. data/lib/moxml/adapter/customized_rexml/entity_reference.rb +1 -11
  35. data/lib/moxml/adapter/headed_ox.rb +9 -128
  36. data/lib/moxml/adapter/leptris.rb +965 -0
  37. data/lib/moxml/adapter/libxml.rb +131 -99
  38. data/lib/moxml/adapter/nokogiri.rb +29 -8
  39. data/lib/moxml/adapter/oga.rb +91 -54
  40. data/lib/moxml/adapter/ox.rb +93 -137
  41. data/lib/moxml/adapter/rexml.rb +61 -50
  42. data/lib/moxml/adapter.rb +2 -1
  43. data/lib/moxml/attribute.rb +8 -4
  44. data/lib/moxml/attribute_resolver.rb +189 -0
  45. data/lib/moxml/c14n/attribute_handler.rb +71 -0
  46. data/lib/moxml/c14n/character_encoder.rb +29 -0
  47. data/lib/moxml/c14n/data_model.rb +145 -0
  48. data/lib/moxml/c14n/exclusive.rb +188 -0
  49. data/lib/moxml/c14n/inclusive_10.rb +42 -0
  50. data/lib/moxml/c14n/inclusive_11.rb +21 -0
  51. data/lib/moxml/c14n/namespace_context.rb +68 -0
  52. data/lib/moxml/c14n/namespace_handler.rb +71 -0
  53. data/lib/moxml/c14n/node.rb +42 -0
  54. data/lib/moxml/c14n/nodes/attribute_node.rb +50 -0
  55. data/lib/moxml/c14n/nodes/comment_node.rb +29 -0
  56. data/lib/moxml/c14n/nodes/element_node.rb +62 -0
  57. data/lib/moxml/c14n/nodes/namespace_node.rb +41 -0
  58. data/lib/moxml/c14n/nodes/processing_instruction_node.rb +30 -0
  59. data/lib/moxml/c14n/nodes/root_node.rb +22 -0
  60. data/lib/moxml/c14n/nodes/text_node.rb +29 -0
  61. data/lib/moxml/c14n/nodes.rb +17 -0
  62. data/lib/moxml/c14n/processor.rb +118 -0
  63. data/lib/moxml/c14n/writer.rb +121 -0
  64. data/lib/moxml/c14n/xml_base_handler.rb +140 -0
  65. data/lib/moxml/c14n.rb +96 -0
  66. data/lib/moxml/config.rb +29 -3
  67. data/lib/moxml/context.rb +12 -0
  68. data/lib/moxml/element.rb +29 -12
  69. data/lib/moxml/entity/reference.rb +28 -0
  70. data/lib/moxml/entity.rb +125 -0
  71. data/lib/moxml/node.rb +90 -1
  72. data/lib/moxml/sax/namespace_splitter.rb +5 -2
  73. data/lib/moxml/signature/algorithms/base64_transform.rb +40 -0
  74. data/lib/moxml/signature/algorithms/canonicalization_base.rb +87 -0
  75. data/lib/moxml/signature/algorithms/digest_base.rb +51 -0
  76. data/lib/moxml/signature/algorithms/dsa_sha.rb +107 -0
  77. data/lib/moxml/signature/algorithms/ecdsa_sha.rb +125 -0
  78. data/lib/moxml/signature/algorithms/enveloped_signature_transform.rb +79 -0
  79. data/lib/moxml/signature/algorithms/exc_c14n_10.rb +23 -0
  80. data/lib/moxml/signature/algorithms/hmac_sha.rb +117 -0
  81. data/lib/moxml/signature/algorithms/inclusive_c14n_10.rb +21 -0
  82. data/lib/moxml/signature/algorithms/inclusive_c14n_11.rb +23 -0
  83. data/lib/moxml/signature/algorithms/rsa_pkcs1_sha.rb +56 -0
  84. data/lib/moxml/signature/algorithms/sha1.rb +13 -0
  85. data/lib/moxml/signature/algorithms/sha224.rb +13 -0
  86. data/lib/moxml/signature/algorithms/sha256.rb +13 -0
  87. data/lib/moxml/signature/algorithms/sha384.rb +13 -0
  88. data/lib/moxml/signature/algorithms/sha512.rb +13 -0
  89. data/lib/moxml/signature/algorithms/signature_method_base.rb +58 -0
  90. data/lib/moxml/signature/algorithms/transform_base.rb +40 -0
  91. data/lib/moxml/signature/algorithms.rb +113 -0
  92. data/lib/moxml/signature/errors.rb +99 -0
  93. data/lib/moxml/signature/key_extractor.rb +172 -0
  94. data/lib/moxml/signature/model/algorithm_method.rb +18 -0
  95. data/lib/moxml/signature/model/digest_method.rb +15 -0
  96. data/lib/moxml/signature/model/key/dsa_key_value.rb +28 -0
  97. data/lib/moxml/signature/model/key/ec_key_value.rb +22 -0
  98. data/lib/moxml/signature/model/key/rsa_key_value.rb +19 -0
  99. data/lib/moxml/signature/model/key/x509_data.rb +32 -0
  100. data/lib/moxml/signature/model/key/x509_digest.rb +19 -0
  101. data/lib/moxml/signature/model/key/x509_issuer_serial.rb +19 -0
  102. data/lib/moxml/signature/model/key_info.rb +21 -0
  103. data/lib/moxml/signature/model/key_value.rb +20 -0
  104. data/lib/moxml/signature/model/object_element.rb +18 -0
  105. data/lib/moxml/signature/model/reference.rb +22 -0
  106. data/lib/moxml/signature/model/signature.rb +21 -0
  107. data/lib/moxml/signature/model/signature_value.rb +16 -0
  108. data/lib/moxml/signature/model/signed_info.rb +20 -0
  109. data/lib/moxml/signature/model/transform.rb +16 -0
  110. data/lib/moxml/signature/model/transforms.rb +36 -0
  111. data/lib/moxml/signature/model.rb +35 -0
  112. data/lib/moxml/signature/parser.rb +270 -0
  113. data/lib/moxml/signature/reference_resolver.rb +79 -0
  114. data/lib/moxml/signature/reference_result.rb +22 -0
  115. data/lib/moxml/signature/serializer.rb +163 -0
  116. data/lib/moxml/signature/signer.rb +73 -0
  117. data/lib/moxml/signature/single_verification_result.rb +31 -0
  118. data/lib/moxml/signature/transform_pipeline.rb +106 -0
  119. data/lib/moxml/signature/verification_result.rb +27 -0
  120. data/lib/moxml/signature/verifier.rb +129 -0
  121. data/lib/moxml/signature.rb +94 -0
  122. data/lib/moxml/version.rb +1 -1
  123. data/lib/moxml/xml_emitter.rb +71 -0
  124. data/lib/moxml/xpath/compiler.rb +60 -7
  125. data/lib/moxml/xpath/parser.rb +22 -15
  126. data/lib/moxml.rb +5 -0
  127. data/reference-docs/w3c-xmldsig-bestpractices.md +216 -0
  128. data/reference-docs/w3c-xmldsig-core.md +400 -0
  129. data/spec/examples/readme_examples_spec.rb +0 -4
  130. data/spec/examples/xpath_examples_spec.rb +0 -11
  131. data/spec/fixtures/xmldsig/keys/rsa_private.pem +28 -0
  132. data/spec/fixtures/xmldsig/keys/rsa_public.pem +9 -0
  133. data/spec/fixtures/xmldsig/keys/rsa_ref.pem +15 -0
  134. data/spec/fixtures/xmldsig/keys/rsa_ref.pub +6 -0
  135. data/spec/fixtures/xmldsig/sign2-doc.xml +6 -0
  136. data/spec/fixtures/xmldsig/sign2-result.xml +25 -0
  137. data/spec/fixtures/xmldsig/sign3-result.xml +39 -0
  138. data/spec/integration/all_adapters_spec.rb +17 -0
  139. data/spec/integration/sax_parity_spec.rb +58 -0
  140. data/spec/integration/shared_examples/edge_cases.rb +0 -10
  141. data/spec/integration/shared_examples/integration_workflows.rb +0 -10
  142. data/spec/integration/shared_examples/node_wrappers/attribute_behavior.rb +98 -0
  143. data/spec/integration/shared_examples/node_wrappers/namespace_behavior.rb +26 -0
  144. data/spec/integration/shared_examples/node_wrappers/node_behavior.rb +0 -8
  145. data/spec/moxml/adapter/leptris_spec.rb +75 -0
  146. data/spec/moxml/adapter/ox_spec.rb +20 -6
  147. data/spec/moxml/adapter/platform_spec.rb +15 -2
  148. data/spec/moxml/adapter/shared_examples/adapter_contract.rb +180 -0
  149. data/spec/moxml/attribute_resolver_spec.rb +108 -0
  150. data/spec/moxml/c14n/api_spec.rb +117 -0
  151. data/spec/moxml/c14n/c14n_spec.rb +88 -0
  152. data/spec/moxml/c14n/comments_pis_spec.rb +65 -0
  153. data/spec/moxml/c14n/inclusive10_spec.rb +60 -0
  154. data/spec/moxml/c14n/namespace_edge_cases_spec.rb +88 -0
  155. data/spec/moxml/c14n/xml_attributes_spec.rb +54 -0
  156. data/spec/moxml/doctype_spec.rb +1 -1
  157. data/spec/moxml/entity_spec.rb +76 -0
  158. data/spec/moxml/node_spec.rb +104 -0
  159. data/spec/moxml/sax_entity_parity_spec.rb +358 -0
  160. data/spec/moxml/signature/algorithms/base64_transform_spec.rb +26 -0
  161. data/spec/moxml/signature/algorithms/digest_base_spec.rb +72 -0
  162. data/spec/moxml/signature/algorithms/dsa_sha_spec.rb +46 -0
  163. data/spec/moxml/signature/algorithms/ecdsa_sha_spec.rb +72 -0
  164. data/spec/moxml/signature/algorithms/enveloped_signature_transform_spec.rb +40 -0
  165. data/spec/moxml/signature/algorithms/hmac_sha_spec.rb +71 -0
  166. data/spec/moxml/signature/algorithms/rsa_pkcs1_sha_spec.rb +55 -0
  167. data/spec/moxml/signature/algorithms_spec.rb +76 -0
  168. data/spec/moxml/signature/cross_verify_spec.rb +64 -0
  169. data/spec/moxml/signature/edge_cases_spec.rb +284 -0
  170. data/spec/moxml/signature/fixtures_spec.rb +80 -0
  171. data/spec/moxml/signature/key_extractor_spec.rb +96 -0
  172. data/spec/moxml/signature/model_spec.rb +54 -0
  173. data/spec/moxml/signature/round_trip_spec.rb +113 -0
  174. data/spec/moxml/xml_emitter_spec.rb +64 -0
  175. data/spec/moxml/xpath/axes_spec.rb +72 -0
  176. data/spec/moxml/xpath/parser_spec.rb +6 -0
  177. data/spec/moxml/xpath_capabilities_spec.rb +5 -3
  178. data/spec/performance/benchmark_spec.rb +13 -6
  179. data/spec/performance/thread_safety_spec.rb +0 -4
  180. data/spec/spec_helper.rb +5 -1
  181. metadata +130 -2
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ class Error < ::Moxml::Error; end
6
+
7
+ class SignatureError < Error; end
8
+
9
+ class UnknownAlgorithm < Error
10
+ attr_reader :category, :uri
11
+
12
+ def initialize(category, uri)
13
+ @category = category
14
+ @uri = uri
15
+ super("Unknown #{category} algorithm: #{uri}")
16
+ end
17
+ end
18
+
19
+ class DuplicateAlgorithm < Error
20
+ attr_reader :category, :uri
21
+
22
+ def initialize(category, uri)
23
+ @category = category
24
+ @uri = uri
25
+ super("Algorithm already registered for #{category}: #{uri}")
26
+ end
27
+ end
28
+
29
+ class SigningError < Error
30
+ attr_reader :algorithm
31
+
32
+ def initialize(message, algorithm: nil)
33
+ @algorithm = algorithm
34
+ super(message)
35
+ end
36
+ end
37
+
38
+ class VerificationError < Error
39
+ attr_reader :signature_id
40
+
41
+ def initialize(message, signature_id: nil)
42
+ @signature_id = signature_id
43
+ super(message)
44
+ end
45
+ end
46
+
47
+ class ReferenceDigestMismatch < VerificationError
48
+ attr_reader :reference_uri, :expected, :computed
49
+
50
+ def initialize(reference_uri:, expected:, computed:, signature_id: nil)
51
+ @reference_uri = reference_uri
52
+ @expected = expected
53
+ @computed = computed
54
+ super(
55
+ "Digest mismatch for reference #{reference_uri.inspect}",
56
+ signature_id: signature_id,
57
+ )
58
+ end
59
+ end
60
+
61
+ class SignatureValueMismatch < VerificationError
62
+ attr_reader :algorithm
63
+
64
+ def initialize(algorithm: nil, signature_id: nil)
65
+ @algorithm = algorithm
66
+ super("SignatureValue did not verify", signature_id: signature_id)
67
+ end
68
+ end
69
+
70
+ class TransformError < Error
71
+ attr_reader :algorithm
72
+
73
+ def initialize(message, algorithm: nil)
74
+ @algorithm = algorithm
75
+ super(message)
76
+ end
77
+ end
78
+
79
+ class CanonicalizationError < Error
80
+ attr_reader :algorithm
81
+
82
+ def initialize(message, algorithm: nil)
83
+ @algorithm = algorithm
84
+ super(message)
85
+ end
86
+ end
87
+
88
+ class MalformedSignatureError < Error
89
+ attr_reader :detail
90
+
91
+ def initialize(message, detail: nil)
92
+ @detail = detail
93
+ super(message)
94
+ end
95
+ end
96
+
97
+ class SignatureKeyError < Error; end
98
+ end
99
+ end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "base64"
5
+
6
+ module Moxml
7
+ module Signature
8
+ # Extracts an OpenSSL verification key from a Model::KeyInfo.
9
+ #
10
+ # Strategy (per spec §4.5): X509Certificate is preferred for key
11
+ # reconstruction because it carries the certified binding. Falls back
12
+ # to RSAKeyValue / DSAKeyValue / ECKeyValue if no certificate is
13
+ # present. KeyName is resolved via an application-supplied key map.
14
+ class KeyExtractor
15
+ attr_reader :key_map, :cert_store
16
+
17
+ def initialize(key_map: {}, cert_store: nil)
18
+ @key_map = key_map || {}
19
+ @cert_store = cert_store
20
+ end
21
+
22
+ def extract(key_info)
23
+ return nil if key_info.nil?
24
+
25
+ from_x509_data(key_info.x509_data) ||
26
+ from_key_value(key_info.key_value) ||
27
+ from_key_name(key_info.key_name)
28
+ end
29
+
30
+ private
31
+
32
+ def from_x509_data(x509_data)
33
+ return nil unless x509_data
34
+
35
+ cert_b64 = x509_data.certificates.first
36
+ return nil unless cert_b64
37
+
38
+ # Certificates are stored as base64-encoded DER (spec §4.5.4).
39
+ # Decode here so we hand OpenSSL raw DER bytes.
40
+ cert_der = Base64.strict_decode64(cert_b64.to_s.gsub(/\s+/, ""))
41
+ cert = OpenSSL::X509::Certificate.new(cert_der)
42
+ cert.public_key
43
+ rescue OpenSSL::X509::CertificateError, ArgumentError
44
+ nil
45
+ end
46
+
47
+ def from_key_value(key_value)
48
+ return nil unless key_value
49
+
50
+ if key_value.rsa_key_value
51
+ rsa_public_key(key_value.rsa_key_value)
52
+ elsif key_value.dsa_key_value
53
+ dsa_public_key(key_value.dsa_key_value)
54
+ elsif key_value.ec_key_value
55
+ ec_public_key(key_value.ec_key_value)
56
+ end
57
+ end
58
+
59
+ def from_key_name(key_name)
60
+ return nil unless key_name
61
+
62
+ key_map[key_name]
63
+ end
64
+
65
+ def rsa_public_key(rsa_kv)
66
+ n = crypto_binary_to_integer(rsa_kv.modulus)
67
+ e = crypto_binary_to_integer(rsa_kv.exponent)
68
+ return nil unless n && e
69
+
70
+ # OpenSSL 3.x removed RSA.new(n, e). Reconstruct via the
71
+ # SubjectPublicKeyInfo form (PKCS#1 RSA public key DER).
72
+ asn1 = OpenSSL::ASN1::Sequence.new(
73
+ [
74
+ OpenSSL::ASN1::Integer.new(n),
75
+ OpenSSL::ASN1::Integer.new(e),
76
+ ],
77
+ )
78
+ OpenSSL::PKey::RSA.new(asn1.to_der)
79
+ rescue OpenSSL::PKey::RSAError
80
+ nil
81
+ end
82
+
83
+ def dsa_public_key(dsa_kv)
84
+ p = crypto_binary_to_integer(dsa_kv.p)
85
+ q = crypto_binary_to_integer(dsa_kv.q)
86
+ g = crypto_binary_to_integer(dsa_kv.g) if dsa_kv.g
87
+ y = crypto_binary_to_integer(dsa_kv.y)
88
+ return nil unless p && q && y
89
+
90
+ params = OpenSSL::ASN1::Sequence.new(
91
+ [
92
+ OpenSSL::ASN1::Integer.new(p),
93
+ OpenSSL::ASN1::Integer.new(q),
94
+ OpenSSL::ASN1::Integer.new(g || 0),
95
+ OpenSSL::ASN1::Integer.new(y),
96
+ ],
97
+ )
98
+ OpenSSL::PKey::DSA.new(params.to_der)
99
+ rescue OpenSSL::PKey::DSAError
100
+ nil
101
+ end
102
+
103
+ def ec_public_key(ec_kv)
104
+ return nil unless ec_kv.named_curve_uri && ec_kv.public_key
105
+
106
+ curve_name = curve_name_for(ec_kv.named_curve_uri)
107
+ return nil unless curve_name
108
+
109
+ # The XML signature PublicKey element already contains the
110
+ # uncompressed-point form (0x04 || x || y) per spec §4.5.2.3.
111
+ public_key_decoded = Base64.strict_decode64(ec_kv.public_key)
112
+ spki_der = build_ec_subject_public_key_info(curve_name, public_key_decoded)
113
+ OpenSSL::PKey::EC.new(spki_der)
114
+ rescue OpenSSL::PKey::ECError, ArgumentError
115
+ nil
116
+ end
117
+
118
+ # Build a SubjectPublicKeyInfo DER for an EC public key.
119
+ # OpenSSL 3.0 makes PKey instances immutable; we can no longer
120
+ # create an empty EC key and assign public_key=. Constructing the
121
+ # full SPKI and reading it back via OpenSSL::PKey::EC.new(der)
122
+ # is the supported path.
123
+ def build_ec_subject_public_key_info(curve_name, point_octets)
124
+ algorithm = OpenSSL::ASN1::Sequence.new(
125
+ [
126
+ OpenSSL::ASN1::ObjectId.new("id-ecPublicKey"),
127
+ OpenSSL::ASN1::ObjectId.new(curve_name_to_oid(curve_name)),
128
+ ],
129
+ )
130
+ OpenSSL::ASN1::Sequence.new(
131
+ [
132
+ algorithm,
133
+ OpenSSL::ASN1::BitString.new(point_octets),
134
+ ],
135
+ ).to_der
136
+ end
137
+
138
+ CURVE_NAME_TO_OID = {
139
+ "prime256v1" => "1.2.840.10045.3.1.7",
140
+ "secp384r1" => "1.3.132.0.34",
141
+ "secp521r1" => "1.3.132.0.35",
142
+ }.freeze
143
+ private_constant :CURVE_NAME_TO_OID
144
+
145
+ def curve_name_to_oid(curve_name)
146
+ CURVE_NAME_TO_OID.fetch(curve_name)
147
+ end
148
+
149
+ # ds:CryptoBinary is base64-encoded I2OSP output.
150
+ def crypto_binary_to_integer(base64_text)
151
+ return nil unless base64_text
152
+
153
+ raw = Base64.strict_decode64(base64_text.to_s.gsub(/\s+/, ""))
154
+ raw.bytes.reduce(0) { |acc, byte| (acc << 8) | byte }
155
+ rescue ArgumentError
156
+ nil
157
+ end
158
+
159
+ # Map NamedCurve URN OIDs to OpenSSL curve names (RFC 5480 §2.1).
160
+ CURVE_OID_TO_NAME = {
161
+ "urn:oid:1.2.840.10045.3.1.7" => "prime256v1", # P-256
162
+ "urn:oid:1.3.132.0.34" => "secp384r1", # P-384
163
+ "urn:oid:1.3.132.0.35" => "secp521r1", # P-521
164
+ }.freeze
165
+ private_constant :CURVE_OID_TO_NAME
166
+
167
+ def curve_name_for(uri)
168
+ CURVE_OID_TO_NAME[uri]
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ # Generic algorithm method element. Used for CanonicalizationMethod and
7
+ # SignatureMethod, both of which are `<Foo Algorithm="uri" />` shape.
8
+ class AlgorithmMethod
9
+ attr_accessor :algorithm, :parameters
10
+
11
+ def initialize(algorithm:, parameters: {})
12
+ @algorithm = algorithm
13
+ @parameters = parameters
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class DigestMethod
7
+ attr_accessor :algorithm
8
+
9
+ def initialize(algorithm:)
10
+ @algorithm = algorithm
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # ds:DSAKeyValue — P, Q, G, Y required; J, Seed, PgenCounter optional.
8
+ # Attribute names mirror the W3C spec §4.5.2.1 element names
9
+ # (P, Q, G, Y, J, Seed, PgenCounter).
10
+ class DSAKeyValue
11
+ attr_accessor :p, :q, :g, :y, :j, :seed, :pgen_counter
12
+
13
+ # rubocop:disable-next Naming/MethodParameterName -- P/Q/G/Y/J are W3C spec names
14
+ def initialize(p:, q:, y:, g: nil, j: nil, seed: nil,
15
+ pgen_counter: nil)
16
+ @p = p
17
+ @q = q
18
+ @y = y
19
+ @g = g
20
+ @j = j
21
+ @seed = seed
22
+ @pgen_counter = pgen_counter
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # dsig11:ECKeyValue — NamedCurve URI + PublicKey octets, or
8
+ # explicit ECParameters.
9
+ class ECKeyValue
10
+ attr_accessor :named_curve_uri, :public_key, :ec_parameters
11
+
12
+ def initialize(named_curve_uri: nil, public_key: nil,
13
+ ec_parameters: nil)
14
+ @named_curve_uri = named_curve_uri
15
+ @public_key = public_key
16
+ @ec_parameters = ec_parameters
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # ds:RSAKeyValue — base64-encoded CryptoBinary Modulus + Exponent.
8
+ class RSAKeyValue
9
+ attr_accessor :modulus, :exponent
10
+
11
+ def initialize(modulus:, exponent:)
12
+ @modulus = modulus
13
+ @exponent = exponent
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # ds:X509Data (spec §4.5.4) — container for certificate identifiers.
8
+ # May carry X509IssuerSerial, X509SubjectName, X509SKI, X509Certificate,
9
+ # X509CRL, and dsig11:X509Digest children, all describing the same key.
10
+ class X509Data
11
+ attr_accessor :issuer_serial, :subject_name, :subject_key_id,
12
+ :certificates, :crls, :digests
13
+
14
+ def initialize(issuer_serial: nil, subject_name: nil,
15
+ subject_key_id: nil, certificates: [],
16
+ crls: [], digests: [])
17
+ @issuer_serial = issuer_serial
18
+ @subject_name = subject_name
19
+ @subject_key_id = subject_key_id
20
+ @certificates = Array(certificates)
21
+ @crls = Array(crls)
22
+ @digests = Array(digests)
23
+ end
24
+
25
+ def first_certificate
26
+ certificates.first
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # dsig11:X509Digest — algorithm URI + base64 digest of a cert.
8
+ class X509Digest
9
+ attr_accessor :algorithm, :digest
10
+
11
+ def initialize(algorithm:, digest:)
12
+ @algorithm = algorithm
13
+ @digest = digest
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ module Key
7
+ # ds:X509IssuerSerial — deprecated in favor of X509Digest.
8
+ class X509IssuerSerial
9
+ attr_accessor :issuer_name, :serial_number
10
+
11
+ def initialize(issuer_name:, serial_number:)
12
+ @issuer_name = issuer_name
13
+ @serial_number = serial_number
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class KeyInfo
7
+ attr_accessor :id, :key_name, :key_value, :x509_data,
8
+ :raw_elements
9
+
10
+ def initialize(id: nil, key_name: nil, key_value: nil,
11
+ x509_data: nil, raw_elements: [])
12
+ @id = id
13
+ @key_name = key_name
14
+ @key_value = key_value
15
+ @x509_data = x509_data
16
+ @raw_elements = raw_elements
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class KeyValue
7
+ attr_accessor :rsa_key_value, :dsa_key_value, :ec_key_value,
8
+ :raw_element
9
+
10
+ def initialize(rsa_key_value: nil, dsa_key_value: nil,
11
+ ec_key_value: nil, raw_element: nil)
12
+ @rsa_key_value = rsa_key_value
13
+ @dsa_key_value = dsa_key_value
14
+ @ec_key_value = ec_key_value
15
+ @raw_element = raw_element
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class ObjectElement
7
+ attr_accessor :id, :mime_type, :encoding, :content
8
+
9
+ def initialize(id: nil, mime_type: nil, encoding: nil, content: nil)
10
+ @id = id
11
+ @mime_type = mime_type
12
+ @encoding = encoding
13
+ @content = content
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class Reference
7
+ attr_accessor :id, :uri, :type, :transforms, :digest_method,
8
+ :digest_value
9
+
10
+ def initialize(id: nil, uri: nil, type: nil, transforms: nil,
11
+ digest_method: nil, digest_value: nil)
12
+ @id = id
13
+ @uri = uri
14
+ @type = type
15
+ @transforms = transforms
16
+ @digest_method = digest_method
17
+ @digest_value = digest_value
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class Signature
7
+ attr_accessor :id, :signed_info, :signature_value,
8
+ :key_info, :objects
9
+
10
+ def initialize(id: nil, signed_info: nil, signature_value: nil,
11
+ key_info: nil, objects: [])
12
+ @id = id
13
+ @signed_info = signed_info
14
+ @signature_value = signature_value
15
+ @key_info = key_info
16
+ @objects = objects
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class SignatureValue
7
+ attr_accessor :id, :value
8
+
9
+ def initialize(id: nil, value: nil)
10
+ @id = id
11
+ @value = value
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class SignedInfo
7
+ attr_accessor :id, :canonicalization_method, :signature_method,
8
+ :references
9
+
10
+ def initialize(id: nil, canonicalization_method: nil,
11
+ signature_method: nil, references: [])
12
+ @id = id
13
+ @canonicalization_method = canonicalization_method
14
+ @signature_method = signature_method
15
+ @references = references
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class Transform
7
+ attr_accessor :algorithm, :parameters
8
+
9
+ def initialize(algorithm:, parameters: {})
10
+ @algorithm = algorithm
11
+ @parameters = parameters
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ module Model
6
+ class Transforms
7
+ attr_accessor :transforms
8
+
9
+ def initialize(transforms: [])
10
+ @transforms = Array(transforms)
11
+ end
12
+
13
+ def <<(transform)
14
+ @transforms << transform
15
+ self
16
+ end
17
+
18
+ def each(&block)
19
+ @transforms.each(&block)
20
+ end
21
+
22
+ def empty?
23
+ @transforms.empty?
24
+ end
25
+
26
+ def size
27
+ @transforms.size
28
+ end
29
+
30
+ def length
31
+ @transforms.size
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ module Signature
5
+ # Plain-Ruby-Object model of the W3C ds:Signature schema.
6
+ #
7
+ # Models carry data; they do not (de)serialize themselves. The Serializer
8
+ # walks a model and emits a Moxml document; the Parser walks a Moxml
9
+ # document and constructs a model. This separation keeps the data shape
10
+ # and the wire shape independent.
11
+ module Model
12
+ autoload :Signature, "moxml/signature/model/signature"
13
+ autoload :SignedInfo, "moxml/signature/model/signed_info"
14
+ autoload :Reference, "moxml/signature/model/reference"
15
+ autoload :Transforms, "moxml/signature/model/transforms"
16
+ autoload :Transform, "moxml/signature/model/transform"
17
+ autoload :DigestMethod, "moxml/signature/model/digest_method"
18
+ autoload :AlgorithmMethod, "moxml/signature/model/algorithm_method"
19
+ autoload :SignatureValue, "moxml/signature/model/signature_value"
20
+ autoload :KeyInfo, "moxml/signature/model/key_info"
21
+ autoload :KeyValue, "moxml/signature/model/key_value"
22
+ autoload :ObjectElement, "moxml/signature/model/object_element"
23
+
24
+ module Key
25
+ autoload :X509Data, "moxml/signature/model/key/x509_data"
26
+ autoload :X509IssuerSerial,
27
+ "moxml/signature/model/key/x509_issuer_serial"
28
+ autoload :X509Digest, "moxml/signature/model/key/x509_digest"
29
+ autoload :RSAKeyValue, "moxml/signature/model/key/rsa_key_value"
30
+ autoload :DSAKeyValue, "moxml/signature/model/key/dsa_key_value"
31
+ autoload :ECKeyValue, "moxml/signature/model/key/ec_key_value"
32
+ end
33
+ end
34
+ end
35
+ end