moxml 0.1.25 → 0.1.26

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +9 -0
  3. data/README.adoc +64 -0
  4. data/docs/signature/algorithms.md +108 -0
  5. data/docs/signature/architecture.md +148 -0
  6. data/docs/signature/c14n.md +110 -0
  7. data/docs/signature/examples.md +109 -0
  8. data/docs/signature/flows.md +132 -0
  9. data/docs/signature/quick-reference.md +115 -0
  10. data/docs/signature/security.md +143 -0
  11. data/examples/signature/auto_key_extraction.rb +24 -0
  12. data/examples/signature/enveloped_rsa.rb +45 -0
  13. data/examples/signature/hmac.rb +33 -0
  14. data/lib/moxml/c14n/attribute_handler.rb +71 -0
  15. data/lib/moxml/c14n/character_encoder.rb +29 -0
  16. data/lib/moxml/c14n/data_model.rb +145 -0
  17. data/lib/moxml/c14n/exclusive.rb +188 -0
  18. data/lib/moxml/c14n/inclusive_10.rb +42 -0
  19. data/lib/moxml/c14n/inclusive_11.rb +21 -0
  20. data/lib/moxml/c14n/namespace_context.rb +68 -0
  21. data/lib/moxml/c14n/namespace_handler.rb +71 -0
  22. data/lib/moxml/c14n/node.rb +42 -0
  23. data/lib/moxml/c14n/nodes/attribute_node.rb +50 -0
  24. data/lib/moxml/c14n/nodes/comment_node.rb +29 -0
  25. data/lib/moxml/c14n/nodes/element_node.rb +62 -0
  26. data/lib/moxml/c14n/nodes/namespace_node.rb +41 -0
  27. data/lib/moxml/c14n/nodes/processing_instruction_node.rb +30 -0
  28. data/lib/moxml/c14n/nodes/root_node.rb +22 -0
  29. data/lib/moxml/c14n/nodes/text_node.rb +29 -0
  30. data/lib/moxml/c14n/nodes.rb +17 -0
  31. data/lib/moxml/c14n/processor.rb +118 -0
  32. data/lib/moxml/c14n/writer.rb +121 -0
  33. data/lib/moxml/c14n/xml_base_handler.rb +140 -0
  34. data/lib/moxml/c14n.rb +96 -0
  35. data/lib/moxml/signature/algorithms/base64_transform.rb +40 -0
  36. data/lib/moxml/signature/algorithms/canonicalization_base.rb +87 -0
  37. data/lib/moxml/signature/algorithms/digest_base.rb +51 -0
  38. data/lib/moxml/signature/algorithms/dsa_sha.rb +107 -0
  39. data/lib/moxml/signature/algorithms/ecdsa_sha.rb +125 -0
  40. data/lib/moxml/signature/algorithms/enveloped_signature_transform.rb +79 -0
  41. data/lib/moxml/signature/algorithms/exc_c14n_10.rb +23 -0
  42. data/lib/moxml/signature/algorithms/hmac_sha.rb +117 -0
  43. data/lib/moxml/signature/algorithms/inclusive_c14n_10.rb +21 -0
  44. data/lib/moxml/signature/algorithms/inclusive_c14n_11.rb +23 -0
  45. data/lib/moxml/signature/algorithms/rsa_pkcs1_sha.rb +56 -0
  46. data/lib/moxml/signature/algorithms/sha1.rb +13 -0
  47. data/lib/moxml/signature/algorithms/sha224.rb +13 -0
  48. data/lib/moxml/signature/algorithms/sha256.rb +13 -0
  49. data/lib/moxml/signature/algorithms/sha384.rb +13 -0
  50. data/lib/moxml/signature/algorithms/sha512.rb +13 -0
  51. data/lib/moxml/signature/algorithms/signature_method_base.rb +58 -0
  52. data/lib/moxml/signature/algorithms/transform_base.rb +40 -0
  53. data/lib/moxml/signature/algorithms.rb +113 -0
  54. data/lib/moxml/signature/errors.rb +99 -0
  55. data/lib/moxml/signature/key_extractor.rb +172 -0
  56. data/lib/moxml/signature/model/algorithm_method.rb +18 -0
  57. data/lib/moxml/signature/model/digest_method.rb +15 -0
  58. data/lib/moxml/signature/model/key/dsa_key_value.rb +29 -0
  59. data/lib/moxml/signature/model/key/ec_key_value.rb +22 -0
  60. data/lib/moxml/signature/model/key/rsa_key_value.rb +19 -0
  61. data/lib/moxml/signature/model/key/x509_data.rb +32 -0
  62. data/lib/moxml/signature/model/key/x509_digest.rb +19 -0
  63. data/lib/moxml/signature/model/key/x509_issuer_serial.rb +19 -0
  64. data/lib/moxml/signature/model/key_info.rb +21 -0
  65. data/lib/moxml/signature/model/key_value.rb +20 -0
  66. data/lib/moxml/signature/model/object_element.rb +18 -0
  67. data/lib/moxml/signature/model/reference.rb +22 -0
  68. data/lib/moxml/signature/model/signature.rb +21 -0
  69. data/lib/moxml/signature/model/signature_value.rb +16 -0
  70. data/lib/moxml/signature/model/signed_info.rb +20 -0
  71. data/lib/moxml/signature/model/transform.rb +16 -0
  72. data/lib/moxml/signature/model/transforms.rb +36 -0
  73. data/lib/moxml/signature/model.rb +35 -0
  74. data/lib/moxml/signature/parser.rb +270 -0
  75. data/lib/moxml/signature/reference_resolver.rb +79 -0
  76. data/lib/moxml/signature/reference_result.rb +22 -0
  77. data/lib/moxml/signature/serializer.rb +163 -0
  78. data/lib/moxml/signature/signer.rb +73 -0
  79. data/lib/moxml/signature/single_verification_result.rb +31 -0
  80. data/lib/moxml/signature/transform_pipeline.rb +106 -0
  81. data/lib/moxml/signature/verification_result.rb +27 -0
  82. data/lib/moxml/signature/verifier.rb +129 -0
  83. data/lib/moxml/signature.rb +94 -0
  84. data/lib/moxml/version.rb +1 -1
  85. data/lib/moxml.rb +2 -0
  86. data/reference-docs/w3c-xmldsig-bestpractices.md +216 -0
  87. data/reference-docs/w3c-xmldsig-core.md +400 -0
  88. data/spec/fixtures/xmldsig/keys/rsa_private.pem +28 -0
  89. data/spec/fixtures/xmldsig/keys/rsa_public.pem +9 -0
  90. data/spec/fixtures/xmldsig/keys/rsa_ref.pem +15 -0
  91. data/spec/fixtures/xmldsig/keys/rsa_ref.pub +6 -0
  92. data/spec/fixtures/xmldsig/sign2-doc.xml +6 -0
  93. data/spec/fixtures/xmldsig/sign2-result.xml +25 -0
  94. data/spec/fixtures/xmldsig/sign3-result.xml +39 -0
  95. data/spec/moxml/c14n/api_spec.rb +117 -0
  96. data/spec/moxml/c14n/c14n_spec.rb +88 -0
  97. data/spec/moxml/c14n/comments_pis_spec.rb +65 -0
  98. data/spec/moxml/c14n/inclusive10_spec.rb +60 -0
  99. data/spec/moxml/c14n/namespace_edge_cases_spec.rb +88 -0
  100. data/spec/moxml/c14n/xml_attributes_spec.rb +54 -0
  101. data/spec/moxml/signature/algorithms/base64_transform_spec.rb +26 -0
  102. data/spec/moxml/signature/algorithms/digest_base_spec.rb +72 -0
  103. data/spec/moxml/signature/algorithms/dsa_sha_spec.rb +46 -0
  104. data/spec/moxml/signature/algorithms/ecdsa_sha_spec.rb +72 -0
  105. data/spec/moxml/signature/algorithms/enveloped_signature_transform_spec.rb +40 -0
  106. data/spec/moxml/signature/algorithms/hmac_sha_spec.rb +71 -0
  107. data/spec/moxml/signature/algorithms/rsa_pkcs1_sha_spec.rb +55 -0
  108. data/spec/moxml/signature/algorithms_spec.rb +76 -0
  109. data/spec/moxml/signature/cross_verify_spec.rb +64 -0
  110. data/spec/moxml/signature/edge_cases_spec.rb +284 -0
  111. data/spec/moxml/signature/fixtures_spec.rb +80 -0
  112. data/spec/moxml/signature/key_extractor_spec.rb +96 -0
  113. data/spec/moxml/signature/model_spec.rb +54 -0
  114. data/spec/moxml/signature/round_trip_spec.rb +113 -0
  115. metadata +111 -2
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "base64"
5
+
6
+ module Moxml
7
+ # W3C XML Signature (xmldsig-core-1.1) processing for any moxml adapter.
8
+ #
9
+ # All XML operations flow through Moxml::Document / Moxml::Element; the
10
+ # signature module never touches the underlying adapter (Nokogiri, Oga,
11
+ # REXML, Ox, LibXML) directly.
12
+ module Signature
13
+ DSIG_NS = "http://www.w3.org/2000/09/xmldsig#"
14
+ DSIG11_NS = "http://www.w3.org/2009/xmldsig11#"
15
+ DSIG_MORE_NS = "http://www.w3.org/2001/04/xmldsig-more#"
16
+
17
+ autoload :Error, "moxml/signature/errors"
18
+ autoload :SignatureError, "moxml/signature/errors"
19
+ autoload :UnknownAlgorithm, "moxml/signature/errors"
20
+ autoload :DuplicateAlgorithm, "moxml/signature/errors"
21
+ autoload :SigningError, "moxml/signature/errors"
22
+ autoload :VerificationError, "moxml/signature/errors"
23
+ autoload :ReferenceDigestMismatch, "moxml/signature/errors"
24
+ autoload :SignatureValueMismatch, "moxml/signature/errors"
25
+ autoload :TransformError, "moxml/signature/errors"
26
+ autoload :CanonicalizationError, "moxml/signature/errors"
27
+ autoload :MalformedSignatureError, "moxml/signature/errors"
28
+ autoload :SignatureKeyError, "moxml/signature/errors"
29
+
30
+ autoload :Algorithms, "moxml/signature/algorithms"
31
+ autoload :C14n, "moxml/c14n"
32
+ autoload :Model, "moxml/signature/model"
33
+ autoload :Serializer, "moxml/signature/serializer"
34
+ autoload :Parser, "moxml/signature/parser"
35
+ autoload :ReferenceResolver, "moxml/signature/reference_resolver"
36
+ autoload :Signer, "moxml/signature/signer"
37
+ autoload :Verifier, "moxml/signature/verifier"
38
+ autoload :KeyExtractor, "moxml/signature/key_extractor"
39
+ autoload :TransformPipeline, "moxml/signature/transform_pipeline"
40
+ autoload :VerificationResult, "moxml/signature/verification_result"
41
+ autoload :SingleVerificationResult,
42
+ "moxml/signature/single_verification_result"
43
+ autoload :ReferenceResult, "moxml/signature/reference_result"
44
+
45
+ class << self
46
+ def sign(context:, document:, key:, **options)
47
+ signature = build_signature(context: context, document: document, **options)
48
+ Signer.new(
49
+ context: context,
50
+ signature: signature,
51
+ document: document,
52
+ key: key,
53
+ ).sign
54
+ signature
55
+ end
56
+
57
+ def verify(context:, document:, key: nil, **options)
58
+ Verifier.new(context: context, document: document, key: key, **options).verify
59
+ end
60
+
61
+ private
62
+
63
+ def build_signature(**opts)
64
+ _context = opts[:context]
65
+ _document = opts[:document]
66
+ signed_info = Model::SignedInfo.new(
67
+ canonicalization_method: Model::AlgorithmMethod.new(
68
+ algorithm: opts[:canonicalization_method],
69
+ ),
70
+ signature_method: Model::AlgorithmMethod.new(
71
+ algorithm: opts[:signature_method],
72
+ ),
73
+ references: [
74
+ Model::Reference.new(
75
+ uri: opts[:reference_uri],
76
+ transforms: Model::Transforms.new(
77
+ transforms: opts[:transforms].map do |transform|
78
+ Model::Transform.new(algorithm: transform)
79
+ end,
80
+ ),
81
+ digest_method: Model::DigestMethod.new(algorithm: opts[:digest_method]),
82
+ ),
83
+ ],
84
+ )
85
+
86
+ Model::Signature.new(
87
+ id: opts[:signature_id],
88
+ signed_info: signed_info,
89
+ key_info: opts[:key_info],
90
+ )
91
+ end
92
+ end
93
+ end
94
+ end
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.1.25"
4
+ VERSION = "0.1.26"
5
5
  end
data/lib/moxml.rb CHANGED
@@ -89,6 +89,8 @@ module Moxml
89
89
  autoload :Adapter, "moxml/adapter"
90
90
  autoload :XPath, "moxml/xpath"
91
91
  autoload :SAX, "moxml/sax"
92
+ autoload :Signature, "moxml/signature"
93
+ autoload :C14n, "moxml/c14n"
92
94
 
93
95
  # Error hierarchy — each subclass autoloads from the same file
94
96
  autoload :Error, "moxml/error"
@@ -0,0 +1,216 @@
1
+ # XML Signature Best Practices
2
+
3
+ W3C Working Group Note 11 April 2013
4
+
5
+ - This version: http://www.w3.org/TR/2013/NOTE-xmldsig-bestpractices-20130411/
6
+ - Latest published version: http://www.w3.org/TR/xmldsig-bestpractices/
7
+ - Latest editor's draft: http://www.w3.org/2008/xmlsec/Drafts/best-practices/Overview.html
8
+ - Previous version: http://www.w3.org/TR/2013/NOTE-xmldsig-bestpractices-20130124/
9
+ - Editors: Frederick Hirsch (Nokia), Pratik Datta (Oracle)
10
+
11
+ Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
12
+
13
+ ## Abstract
14
+
15
+ This document collects best practices for implementers and users of the XML
16
+ Signature specification [XMLDSIG-CORE1]. Most of these best practices are
17
+ related to improving security and mitigating attacks, yet others are for best
18
+ practices in the practical use of XML Signature, such as signing XML that
19
+ doesn't use namespaces, for example.
20
+
21
+ ## 1. Overview
22
+
23
+ The XML Signature specification [XMLDSIG-CORE1] offers powerful and flexible
24
+ mechanisms to support a variety of use cases. This flexibility has the downside
25
+ of increasing the number of possible attacks. One countermeasure to the
26
+ increased number of threats is to follow best practices, including a
27
+ simplification of use of XML Signature where possible.
28
+
29
+ ## 2. Best Practices for Implementers
30
+
31
+ ### 2.1 Reduce the opportunities for denial of service attacks
32
+
33
+ XML Signature may be used in application server systems, where multiple incoming
34
+ messages are being processed simultaneously. In this situation incoming messages
35
+ should be assumed to be possibly hostile with the concern that a single poison
36
+ message could bring down an entire set of web applications and services.
37
+
38
+ **Best Practice 1**: Mitigate denial of service attacks by executing potentially
39
+ dangerous operations only after successfully authenticating the signature.
40
+
41
+ Validate the `ds:Reference` elements for a signature only after establishing
42
+ trust, for example by verifying the key and validating `ds:SignedInfo` first.
43
+
44
+ Recommended order of operations:
45
+
46
+ 1. **Step 1** — fetch the verification key and establish trust in that key.
47
+ 2. **Step 2** — validate `ds:SignedInfo` with that key.
48
+ 3. **Step 3** — validate the references.
49
+
50
+ **Best Practice 2**: Establish trust in the verification/validation key (validate
51
+ X.509 certificates, certificate chains and revocation status).
52
+
53
+ #### 2.1.1 XSLT transform that causes denial of service
54
+
55
+ A nested-loop XSLT can require O(N^4) operations on a document with N elements.
56
+
57
+ **Best Practice 3**: Consider avoiding XSLT Transforms.
58
+
59
+ #### 2.1.2 XSLT transform that executes arbitrary code
60
+
61
+ XSLT user-defined extensions can execute arbitrary code (e.g., shell commands).
62
+
63
+ **Best Practice 4**: When XSLT is required disallow the use of user-defined
64
+ extensions.
65
+
66
+ #### 2.1.3 XPath Filtering transform that causes denial of service
67
+
68
+ A document with N namespaces and N elements produces N×N namespace nodes; an
69
+ XPath Filter evaluates the expression once per node, giving O(N^4) cost.
70
+
71
+ **Best Practice 5**: Try to avoid or limit XPath transforms.
72
+
73
+ #### 2.1.4 XPath selection DoS in streaming mode
74
+
75
+ Wildcard axes (descendant, following, etc.) cause search-context explosion in
76
+ streaming verifiers.
77
+
78
+ **Best Practice 6**: Avoid using "descendant", "descendant-or-self",
79
+ "following-sibling", and "following" axes when using streaming XPaths.
80
+
81
+ #### 2.1.5 Retrieval method that causes an infinite loop
82
+
83
+ `ds:RetrievalMethod` may form cyclic references.
84
+
85
+ **Best Practice 7**: Try to avoid or limit `ds:RetrievalMethod` support with
86
+ `ds:KeyInfo`.
87
+
88
+ #### 2.1.6 Problematic external references
89
+
90
+ External URI references can read sensitive files or trigger side effects on
91
+ other sites.
92
+
93
+ **Best Practice 8**: Control external references (mitigate query parameters,
94
+ unknown URI schemes, inappropriate content).
95
+
96
+ #### 2.1.7 Denial of service caused by too many transforms
97
+
98
+ A reference may carry thousands of C14N transforms.
99
+
100
+ **Best Practice 9**: Limit the number of `ds:Reference` transforms allowed.
101
+
102
+ ### 2.2 Provide a mechanism to determine what was signed
103
+
104
+ **Best Practice 10**: Offer interfaces for the application to learn what was
105
+ signed (return pre-digested data and pre-C14N data).
106
+
107
+ ### 2.3 Be aware of certificate encoding issues
108
+
109
+ **Best Practice 11**: Do not re-encode certificates; use DER when possible with
110
+ the `X509Certificate` element. Re-encoding can break the signature on the
111
+ certificate.
112
+
113
+ ## 3. Best Practices for Applications
114
+
115
+ ### 3.1 Check what is signed
116
+
117
+ **Best Practice 12**: Enable verifier to automate "see what is signed"
118
+ functionality.
119
+
120
+ **Best Practice 13**: When applying XML Signatures using XPath it is recommended
121
+ to always actively verify that the signature protects the intended elements and
122
+ not more or less.
123
+
124
+ **Best Practice 14**: When checking a reference URI, don't just check the name of
125
+ the element (wrapping attack mitigation — also check position).
126
+
127
+ ### 3.2 Prevent replay attacks
128
+
129
+ **Best Practice 15**: Unless impractical, sign all parts of the document.
130
+
131
+ **Best Practice 16**: Use a nonce in combination with signing time.
132
+
133
+ **Best Practice 17**: Do not rely on application logic to prevent replay attacks
134
+ since applications may change.
135
+
136
+ **Best Practice 18**: Nonce and signing time must be signature protected.
137
+
138
+ ### 3.3 Enable Long-Lived Signatures
139
+
140
+ **Best Practice 19**: Use Timestamp tokens issued by Timestamp authorities for
141
+ long lived signatures.
142
+
143
+ **Best Practice 20**: Long lived signatures should include a `xsd:dateTime` field
144
+ to indicate the time of signing.
145
+
146
+ ### 3.4 Signing XML without namespace information ("legacy XML")
147
+
148
+ **Best Practice 21**: When creating an enveloping signature over XML without
149
+ namespace information, take steps to avoid having that content inherit the XML
150
+ Signature namespace (insert an empty default namespace declaration, or define a
151
+ namespace prefix for the Signature namespace).
152
+
153
+ ### 3.5 Prefer the XPath Filter 2 Transform
154
+
155
+ **Best Practice 22**: Prefer the XPath Filter 2 Transform to the XPath Filter
156
+ Transform if possible.
157
+
158
+ ## 4. Best Practices for Signers and Verifiers
159
+
160
+ ### 4.1 Do not transmit external unparsed entity references
161
+
162
+ **Best Practice 23**: Do not transmit unparsed external entity references in
163
+ signed material. Expand all entity references before creating the cleartext.
164
+
165
+ ### 4.2 Be aware of schema processing
166
+
167
+ **Best Practice 24**: Do not rely on a validating processor on the consumer's end
168
+ to normalize XML documents.
169
+
170
+ **Best Practice 25**: Avoid destructive validation before signature validation.
171
+
172
+ ### 4.3 HMAC truncation
173
+
174
+ **Best Practice 26**: When using an HMAC, set the HMAC Output Length to one half
175
+ the number of bits in the hash size.
176
+
177
+ ### 4.4 Distinct keys for sign and encrypt
178
+
179
+ **Best Practice 27**: When encrypting and signing use distinct keys.
180
+
181
+ ## 5. Best Practices Summary
182
+
183
+ 1. Mitigate DoS by authenticating before dangerous operations.
184
+ 2. Establish trust in the verification key.
185
+ 3. Avoid XSLT transforms.
186
+ 4. Disallow XSLT user-defined extensions.
187
+ 5. Avoid/limit XPath transforms.
188
+ 6. Avoid wildcard axes in streaming XPaths.
189
+ 7. Avoid/limit `ds:RetrievalMethod`.
190
+ 8. Control external references.
191
+ 9. Limit number of transforms per Reference.
192
+ 10. Offer interfaces to learn what was signed.
193
+ 11. Don't re-encode certificates; prefer DER.
194
+ 12. Enable verifier to "see what is signed".
195
+ 13. With XPath, verify the signature actually protects intended elements.
196
+ 14. When checking reference URI, check both name and position.
197
+ 15. Sign all parts of the document unless impractical.
198
+ 16. Use nonce + signing time.
199
+ 17. Don't rely solely on application logic for replay prevention.
200
+ 18. Nonce and signing time must be signature protected.
201
+ 19. Use TSA-issued timestamp tokens for long-lived signatures.
202
+ 20. Include `xsd:dateTime` for signing time in long-lived signatures.
203
+ 21. Avoid namespace inheritance in enveloping signatures over legacy XML.
204
+ 22. Prefer XPath Filter 2 over XPath Filter.
205
+ 23. Don't transmit unparsed external entity references.
206
+ 24. Don't rely on validating parser on consumer's end.
207
+ 25. Avoid destructive validation before signature validation.
208
+ 26. Truncate HMAC to half hash size.
209
+ 27. Use distinct keys for signing and encryption.
210
+
211
+ ## References
212
+
213
+ - [XMLDSIG-CORE1] — XML Signature Syntax and Processing Version 1.1
214
+ - [XADES] — XML Advanced Electronic Signatures (ETSI TS 101 903)
215
+ - [RFC3161] — Internet X.509 PKI Time-Stamp Protocol (TSP)
216
+ - [MCINTOSH-WRAP] — XML signature element wrapping attacks and countermeasures