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.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +9 -0
- data/.github/workflows/windows.yml +62 -0
- data/Gemfile +3 -1
- data/README.adoc +133 -6
- data/docs/signature/algorithms.md +108 -0
- data/docs/signature/architecture.md +148 -0
- data/docs/signature/c14n.md +110 -0
- data/docs/signature/examples.md +109 -0
- data/docs/signature/flows.md +132 -0
- data/docs/signature/quick-reference.md +115 -0
- data/docs/signature/security.md +143 -0
- data/examples/signature/auto_key_extraction.rb +24 -0
- data/examples/signature/enveloped_rsa.rb +45 -0
- data/examples/signature/hmac.rb +33 -0
- data/lib/compat/opal/moxml_boot.rb +5 -0
- data/lib/moxml/adapter/base.rb +53 -49
- data/lib/moxml/adapter/customized_leptris/declaration.rb +32 -0
- data/lib/moxml/adapter/customized_leptris/doctype.rb +31 -0
- data/lib/moxml/adapter/customized_leptris/entity_reference.rb +12 -0
- data/lib/moxml/adapter/customized_leptris/text_segment.rb +26 -0
- data/lib/moxml/adapter/customized_leptris.rb +16 -0
- data/lib/moxml/adapter/customized_libxml/cdata.rb +3 -12
- data/lib/moxml/adapter/customized_libxml/comment.rb +2 -9
- data/lib/moxml/adapter/customized_libxml/declaration.rb +1 -10
- data/lib/moxml/adapter/customized_libxml/node.rb +8 -0
- data/lib/moxml/adapter/customized_libxml/processing_instruction.rb +2 -10
- data/lib/moxml/adapter/customized_libxml/text.rb +2 -9
- data/lib/moxml/adapter/customized_oga/entity_decoder.rb +37 -0
- data/lib/moxml/adapter/customized_oga/raw_value_override.rb +52 -0
- data/lib/moxml/adapter/customized_oga/xml_generator.rb +4 -34
- data/lib/moxml/adapter/customized_oga.rb +2 -0
- data/lib/moxml/adapter/customized_ox/entity_reference.rb +1 -17
- data/lib/moxml/adapter/customized_rexml/entity_reference.rb +1 -11
- data/lib/moxml/adapter/headed_ox.rb +9 -128
- data/lib/moxml/adapter/leptris.rb +965 -0
- data/lib/moxml/adapter/libxml.rb +131 -99
- data/lib/moxml/adapter/nokogiri.rb +29 -8
- data/lib/moxml/adapter/oga.rb +91 -54
- data/lib/moxml/adapter/ox.rb +93 -137
- data/lib/moxml/adapter/rexml.rb +61 -50
- data/lib/moxml/adapter.rb +2 -1
- data/lib/moxml/attribute.rb +8 -4
- data/lib/moxml/attribute_resolver.rb +189 -0
- data/lib/moxml/c14n/attribute_handler.rb +71 -0
- data/lib/moxml/c14n/character_encoder.rb +29 -0
- data/lib/moxml/c14n/data_model.rb +145 -0
- data/lib/moxml/c14n/exclusive.rb +188 -0
- data/lib/moxml/c14n/inclusive_10.rb +42 -0
- data/lib/moxml/c14n/inclusive_11.rb +21 -0
- data/lib/moxml/c14n/namespace_context.rb +68 -0
- data/lib/moxml/c14n/namespace_handler.rb +71 -0
- data/lib/moxml/c14n/node.rb +42 -0
- data/lib/moxml/c14n/nodes/attribute_node.rb +50 -0
- data/lib/moxml/c14n/nodes/comment_node.rb +29 -0
- data/lib/moxml/c14n/nodes/element_node.rb +62 -0
- data/lib/moxml/c14n/nodes/namespace_node.rb +41 -0
- data/lib/moxml/c14n/nodes/processing_instruction_node.rb +30 -0
- data/lib/moxml/c14n/nodes/root_node.rb +22 -0
- data/lib/moxml/c14n/nodes/text_node.rb +29 -0
- data/lib/moxml/c14n/nodes.rb +17 -0
- data/lib/moxml/c14n/processor.rb +118 -0
- data/lib/moxml/c14n/writer.rb +121 -0
- data/lib/moxml/c14n/xml_base_handler.rb +140 -0
- data/lib/moxml/c14n.rb +96 -0
- data/lib/moxml/config.rb +29 -3
- data/lib/moxml/context.rb +12 -0
- data/lib/moxml/element.rb +29 -12
- data/lib/moxml/entity/reference.rb +28 -0
- data/lib/moxml/entity.rb +125 -0
- data/lib/moxml/node.rb +90 -1
- data/lib/moxml/sax/namespace_splitter.rb +5 -2
- data/lib/moxml/signature/algorithms/base64_transform.rb +40 -0
- data/lib/moxml/signature/algorithms/canonicalization_base.rb +87 -0
- data/lib/moxml/signature/algorithms/digest_base.rb +51 -0
- data/lib/moxml/signature/algorithms/dsa_sha.rb +107 -0
- data/lib/moxml/signature/algorithms/ecdsa_sha.rb +125 -0
- data/lib/moxml/signature/algorithms/enveloped_signature_transform.rb +79 -0
- data/lib/moxml/signature/algorithms/exc_c14n_10.rb +23 -0
- data/lib/moxml/signature/algorithms/hmac_sha.rb +117 -0
- data/lib/moxml/signature/algorithms/inclusive_c14n_10.rb +21 -0
- data/lib/moxml/signature/algorithms/inclusive_c14n_11.rb +23 -0
- data/lib/moxml/signature/algorithms/rsa_pkcs1_sha.rb +56 -0
- data/lib/moxml/signature/algorithms/sha1.rb +13 -0
- data/lib/moxml/signature/algorithms/sha224.rb +13 -0
- data/lib/moxml/signature/algorithms/sha256.rb +13 -0
- data/lib/moxml/signature/algorithms/sha384.rb +13 -0
- data/lib/moxml/signature/algorithms/sha512.rb +13 -0
- data/lib/moxml/signature/algorithms/signature_method_base.rb +58 -0
- data/lib/moxml/signature/algorithms/transform_base.rb +40 -0
- data/lib/moxml/signature/algorithms.rb +113 -0
- data/lib/moxml/signature/errors.rb +99 -0
- data/lib/moxml/signature/key_extractor.rb +172 -0
- data/lib/moxml/signature/model/algorithm_method.rb +18 -0
- data/lib/moxml/signature/model/digest_method.rb +15 -0
- data/lib/moxml/signature/model/key/dsa_key_value.rb +28 -0
- data/lib/moxml/signature/model/key/ec_key_value.rb +22 -0
- data/lib/moxml/signature/model/key/rsa_key_value.rb +19 -0
- data/lib/moxml/signature/model/key/x509_data.rb +32 -0
- data/lib/moxml/signature/model/key/x509_digest.rb +19 -0
- data/lib/moxml/signature/model/key/x509_issuer_serial.rb +19 -0
- data/lib/moxml/signature/model/key_info.rb +21 -0
- data/lib/moxml/signature/model/key_value.rb +20 -0
- data/lib/moxml/signature/model/object_element.rb +18 -0
- data/lib/moxml/signature/model/reference.rb +22 -0
- data/lib/moxml/signature/model/signature.rb +21 -0
- data/lib/moxml/signature/model/signature_value.rb +16 -0
- data/lib/moxml/signature/model/signed_info.rb +20 -0
- data/lib/moxml/signature/model/transform.rb +16 -0
- data/lib/moxml/signature/model/transforms.rb +36 -0
- data/lib/moxml/signature/model.rb +35 -0
- data/lib/moxml/signature/parser.rb +270 -0
- data/lib/moxml/signature/reference_resolver.rb +79 -0
- data/lib/moxml/signature/reference_result.rb +22 -0
- data/lib/moxml/signature/serializer.rb +163 -0
- data/lib/moxml/signature/signer.rb +73 -0
- data/lib/moxml/signature/single_verification_result.rb +31 -0
- data/lib/moxml/signature/transform_pipeline.rb +106 -0
- data/lib/moxml/signature/verification_result.rb +27 -0
- data/lib/moxml/signature/verifier.rb +129 -0
- data/lib/moxml/signature.rb +94 -0
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xml_emitter.rb +71 -0
- data/lib/moxml/xpath/compiler.rb +60 -7
- data/lib/moxml/xpath/parser.rb +22 -15
- data/lib/moxml.rb +5 -0
- data/reference-docs/w3c-xmldsig-bestpractices.md +216 -0
- data/reference-docs/w3c-xmldsig-core.md +400 -0
- data/spec/examples/readme_examples_spec.rb +0 -4
- data/spec/examples/xpath_examples_spec.rb +0 -11
- data/spec/fixtures/xmldsig/keys/rsa_private.pem +28 -0
- data/spec/fixtures/xmldsig/keys/rsa_public.pem +9 -0
- data/spec/fixtures/xmldsig/keys/rsa_ref.pem +15 -0
- data/spec/fixtures/xmldsig/keys/rsa_ref.pub +6 -0
- data/spec/fixtures/xmldsig/sign2-doc.xml +6 -0
- data/spec/fixtures/xmldsig/sign2-result.xml +25 -0
- data/spec/fixtures/xmldsig/sign3-result.xml +39 -0
- data/spec/integration/all_adapters_spec.rb +17 -0
- data/spec/integration/sax_parity_spec.rb +58 -0
- data/spec/integration/shared_examples/edge_cases.rb +0 -10
- data/spec/integration/shared_examples/integration_workflows.rb +0 -10
- data/spec/integration/shared_examples/node_wrappers/attribute_behavior.rb +98 -0
- data/spec/integration/shared_examples/node_wrappers/namespace_behavior.rb +26 -0
- data/spec/integration/shared_examples/node_wrappers/node_behavior.rb +0 -8
- data/spec/moxml/adapter/leptris_spec.rb +75 -0
- data/spec/moxml/adapter/ox_spec.rb +20 -6
- data/spec/moxml/adapter/platform_spec.rb +15 -2
- data/spec/moxml/adapter/shared_examples/adapter_contract.rb +180 -0
- data/spec/moxml/attribute_resolver_spec.rb +108 -0
- data/spec/moxml/c14n/api_spec.rb +117 -0
- data/spec/moxml/c14n/c14n_spec.rb +88 -0
- data/spec/moxml/c14n/comments_pis_spec.rb +65 -0
- data/spec/moxml/c14n/inclusive10_spec.rb +60 -0
- data/spec/moxml/c14n/namespace_edge_cases_spec.rb +88 -0
- data/spec/moxml/c14n/xml_attributes_spec.rb +54 -0
- data/spec/moxml/doctype_spec.rb +1 -1
- data/spec/moxml/entity_spec.rb +76 -0
- data/spec/moxml/node_spec.rb +104 -0
- data/spec/moxml/sax_entity_parity_spec.rb +358 -0
- data/spec/moxml/signature/algorithms/base64_transform_spec.rb +26 -0
- data/spec/moxml/signature/algorithms/digest_base_spec.rb +72 -0
- data/spec/moxml/signature/algorithms/dsa_sha_spec.rb +46 -0
- data/spec/moxml/signature/algorithms/ecdsa_sha_spec.rb +72 -0
- data/spec/moxml/signature/algorithms/enveloped_signature_transform_spec.rb +40 -0
- data/spec/moxml/signature/algorithms/hmac_sha_spec.rb +71 -0
- data/spec/moxml/signature/algorithms/rsa_pkcs1_sha_spec.rb +55 -0
- data/spec/moxml/signature/algorithms_spec.rb +76 -0
- data/spec/moxml/signature/cross_verify_spec.rb +64 -0
- data/spec/moxml/signature/edge_cases_spec.rb +284 -0
- data/spec/moxml/signature/fixtures_spec.rb +80 -0
- data/spec/moxml/signature/key_extractor_spec.rb +96 -0
- data/spec/moxml/signature/model_spec.rb +54 -0
- data/spec/moxml/signature/round_trip_spec.rb +113 -0
- data/spec/moxml/xml_emitter_spec.rb +64 -0
- data/spec/moxml/xpath/axes_spec.rb +72 -0
- data/spec/moxml/xpath/parser_spec.rb +6 -0
- data/spec/moxml/xpath_capabilities_spec.rb +5 -3
- data/spec/performance/benchmark_spec.rb +13 -6
- data/spec/performance/thread_safety_spec.rb +0 -4
- data/spec/spec_helper.rb +5 -1
- metadata +130 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e82117ebd56032bed4f9edffbb2714dec306b7bec52999193ef69fe62835ab9
|
|
4
|
+
data.tar.gz: 824fb9a07952249c2c97e650d5610d90c53ee23f279980aa5987e2a53922d74a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 845a7de92860b25e68353e14efee1cc0015abfdc5a32f526b0baf1c45870e2966c1db6560eb45267a2fd0beab62936063493ac559fcca4317feffdcd0e54042a
|
|
7
|
+
data.tar.gz: 8242097334c0d1287bcc5c61658042e095ca1a34e375ff034c1504b9607f272937d62bd3ded2c439f45e7d6ae71ea58d86f5af37992858ab9a5fbadbe31fe738
|
|
@@ -13,6 +13,14 @@ on:
|
|
|
13
13
|
Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
|
|
14
14
|
required: true
|
|
15
15
|
default: 'skip'
|
|
16
|
+
gated:
|
|
17
|
+
description: |
|
|
18
|
+
Defer rubygems publish to a separate repository_dispatch (do-release) run.
|
|
19
|
+
- false (default): bump + tag + publish in one step.
|
|
20
|
+
- true: bump + tag only; publish when do-release is triggered.
|
|
21
|
+
required: false
|
|
22
|
+
default: false
|
|
23
|
+
type: boolean
|
|
16
24
|
repository_dispatch:
|
|
17
25
|
types: [ do-release ]
|
|
18
26
|
|
|
@@ -21,6 +29,7 @@ jobs:
|
|
|
21
29
|
uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
|
|
22
30
|
with:
|
|
23
31
|
next_version: ${{ github.event.inputs.next_version }}
|
|
32
|
+
gated: ${{ inputs.gated == true }}
|
|
24
33
|
secrets:
|
|
25
34
|
rubygems-api-key: ${{ secrets.LUTAML_CI_RUBYGEMS_API_KEY }}
|
|
26
35
|
pat_token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: windows
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
adapters:
|
|
14
|
+
name: Adapter specs on Windows (libxml)
|
|
15
|
+
runs-on: windows-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v6
|
|
19
|
+
with:
|
|
20
|
+
submodules: "recursive"
|
|
21
|
+
|
|
22
|
+
- name: Set up Ruby
|
|
23
|
+
uses: ruby/setup-ruby@v1
|
|
24
|
+
with:
|
|
25
|
+
ruby-version: "3.3"
|
|
26
|
+
bundler-cache: false
|
|
27
|
+
|
|
28
|
+
- name: Install libxml2 and build tools via MSYS2
|
|
29
|
+
shell: cmd
|
|
30
|
+
run: |
|
|
31
|
+
C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm ^
|
|
32
|
+
mingw-w64-ucrt-x86_64-libxml2 ^
|
|
33
|
+
mingw-w64-ucrt-x86_64-libiconv ^
|
|
34
|
+
mingw-w64-ucrt-x86_64-zlib ^
|
|
35
|
+
mingw-w64-ucrt-x86_64-ragel ^
|
|
36
|
+
mingw-w64-ucrt-x86_64-make ^
|
|
37
|
+
mingw-w64-ucrt-x86_64-gcc
|
|
38
|
+
|
|
39
|
+
- name: Put MSYS2 UCRT64 toolchain on PATH
|
|
40
|
+
shell: pwsh
|
|
41
|
+
run: |
|
|
42
|
+
"PATH=C:\msys64\ucrt64\bin;C:\msys64\usr\bin;$env:PATH" >> $env:GITHUB_ENV
|
|
43
|
+
|
|
44
|
+
- name: Configure libxml-ruby build
|
|
45
|
+
shell: pwsh
|
|
46
|
+
run: |
|
|
47
|
+
bundle config build.libxml-ruby --with-xml2-include=C:/msys64/ucrt64/include/libxml2 --with-xml2-lib=C:/msys64/ucrt64/lib --with-iconv-include=C:/msys64/ucrt64/include --with-iconv-lib=C:/msys64/ucrt64/lib
|
|
48
|
+
|
|
49
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
50
|
+
shell: pwsh
|
|
51
|
+
run: |
|
|
52
|
+
gem install ruby-ll --no-document
|
|
53
|
+
rake vendor:prepare
|
|
54
|
+
|
|
55
|
+
- name: Install dependencies
|
|
56
|
+
run: bundle install --jobs 4
|
|
57
|
+
|
|
58
|
+
- name: Compile vendored native extensions
|
|
59
|
+
run: bundle exec rake vendor:compile
|
|
60
|
+
|
|
61
|
+
- name: Run adapter specs
|
|
62
|
+
run: bundle exec rake spec:adapter
|
data/Gemfile
CHANGED
|
@@ -9,6 +9,7 @@ gemspec
|
|
|
9
9
|
gem "benchmark"
|
|
10
10
|
gem "benchmark-ips"
|
|
11
11
|
gem "get_process_mem"
|
|
12
|
+
gem "leptris", "~> 1.1"
|
|
12
13
|
gem "libxml-ruby", "~> 5.0"
|
|
13
14
|
gem "nokogiri", "~> 1.18"
|
|
14
15
|
gem "openssl", "~> 3.0"
|
|
@@ -30,7 +31,8 @@ gem "rubocop-performance"
|
|
|
30
31
|
gem "rubocop-rake"
|
|
31
32
|
gem "rubocop-rspec"
|
|
32
33
|
gem "simplecov", require: false
|
|
33
|
-
|
|
34
|
+
# stackprof relies on POSIX signals (SIGPROF/sigaction) unavailable on Windows
|
|
35
|
+
gem "stackprof" unless Gem.win_platform?
|
|
34
36
|
gem "tempfile"
|
|
35
37
|
|
|
36
38
|
# Needed by get_process_mem on Windows
|
data/README.adoc
CHANGED
|
@@ -47,12 +47,21 @@ LibXML:: https://github.com/xml4r/libxml-ruby[libxml-ruby], Ruby bindings
|
|
|
47
47
|
for the performant https://github.com/GNOME/libxml2[libxml2] C library.
|
|
48
48
|
Alternative to Nokogiri with similar performance characteristics.
|
|
49
49
|
|
|
50
|
+
Leptris:: https://github.com/leptris/leptris[Leptris], a pure-C99 XML 1.0
|
|
51
|
+
parser with a W3C-conformant XPath 1.0 engine, consumed through the
|
|
52
|
+
https://github.com/leptris/leptris-ruby[leptris-ruby] FFI binding
|
|
53
|
+
(precompiled platform gems — no compilation at install). Fastest on
|
|
54
|
+
every measured operation; requires leptris >= 1.2 for programmatic
|
|
55
|
+
document construction.
|
|
56
|
+
|
|
50
57
|
==== Default adapter selection
|
|
51
58
|
|
|
52
59
|
When no adapter is explicitly specified, Moxml selects one automatically based on
|
|
53
60
|
the runtime environment:
|
|
54
61
|
|
|
55
62
|
. If running on Opal (`RUBY_ENGINE == "opal"`), Oga is used (pure Ruby, no C extensions)
|
|
63
|
+
. Otherwise, if the installed leptris gem supports programmatic document
|
|
64
|
+
construction (`Leptris::XML::Document.create`, leptris >= 1.2), Leptris is used
|
|
56
65
|
. Otherwise, Moxml detects already-loaded XML libraries in this order:
|
|
57
66
|
.. Nokogiri
|
|
58
67
|
.. Ox
|
|
@@ -63,7 +72,7 @@ the runtime environment:
|
|
|
63
72
|
----
|
|
64
73
|
# Automatic detection — picks the best available adapter
|
|
65
74
|
ctx = Moxml.new
|
|
66
|
-
ctx.config.adapter_name # => :
|
|
75
|
+
ctx.config.adapter_name # => :leptris (leptris >= 1.2), :nokogiri otherwise, :oga on Opal
|
|
67
76
|
|
|
68
77
|
# Explicit override — always takes precedence
|
|
69
78
|
ctx = Moxml.new(:ox)
|
|
@@ -80,9 +89,9 @@ The following table summarizes the features supported by each library.
|
|
|
80
89
|
NOTE: The checkmarks indicate support for the feature, while the footnotes
|
|
81
90
|
provide additional context for specific features.
|
|
82
91
|
|
|
83
|
-
[cols="1,1,1,1,1,3"]
|
|
92
|
+
[cols="1,1,1,1,1,1,1,3"]
|
|
84
93
|
|===
|
|
85
|
-
|Feature |Nokogiri |Oga |REXML |LibXML |Ox |HeadedOx
|
|
94
|
+
|Feature |Nokogiri |Oga |REXML |LibXML |Ox |HeadedOx |Leptris
|
|
86
95
|
|
|
87
96
|
|Parsing, serializing
|
|
88
97
|
| ✅
|
|
@@ -91,6 +100,7 @@ provide additional context for specific features.
|
|
|
91
100
|
| ✅
|
|
92
101
|
| ✅
|
|
93
102
|
| ✅
|
|
103
|
+
| ✅
|
|
94
104
|
|
|
95
105
|
|SAX parsing
|
|
96
106
|
| ✅ Full (10/10 events)
|
|
@@ -99,6 +109,7 @@ provide additional context for specific features.
|
|
|
99
109
|
| ✅ Full (10/10 events)
|
|
100
110
|
| ⚠️ Core (4/10 events) See NOTE 7.
|
|
101
111
|
| ⚠️ Core (4/10 events) See NOTE 7.
|
|
112
|
+
| ✅ Full See NOTE 8.
|
|
102
113
|
|
|
103
114
|
|Node manipulation
|
|
104
115
|
| ✅
|
|
@@ -107,6 +118,7 @@ provide additional context for specific features.
|
|
|
107
118
|
| ✅
|
|
108
119
|
| ✅ See NOTE 1.
|
|
109
120
|
| ✅ See NOTE 1.
|
|
121
|
+
| ✅
|
|
110
122
|
|
|
111
123
|
|Basic XPath
|
|
112
124
|
| ✅
|
|
@@ -115,6 +127,8 @@ provide additional context for specific features.
|
|
|
115
127
|
| ✅
|
|
116
128
|
| Uses Ox-specific API `locate`. See NOTE 2.
|
|
117
129
|
| ✅ Full XPath 1.0. See NOTE 3.
|
|
130
|
+
| ✅ Full XPath 1.0 via Moxml's Ruby engine. See NOTE 8.
|
|
131
|
+
|
|
118
132
|
|
|
119
133
|
|XPath with namespaces
|
|
120
134
|
| ✅
|
|
@@ -123,6 +137,7 @@ provide additional context for specific features.
|
|
|
123
137
|
| ✅
|
|
124
138
|
| Uses Ox-specific API `locate`. See NOTE 2.
|
|
125
139
|
| ⚠️ Basic. See NOTE 3.
|
|
140
|
+
| ✅ Full See NOTE 8.
|
|
126
141
|
|
|
127
142
|
|===
|
|
128
143
|
|
|
@@ -139,15 +154,23 @@ NOTE: Ox/HeadedOx SAX: Only core events supported (start_element, end_element,
|
|
|
139
154
|
characters, errors). No separate CDATA, comment, or processing instruction
|
|
140
155
|
events.
|
|
141
156
|
|
|
157
|
+
NOTE: Leptris: XPath is evaluated by Moxml's pure-Ruby XPath 1.0 engine
|
|
158
|
+
(same as HeadedOx) rather than libleptris's native engine, because the
|
|
159
|
+
native engine does not resolve expression prefixes against
|
|
160
|
+
document-declared namespaces. XML declarations, programmatic DOCTYPEs,
|
|
161
|
+
and entity references are value objects stored via NativeAttachment —
|
|
162
|
+
libleptris has no first-class nodes for them.
|
|
163
|
+
|
|
142
164
|
== Adapter comparison
|
|
143
165
|
|
|
144
166
|
=== Feature compatibility matrix
|
|
145
167
|
|
|
146
|
-
[cols="3,1,1,1,1,1,1", options="header"]
|
|
168
|
+
[cols="3,1,1,1,1,1,1,1", options="header"]
|
|
147
169
|
|===
|
|
148
|
-
| Feature/Operation | Nokogiri | Oga | REXML | LibXML | Ox | HeadedOx
|
|
170
|
+
| Feature/Operation | Nokogiri | Oga | REXML | LibXML | Ox | HeadedOx | Leptris
|
|
149
171
|
|
|
150
172
|
| *Core Operations*
|
|
173
|
+
|
|
151
174
|
|
|
|
152
175
|
|
|
|
153
176
|
|
|
|
@@ -162,6 +185,7 @@ events.
|
|
|
162
185
|
| ✅ Full
|
|
163
186
|
| ✅ Full
|
|
164
187
|
| ✅ Full
|
|
188
|
+
| ✅ Full
|
|
165
189
|
|
|
166
190
|
| Parse XML file/IO
|
|
167
191
|
| ✅ Full
|
|
@@ -170,6 +194,7 @@ events.
|
|
|
170
194
|
| ✅ Full
|
|
171
195
|
| ✅ Full
|
|
172
196
|
| ✅ Full
|
|
197
|
+
| ✅ Full
|
|
173
198
|
|
|
174
199
|
| Serialize to XML
|
|
175
200
|
| ✅ Full
|
|
@@ -178,9 +203,12 @@ events.
|
|
|
178
203
|
| ✅ Full
|
|
179
204
|
| ✅ Full
|
|
180
205
|
| ✅ Full
|
|
206
|
+
| ✅ Full
|
|
181
207
|
|
|
182
208
|
| *Element Operations*
|
|
209
|
+
|
|
183
210
|
|
|
|
211
|
+
|
|
184
212
|
|
|
|
185
213
|
|
|
|
186
214
|
|
|
|
@@ -194,6 +222,7 @@ events.
|
|
|
194
222
|
| ✅ Full
|
|
195
223
|
| ✅ Full
|
|
196
224
|
| ✅ Full
|
|
225
|
+
| ✅ Full
|
|
197
226
|
|
|
198
227
|
| Get/set attributes
|
|
199
228
|
| ✅ Full
|
|
@@ -202,6 +231,7 @@ events.
|
|
|
202
231
|
| ✅ Full
|
|
203
232
|
| ✅ Full
|
|
204
233
|
| ✅ Full
|
|
234
|
+
| ✅ Full
|
|
205
235
|
|
|
206
236
|
| Add/remove children
|
|
207
237
|
| ✅ Full
|
|
@@ -210,6 +240,7 @@ events.
|
|
|
210
240
|
| ✅ Full
|
|
211
241
|
| ✅ Full
|
|
212
242
|
| ✅ Full
|
|
243
|
+
| ✅ Full
|
|
213
244
|
|
|
214
245
|
| Replace nodes
|
|
215
246
|
| ✅ Full
|
|
@@ -218,9 +249,12 @@ events.
|
|
|
218
249
|
| ✅ Full
|
|
219
250
|
| ⚠️ Limited^1^
|
|
220
251
|
| ⚠️ Limited^1^
|
|
252
|
+
| ✅ Full
|
|
221
253
|
|
|
222
254
|
| *Namespace Operations*
|
|
255
|
+
|
|
223
256
|
|
|
|
257
|
+
|
|
224
258
|
|
|
|
225
259
|
|
|
|
226
260
|
|
|
|
@@ -234,6 +268,7 @@ events.
|
|
|
234
268
|
| ✅ Full
|
|
235
269
|
| ✅ Full
|
|
236
270
|
| ✅ Full
|
|
271
|
+
| ✅ Full
|
|
237
272
|
|
|
238
273
|
| Default namespaces
|
|
239
274
|
| ✅ Full
|
|
@@ -242,6 +277,7 @@ events.
|
|
|
242
277
|
| ✅ Full
|
|
243
278
|
| ⚠️ Basic
|
|
244
279
|
| ⚠️ Basic
|
|
280
|
+
| ✅ Full
|
|
245
281
|
|
|
246
282
|
| Namespace inheritance
|
|
247
283
|
| ✅ Full
|
|
@@ -250,6 +286,7 @@ events.
|
|
|
250
286
|
| ✅ Full
|
|
251
287
|
| ❌ None
|
|
252
288
|
| ❌ None^5^
|
|
289
|
+
| ✅ Full
|
|
253
290
|
|
|
254
291
|
| Namespaced attributes
|
|
255
292
|
| ✅ Full
|
|
@@ -258,9 +295,12 @@ events.
|
|
|
258
295
|
| ✅ Full
|
|
259
296
|
| ⚠️ Limited
|
|
260
297
|
| ⚠️ Limited^5^
|
|
298
|
+
| ✅ Full
|
|
261
299
|
|
|
262
300
|
| *XPath Queries*
|
|
301
|
+
|
|
263
302
|
|
|
|
303
|
+
|
|
264
304
|
|
|
|
265
305
|
|
|
|
266
306
|
|
|
|
@@ -274,6 +314,7 @@ events.
|
|
|
274
314
|
| ✅ Full
|
|
275
315
|
| ✅ Full
|
|
276
316
|
| ✅ Full
|
|
317
|
+
| ✅ Full
|
|
277
318
|
|
|
278
319
|
| Attribute predicates (`[@id]`)
|
|
279
320
|
| ✅ Full
|
|
@@ -282,6 +323,7 @@ events.
|
|
|
282
323
|
| ✅ Full
|
|
283
324
|
| ⚠️ Existence only^2^
|
|
284
325
|
| ✅ Full
|
|
326
|
+
| ✅ Full
|
|
285
327
|
|
|
286
328
|
| Attribute values (`[@id='123']`)
|
|
287
329
|
| ✅ Full
|
|
@@ -290,6 +332,7 @@ events.
|
|
|
290
332
|
| ✅ Full
|
|
291
333
|
| ❌ None^3^
|
|
292
334
|
| ✅ Full
|
|
335
|
+
| ✅ Full
|
|
293
336
|
|
|
294
337
|
| Logical operators (`[@a and @b]`)
|
|
295
338
|
| ✅ Full
|
|
@@ -298,6 +341,7 @@ events.
|
|
|
298
341
|
| ✅ Full
|
|
299
342
|
| ❌ None
|
|
300
343
|
| ✅ Full
|
|
344
|
+
| ✅ Full
|
|
301
345
|
|
|
302
346
|
| Position predicates (`[1]`, `[last()]`)
|
|
303
347
|
| ✅ Full
|
|
@@ -306,6 +350,7 @@ events.
|
|
|
306
350
|
| ✅ Full
|
|
307
351
|
| ❌ None
|
|
308
352
|
| ✅ Full
|
|
353
|
+
| ✅ Full
|
|
309
354
|
|
|
310
355
|
| Text predicates (`[text()='x']`)
|
|
311
356
|
| ✅ Full
|
|
@@ -314,6 +359,7 @@ events.
|
|
|
314
359
|
| ✅ Full
|
|
315
360
|
| ❌ None
|
|
316
361
|
| ✅ Full
|
|
362
|
+
| ✅ Full
|
|
317
363
|
|
|
318
364
|
| Namespace-aware queries
|
|
319
365
|
| ✅ Full
|
|
@@ -322,6 +368,7 @@ events.
|
|
|
322
368
|
| ✅ Full
|
|
323
369
|
| ❌ None
|
|
324
370
|
| ⚠️ Basic^5^
|
|
371
|
+
| ✅ Full
|
|
325
372
|
|
|
326
373
|
| Parent axis (`..`)
|
|
327
374
|
| ✅ Full
|
|
@@ -330,6 +377,7 @@ events.
|
|
|
330
377
|
| ✅ Full
|
|
331
378
|
| ❌ None
|
|
332
379
|
| ✅ Full
|
|
380
|
+
| ✅ Full
|
|
333
381
|
|
|
334
382
|
| Sibling axes
|
|
335
383
|
| ✅ Full
|
|
@@ -338,6 +386,7 @@ events.
|
|
|
338
386
|
| ✅ Full
|
|
339
387
|
| ❌ None
|
|
340
388
|
| ❌ None^5^
|
|
389
|
+
| ✅ Full
|
|
341
390
|
|
|
342
391
|
| XPath functions (`count()`, etc.)
|
|
343
392
|
| ✅ Full
|
|
@@ -346,9 +395,12 @@ events.
|
|
|
346
395
|
| ✅ Full
|
|
347
396
|
| ❌ None
|
|
348
397
|
| ✅ All 27
|
|
398
|
+
| ✅ All 27
|
|
349
399
|
|
|
350
400
|
| *Special Content*
|
|
401
|
+
|
|
351
402
|
|
|
|
403
|
+
|
|
352
404
|
|
|
|
353
405
|
|
|
|
354
406
|
|
|
|
@@ -362,6 +414,7 @@ events.
|
|
|
362
414
|
| ✅ Full
|
|
363
415
|
| ✅ Full
|
|
364
416
|
| ✅ Full
|
|
417
|
+
| ✅ Full
|
|
365
418
|
|
|
366
419
|
| Comments
|
|
367
420
|
| ✅ Full
|
|
@@ -370,6 +423,7 @@ events.
|
|
|
370
423
|
| ✅ Full
|
|
371
424
|
| ✅ Full
|
|
372
425
|
| ✅ Full
|
|
426
|
+
| ✅ Full
|
|
373
427
|
|
|
374
428
|
| Processing instructions
|
|
375
429
|
| ✅ Full
|
|
@@ -378,6 +432,7 @@ events.
|
|
|
378
432
|
| ✅ Full
|
|
379
433
|
| ✅ Full
|
|
380
434
|
| ✅ Full
|
|
435
|
+
| ✅ Full
|
|
381
436
|
|
|
382
437
|
| DOCTYPE declarations
|
|
383
438
|
| ✅ Full
|
|
@@ -386,9 +441,12 @@ events.
|
|
|
386
441
|
| ✅ Full
|
|
387
442
|
| ✅ Full
|
|
388
443
|
| ✅ Full
|
|
444
|
+
| ⚠️ Value-object sidecar^8^
|
|
389
445
|
|
|
390
446
|
| *Performance*
|
|
447
|
+
|
|
391
448
|
|
|
|
449
|
+
|
|
392
450
|
|
|
|
393
451
|
|
|
|
394
452
|
|
|
|
@@ -402,6 +460,7 @@ events.
|
|
|
402
460
|
| Fast
|
|
403
461
|
| Very Fast
|
|
404
462
|
| Very Fast
|
|
463
|
+
| Fastest
|
|
405
464
|
|
|
406
465
|
| Serialize speed
|
|
407
466
|
| Fast
|
|
@@ -410,6 +469,7 @@ events.
|
|
|
410
469
|
| Medium
|
|
411
470
|
| Very Fast
|
|
412
471
|
| Very Fast
|
|
472
|
+
| Very Fast
|
|
413
473
|
|
|
414
474
|
| Memory usage
|
|
415
475
|
| Good
|
|
@@ -418,6 +478,7 @@ events.
|
|
|
418
478
|
| Good
|
|
419
479
|
| Excellent
|
|
420
480
|
| Excellent
|
|
481
|
+
| Excellent
|
|
421
482
|
|
|
422
483
|
| Thread safety
|
|
423
484
|
| ✅ Yes
|
|
@@ -426,13 +487,15 @@ events.
|
|
|
426
487
|
| ✅ Yes
|
|
427
488
|
| ✅ Yes
|
|
428
489
|
| ✅ Yes
|
|
490
|
+
| ⚠️ One doc per thread^8^
|
|
429
491
|
|===
|
|
430
492
|
+
|
|
431
493
|
^1^ Ox/HeadedOx: Text node replacement may fail in some cases due to internal node structure +
|
|
432
494
|
^2^ Ox: `//book[@id]` works (returns all book elements), but doesn't filter by attribute existence +
|
|
433
495
|
^3^ HeadedOx: Full XPath 1.0 with all 27 functions and 6 axes. Pure Ruby XPath engine on Ox's C parser. 99.20% pass rate. See link:docs/headed-ox.adoc[] +
|
|
434
496
|
^4^ Ox: Use `.find { |el| el["id"] == "123" }` instead of XPath attribute value predicates +
|
|
435
|
-
^5^ HeadedOx limitations: Namespace introspection and 7 axes not implemented. See link:docs/HEADED_OX_LIMITATIONS.md[]
|
|
497
|
+
^5^ HeadedOx limitations: Namespace introspection and 7 axes not implemented. See link:docs/HEADED_OX_LIMITATIONS.md[] +
|
|
498
|
+
^8^ Leptris: XPath runs through Moxml's pure-Ruby XPath 1.0 engine (the native C engine does not resolve expression prefixes against document namespaces); DOCTYPEs and XML declarations are value objects stored via NativeAttachment; libleptris documents are not thread-safe — one document per thread
|
|
436
499
|
|
|
437
500
|
=== Adapter selection guide
|
|
438
501
|
|
|
@@ -559,6 +622,70 @@ ruby examples/api_client/api_client.rb
|
|
|
559
622
|
See the link:examples/README.md[examples README] for complete documentation and
|
|
560
623
|
learning paths.
|
|
561
624
|
|
|
625
|
+
== XML Signature (Moxml::Signature)
|
|
626
|
+
|
|
627
|
+
Moxml includes an XML-implementation-agnostic implementation of W3C XML
|
|
628
|
+
Signature (xmldsig-core-1.1). Sign and verify documents with any moxml
|
|
629
|
+
adapter; the canonicalization engine produces byte-exact output that
|
|
630
|
+
cross-verifies with libxmlsec1.
|
|
631
|
+
|
|
632
|
+
=== Quick start
|
|
633
|
+
|
|
634
|
+
[source,ruby]
|
|
635
|
+
----
|
|
636
|
+
require "moxml"
|
|
637
|
+
require "moxml/signature"
|
|
638
|
+
require "openssl"
|
|
639
|
+
|
|
640
|
+
ctx = Moxml.new(:nokogiri)
|
|
641
|
+
key = OpenSSL::PKey::RSA.generate(2048)
|
|
642
|
+
doc = ctx.parse("<doc><greeting>Hello, World!</greeting></doc>")
|
|
643
|
+
|
|
644
|
+
# Sign
|
|
645
|
+
signature = Moxml::Signature.sign(
|
|
646
|
+
context: ctx, document: doc, key: key,
|
|
647
|
+
signature_method: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
|
|
648
|
+
canonicalization_method: "http://www.w3.org/2001/10/xml-exc-c14n#",
|
|
649
|
+
digest_method: "http://www.w3.org/2001/04/xmlenc#sha256",
|
|
650
|
+
reference_uri: "",
|
|
651
|
+
transforms: ["http://www.w3.org/2000/09/xmldsig#enveloped-signature"],
|
|
652
|
+
)
|
|
653
|
+
serialized = Moxml::Signature::Serializer.new(context: ctx).serialize(signature)
|
|
654
|
+
doc.root.add_child(serialized.root)
|
|
655
|
+
|
|
656
|
+
# Verify (auto-extracts key from KeyInfo if absent)
|
|
657
|
+
result = Moxml::Signature.verify(context: ctx, document: doc, key: key)
|
|
658
|
+
result.valid? # => true
|
|
659
|
+
----
|
|
660
|
+
|
|
661
|
+
=== Supported algorithms
|
|
662
|
+
|
|
663
|
+
Digests:: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
|
|
664
|
+
Signature methods:: RSA-PKCS1v1.5, HMAC, ECDSA (P-256/P-384/P-521), DSA
|
|
665
|
+
Canonicalization:: Exclusive C14N 1.0, Inclusive C14N 1.0, Inclusive C14N 1.1
|
|
666
|
+
Transforms:: base64, Enveloped Signature
|
|
667
|
+
|
|
668
|
+
Adding a custom algorithm means declaring `identifier "http://..."` on a
|
|
669
|
+
subclass — no edits to existing code. See
|
|
670
|
+
link:docs/signature/algorithms.md[the algorithms doc].
|
|
671
|
+
|
|
672
|
+
=== Canonicalization (Moxml::C14n)
|
|
673
|
+
|
|
674
|
+
C14N is a top-level moxml feature (sibling to XPath, Builder, SAX).
|
|
675
|
+
Inclusive C14N is ported from the sibling `canon` gem; Exclusive C14N
|
|
676
|
+
is moxml-native. See link:docs/signature/c14n.md[the C14N doc].
|
|
677
|
+
|
|
678
|
+
=== Documentation
|
|
679
|
+
|
|
680
|
+
* link:docs/signature/architecture.md[Architecture]
|
|
681
|
+
* link:docs/signature/algorithms.md[Algorithm registry]
|
|
682
|
+
* link:docs/signature/c14n.md[Canonicalization]
|
|
683
|
+
* link:docs/signature/flows.md[Signer and Verifier flows]
|
|
684
|
+
* link:docs/signature/key-extraction.md[Key extraction] (TODO)
|
|
685
|
+
* link:docs/signature/security.md[Security considerations]
|
|
686
|
+
* link:docs/signature/quick-reference.md[Quick reference]
|
|
687
|
+
* link:examples/signature/[Runnable examples]
|
|
688
|
+
|
|
562
689
|
== Working with documents
|
|
563
690
|
|
|
564
691
|
=== Using the builder pattern
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Algorithm registry
|
|
2
|
+
|
|
3
|
+
The `Moxml::Signature::Algorithms` module is the open-closed hub for
|
|
4
|
+
all W3C XML Signature algorithms. Algorithms are identified by URI;
|
|
5
|
+
the registry maps URI → class for each of four categories:
|
|
6
|
+
|
|
7
|
+
| Category | W3C spec section | Base class |
|
|
8
|
+
| -------------------- | ---------------- | --------------------------------------------- |
|
|
9
|
+
| `:digest` | §6.2 | `Algorithms::DigestBase` |
|
|
10
|
+
| `:signature_method` | §6.3, §6.4 | `Algorithms::SignatureMethodBase` |
|
|
11
|
+
| `:canonicalization` | §6.5 | `Algorithms::CanonicalizationBase` |
|
|
12
|
+
| `:transform` | §6.6 | `Algorithms::TransformBase` |
|
|
13
|
+
|
|
14
|
+
## Built-in algorithms
|
|
15
|
+
|
|
16
|
+
### Digests (§6.2)
|
|
17
|
+
|
|
18
|
+
| URI | Class |
|
|
19
|
+
| ---------------------------------------------------------- | ---------------- |
|
|
20
|
+
| `http://www.w3.org/2000/09/xmldsig#sha1` | `SHA1` |
|
|
21
|
+
| `http://www.w3.org/2001/04/xmldsig-more#sha224` | `SHA224` |
|
|
22
|
+
| `http://www.w3.org/2001/04/xmlenc#sha256` (REQUIRED) | `SHA256` |
|
|
23
|
+
| `http://www.w3.org/2001/04/xmldsig-more#sha384` | `SHA384` |
|
|
24
|
+
| `http://www.w3.org/2001/04/xmlenc#sha512` | `SHA512` |
|
|
25
|
+
|
|
26
|
+
### Signature methods (§6.3, §6.4)
|
|
27
|
+
|
|
28
|
+
| URI | Class | Notes |
|
|
29
|
+
| ---------------------------------------------------------- | ---------------- | ----- |
|
|
30
|
+
| `…xmldsig#rsa-sha1` | `RsaPkcs1Sha` | Verification only (BP: SHA-1 discouraged) |
|
|
31
|
+
| `…xmldsig-more#rsa-sha224` | `RsaPkcs1Sha` | |
|
|
32
|
+
| `…xmldsig-more#rsa-sha256` (REQUIRED) | `RsaPkcs1Sha` | |
|
|
33
|
+
| `…xmldsig-more#rsa-sha384` | `RsaPkcs1Sha` | |
|
|
34
|
+
| `…xmldsig-more#rsa-sha512` | `RsaPkcs1Sha` | |
|
|
35
|
+
| `…xmldsig#hmac-sha1` | `HmacSha` | Truncation enforced per §4.4.2 |
|
|
36
|
+
| `…xmldsig-more#hmac-sha224` | `HmacSha` | |
|
|
37
|
+
| `…xmldsig-more#hmac-sha256` (REQUIRED) | `HmacSha` | |
|
|
38
|
+
| `…xmldsig-more#hmac-sha384` | `HmacSha` | |
|
|
39
|
+
| `…xmldsig-more#hmac-sha512` | `HmacSha` | |
|
|
40
|
+
| `…xmldsig-more#ecdsa-sha1` | `EcdsaSha` | |
|
|
41
|
+
| `…xmldsig-more#ecdsa-sha224` | `EcdsaSha` | |
|
|
42
|
+
| `…xmldsig-more#ecdsa-sha256` (REQUIRED) | `EcdsaSha` | P-256/P-384/P-521 |
|
|
43
|
+
| `…xmldsig-more#ecdsa-sha384` | `EcdsaSha` | |
|
|
44
|
+
| `…xmldsig-more#ecdsa-sha512` | `EcdsaSha` | |
|
|
45
|
+
| `…xmldsig#dsa-sha1` | `DsaSha` | |
|
|
46
|
+
| `…xmldsig11#dsa-sha256` | `DsaSha` | |
|
|
47
|
+
|
|
48
|
+
### Canonicalization (§6.5)
|
|
49
|
+
|
|
50
|
+
| URI | Engine |
|
|
51
|
+
| ---------------------------------------------------------- | ---------------------------- |
|
|
52
|
+
| `http://www.w3.org/TR/2001/REC-xml-c14n-20010315` | `Moxml::C14n::Inclusive10` (canon-ported) |
|
|
53
|
+
| `…REC-xml-c14n-20010315#WithComments` | same, `with_comments: true` |
|
|
54
|
+
| `http://www.w3.org/2006/12/xml-c14n11` | `Moxml::C14n::Inclusive11` |
|
|
55
|
+
| `…xml-c14n11#WithComments` | same, `with_comments: true` |
|
|
56
|
+
| `http://www.w3.org/2001/10/xml-exc-c14n#` | `Moxml::C14n::Exclusive` (moxml-native) |
|
|
57
|
+
| `…xml-exc-c14n#WithComments` | same, `with_comments: true` |
|
|
58
|
+
|
|
59
|
+
### Transforms (§6.6)
|
|
60
|
+
|
|
61
|
+
| URI | Class |
|
|
62
|
+
| ---------------------------------------------------------- | ------------------------------ |
|
|
63
|
+
| `http://www.w3.org/2000/09/xmldsig#base64` | `Base64Transform` |
|
|
64
|
+
| `http://www.w3.org/2000/09/xmldsig#enveloped-signature` | `EnvelopedSignatureTransform` |
|
|
65
|
+
|
|
66
|
+
Canonicalization algorithms can also be used as transforms per §6.6.1.
|
|
67
|
+
The `TransformPipeline` looks them up in the canonicalization registry
|
|
68
|
+
as a fallback.
|
|
69
|
+
|
|
70
|
+
## Adding a custom algorithm
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
require "moxml/signature"
|
|
74
|
+
|
|
75
|
+
module MyAlgo
|
|
76
|
+
class SHA3_256 < Moxml::Signature::Algorithms::DigestBase
|
|
77
|
+
identifier "http://www.w3.org/2007/xmldsig-more#sha3-256"
|
|
78
|
+
|
|
79
|
+
def compute_digest(data)
|
|
80
|
+
OpenSSL::Digest.digest("SHA3-256", data)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Now the URI resolves:
|
|
86
|
+
Moxml::Signature::Algorithms.lookup(
|
|
87
|
+
:digest,
|
|
88
|
+
"http://www.w3.org/2007/xmldsig-more#sha3-256",
|
|
89
|
+
)
|
|
90
|
+
# => MyAlgo::SHA3_256
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The `identifier` declaration registers the class on load. No edits to
|
|
94
|
+
existing code are required — pure OCP.
|
|
95
|
+
|
|
96
|
+
## API
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
Algorithms.lookup(:digest, uri) # → class, raises UnknownAlgorithm
|
|
100
|
+
Algorithms.registered?(:digest, uri) # → bool
|
|
101
|
+
Algorithms[:digest] # → { uri => class, ... }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Lazy loading
|
|
105
|
+
|
|
106
|
+
The registry autoloads built-in algorithm classes on first lookup
|
|
107
|
+
(`load_builtins!` references each constant, triggering autoload).
|
|
108
|
+
Custom algorithms register themselves on `require` of their file.
|