hanko_xml 0.1.0-aarch64-linux → 0.2.0-aarch64-linux
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/CHANGELOG.md +66 -0
- data/README.md +2 -1
- data/lib/hanko_xml/3.1/hanko_xml.so +0 -0
- data/lib/hanko_xml/3.2/hanko_xml.so +0 -0
- data/lib/hanko_xml/3.3/hanko_xml.so +0 -0
- data/lib/hanko_xml/3.4/hanko_xml.so +0 -0
- data/lib/hanko_xml/signer.rb +4 -1
- data/lib/hanko_xml/verifier.rb +10 -3
- data/lib/hanko_xml/version.rb +1 -1
- data/lib/hanko_xml/xades/augmenter.rb +248 -0
- data/lib/hanko_xml/xades/locator.rb +67 -0
- data/lib/hanko_xml/xades/long_term.rb +252 -0
- data/lib/hanko_xml/xades/timestamp.rb +386 -0
- data/lib/hanko_xml/xades/validation_data.rb +115 -0
- data/lib/hanko_xml/xades/verifier.rb +311 -37
- data/lib/hanko_xml/xades.rb +93 -6
- data/sig/hanko_xml/native.rbs +2 -0
- data/sig/hanko_xml/xades.rbs +91 -1
- metadata +7 -2
data/lib/hanko_xml/xades.rb
CHANGED
|
@@ -12,6 +12,10 @@ module HankoXml
|
|
|
12
12
|
module Xades
|
|
13
13
|
NS = "http://uri.etsi.org/01903/v1.3.2#"
|
|
14
14
|
|
|
15
|
+
# XAdES 1.4.1 (EN 319 132-1), the namespace of ArchiveTimeStamp and
|
|
16
|
+
# TimeStampValidationData (#169).
|
|
17
|
+
NS141 = "http://uri.etsi.org/01903/v1.4.1#"
|
|
18
|
+
|
|
15
19
|
# Earlier XAdES namespaces (TS 101 903 v1.1.1, v1.2.2) that Xades::Verifier
|
|
16
20
|
# also reads (#86). Xades::Signer writes only NS.
|
|
17
21
|
LEGACY_NAMESPACES = %w[http://uri.etsi.org/01903/v1.2.2# http://uri.etsi.org/01903/v1.1.1#].freeze
|
|
@@ -70,8 +74,8 @@ module HankoXml
|
|
|
70
74
|
end
|
|
71
75
|
|
|
72
76
|
# The authenticated view of a verified <xades:SignedProperties>
|
|
73
|
-
# (Xades::Verification#signed_properties).
|
|
74
|
-
# (
|
|
77
|
+
# (Xades::Verification#signed_properties). Timestamps are
|
|
78
|
+
# Xades::Verification#signature_timestamps (#163).
|
|
75
79
|
SignedProperties = Struct.new(:signing_time, :signature_policy, :claimed_roles, :data_object_formats,
|
|
76
80
|
keyword_init: true) do
|
|
77
81
|
def initialize(**)
|
|
@@ -88,10 +92,17 @@ module HankoXml
|
|
|
88
92
|
# certificate:), and optionally SignaturePolicyIdentifier, SignerRoleV2
|
|
89
93
|
# and DataObjectFormat.
|
|
90
94
|
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
95
|
+
# With timestamper:, a XAdES-T signature (#162): an RFC 3161 token over
|
|
96
|
+
# the canonicalized <ds:SignatureValue> in a <xades:SignatureTimeStamp>.
|
|
97
|
+
#
|
|
98
|
+
# With validation_data: as well, XAdES-LT (#167): CertificateValues and
|
|
99
|
+
# RevocationValues after the SignatureTimeStamp. Xades::Augmenter adds
|
|
100
|
+
# either to a signature that already exists.
|
|
101
|
+
#
|
|
102
|
+
# Always builds a new <Signature> (template: :build).
|
|
93
103
|
class Signer < HankoXml::Signer
|
|
94
|
-
attr_reader :signing_time, :signature_policy, :claimed_roles, :data_object_format
|
|
104
|
+
attr_reader :signing_time, :signature_policy, :claimed_roles, :data_object_format,
|
|
105
|
+
:timestamper, :timestamp_canonicalization_method, :validation_data
|
|
95
106
|
|
|
96
107
|
# @param certificate [Key, OpenSSL::X509::Certificate, String, Pathname] Required: SigningCertificateV2
|
|
97
108
|
# commits to it.
|
|
@@ -102,9 +113,18 @@ module HankoXml
|
|
|
102
113
|
# of this Signer's own references, which get an Id when they have none.
|
|
103
114
|
# @param signature_id [String, nil] The <Signature> Id; generated when nil, since QualifyingProperties
|
|
104
115
|
# targets it.
|
|
116
|
+
# @param timestamper [#call, nil] Called with a DER RFC 3161 TimeStampReq, returns the TSA's DER
|
|
117
|
+
# TimeStampResp. The library never opens a connection: the callable owns the TSA exchange.
|
|
118
|
+
# @param timestamp_digest_method [Symbol, nil] The imprint digest; nil means digest_method:.
|
|
119
|
+
# @param timestamp_canonicalization_method [Symbol] How <ds:SignatureValue> is canonicalized for the
|
|
120
|
+
# imprint.
|
|
121
|
+
# @param validation_data [ValidationData, Hash, nil] Certificates, CRLs and OCSP responses to embed
|
|
122
|
+
# (XAdES-LT); needs timestamper:, since B-LT builds on B-T.
|
|
105
123
|
# All other keywords are {HankoXml::Signer}'s.
|
|
106
124
|
def initialize(certificate: nil, signing_time: nil, signature_policy: nil, claimed_roles: [],
|
|
107
|
-
data_object_format: nil, signature_id: nil, template: :build,
|
|
125
|
+
data_object_format: nil, signature_id: nil, template: :build, timestamper: nil,
|
|
126
|
+
timestamp_digest_method: nil, timestamp_canonicalization_method: :exc_c14n, validation_data: nil,
|
|
127
|
+
**options, &block)
|
|
108
128
|
unless template.to_sym == :build
|
|
109
129
|
raise HankoXml::ConfigurationError,
|
|
110
130
|
"template: #{template.inspect} is not supported for XAdES; it always builds a new <Signature>"
|
|
@@ -117,6 +137,14 @@ module HankoXml
|
|
|
117
137
|
@signature_policy = coerce_signature_policy(signature_policy)
|
|
118
138
|
@claimed_roles = Array(claimed_roles).map { |role| role.to_s.dup.freeze }.freeze
|
|
119
139
|
@data_object_format = coerce_data_object_format(data_object_format)
|
|
140
|
+
SignatureTimeStamper.check_timestamper!(timestamper)
|
|
141
|
+
@timestamper = timestamper
|
|
142
|
+
@timestamp_digest_method = timestamp_digest_method
|
|
143
|
+
@timestamp_canonicalization_method = timestamp_canonicalization_method
|
|
144
|
+
@validation_data = ValidationData.coerce(validation_data)
|
|
145
|
+
if @validation_data && !timestamper
|
|
146
|
+
raise HankoXml::ConfigurationError, "validation_data: needs timestamper: (XAdES-LT builds on XAdES-T)"
|
|
147
|
+
end
|
|
120
148
|
|
|
121
149
|
super(certificate: certificate, signature_id: signature_id || "xades-#{SecureRandom.hex(8)}",
|
|
122
150
|
template: :build, **options, &block)
|
|
@@ -142,8 +170,37 @@ module HankoXml
|
|
|
142
170
|
"#{signature_id}-signedprops"
|
|
143
171
|
end
|
|
144
172
|
|
|
173
|
+
# The imprint digest: timestamp_digest_method:, or else digest_method:.
|
|
174
|
+
def timestamp_digest_method
|
|
175
|
+
@timestamp_digest_method || digest_method
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def signature_timestamp_id
|
|
179
|
+
"#{signature_id}-sigts"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def to_h
|
|
183
|
+
super.merge(signing_time: signing_time, signature_policy: signature_policy, claimed_roles: claimed_roles,
|
|
184
|
+
data_object_format: data_object_format, timestamper: timestamper,
|
|
185
|
+
timestamp_digest_method: timestamp_digest_method,
|
|
186
|
+
timestamp_canonicalization_method: timestamp_canonicalization_method,
|
|
187
|
+
validation_data: validation_data)
|
|
188
|
+
end
|
|
189
|
+
|
|
145
190
|
private
|
|
146
191
|
|
|
192
|
+
# xmlsec has signed; before the signed values reach the caller's
|
|
193
|
+
# document, obtain the timestamp over the new SignatureValue. A failure
|
|
194
|
+
# raises before anything is written back.
|
|
195
|
+
def write_back_signature(doc, signed_bytes, index, caller_sig_node)
|
|
196
|
+
token = timestamper && SignatureTimeStamper.new(self).token(signed_bytes, index)
|
|
197
|
+
super
|
|
198
|
+
return unless token
|
|
199
|
+
|
|
200
|
+
caller_sig_node.at_xpath(SignatureTimeStamper::ENCAPSULATED_XPATH, "ds" => HankoXml::NS["ds"], "xades" => NS)
|
|
201
|
+
.content = [token].pack("m0")
|
|
202
|
+
end
|
|
203
|
+
|
|
147
204
|
def signed_properties_reference
|
|
148
205
|
HankoXml::Reference.new(uri: "##{signed_properties_id}", type: SIGNED_PROPERTIES_TYPE,
|
|
149
206
|
transforms: [:exc_c14n], digest_method: digest_method)
|
|
@@ -179,6 +236,10 @@ module HankoXml
|
|
|
179
236
|
# Checked with the key material, after the block may have set certificate:.
|
|
180
237
|
def check_key_material!
|
|
181
238
|
super
|
|
239
|
+
if timestamper
|
|
240
|
+
SignatureTimeStamper.check_algorithms!(policy, digest: timestamp_digest_method,
|
|
241
|
+
canonicalization: timestamp_canonicalization_method)
|
|
242
|
+
end
|
|
182
243
|
return if certificate.is_a?(HankoXml::Key) && certificate.certificate?
|
|
183
244
|
|
|
184
245
|
raise HankoXml::ConfigurationError, "XAdES needs certificate:, which SigningCertificateV2 commits to"
|
|
@@ -207,6 +268,7 @@ module HankoXml
|
|
|
207
268
|
|
|
208
269
|
build_signature_properties(xades(signed, "SignedSignatureProperties"))
|
|
209
270
|
build_data_object_properties(signed) if @signer.data_object_format
|
|
271
|
+
build_unsigned_properties(qualifying) if @signer.timestamper
|
|
210
272
|
object
|
|
211
273
|
end
|
|
212
274
|
|
|
@@ -247,6 +309,26 @@ module HankoXml
|
|
|
247
309
|
hash.add_child(element("DigestValue")).content = policy.digest_value
|
|
248
310
|
end
|
|
249
311
|
|
|
312
|
+
# SignatureTimeStamp, then any validation data (#167).
|
|
313
|
+
def build_unsigned_properties(qualifying)
|
|
314
|
+
unsigned = xades(xades(qualifying, "UnsignedProperties"), "UnsignedSignatureProperties")
|
|
315
|
+
build_signature_timestamp(unsigned)
|
|
316
|
+
@signer.validation_data&.append_to(unsigned, @xades_ns)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# The SignatureTimeStamp skeleton: the CanonicalizationMethod is in the
|
|
320
|
+
# document before signing, so xmlsec reads it to canonicalize the
|
|
321
|
+
# SignatureValue (#161), as the verifier will. No Reference covers
|
|
322
|
+
# UnsignedProperties, so filling EncapsulatedTimeStamp afterwards
|
|
323
|
+
# changes nothing signed.
|
|
324
|
+
def build_signature_timestamp(unsigned)
|
|
325
|
+
timestamp = xades(unsigned, "SignatureTimeStamp")
|
|
326
|
+
timestamp["Id"] = @signer.signature_timestamp_id
|
|
327
|
+
method = timestamp.add_child(element("CanonicalizationMethod"))
|
|
328
|
+
method["Algorithm"] = HankoXml::Algorithms.uri_for(:canonicalization, @signer.timestamp_canonicalization_method)
|
|
329
|
+
xades(timestamp, "EncapsulatedTimeStamp")
|
|
330
|
+
end
|
|
331
|
+
|
|
250
332
|
def build_data_object_properties(signed)
|
|
251
333
|
properties = xades(signed, "SignedDataObjectProperties")
|
|
252
334
|
format = @signer.data_object_format
|
|
@@ -284,4 +366,9 @@ module HankoXml
|
|
|
284
366
|
end
|
|
285
367
|
end
|
|
286
368
|
|
|
369
|
+
require_relative "xades/locator"
|
|
370
|
+
require_relative "xades/timestamp"
|
|
371
|
+
require_relative "xades/validation_data"
|
|
372
|
+
require_relative "xades/augmenter"
|
|
373
|
+
require_relative "xades/long_term"
|
|
287
374
|
require_relative "xades/verifier"
|
data/sig/hanko_xml/native.rbs
CHANGED
|
@@ -8,5 +8,7 @@ module HankoXml
|
|
|
8
8
|
def self.sign: (String xml_bytes, String key_pem, Array[String] cert_pems, Array[String] id_attributes, Integer index) -> String
|
|
9
9
|
def self.scan: (String xml_bytes, Array[String] id_attributes, bool strict) -> Hash[Symbol, untyped]
|
|
10
10
|
def self.validate_schema: (String xml_bytes, Integer index, String xsd_path) -> Array[String]
|
|
11
|
+
def self.reference_data: (String xml_bytes, Array[String] trusted_pems, Array[String] id_attributes, Integer index, Array[[String, String]] referenced_documents, bool allow_xpath_filter2) -> Array[String?]
|
|
12
|
+
def self.canonicalize: (String xml_bytes, Integer index, Array[[String, String, Integer?]] target_path, Array[[String, String, Integer?]] method_path) -> String
|
|
11
13
|
end
|
|
12
14
|
end
|
data/sig/hanko_xml/xades.rbs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module HankoXml
|
|
2
2
|
module Xades
|
|
3
3
|
NS: String
|
|
4
|
+
NS141: String
|
|
4
5
|
LEGACY_NAMESPACES: Array[String]
|
|
5
6
|
NAMESPACES: Array[String]
|
|
6
7
|
SIGNED_PROPERTIES_TYPE: String
|
|
@@ -23,11 +24,19 @@ module HankoXml
|
|
|
23
24
|
def initialize: (?mime_type: String?, ?description: String?, ?encoding: String?) -> void
|
|
24
25
|
end
|
|
25
26
|
|
|
27
|
+
# Takes a DER TimeStampReq, returns the TSA's DER TimeStampResp (#162).
|
|
28
|
+
interface _Timestamper
|
|
29
|
+
def call: (String request_der) -> String
|
|
30
|
+
end
|
|
31
|
+
|
|
26
32
|
class Signer < HankoXml::Signer
|
|
27
33
|
attr_reader signing_time: Time?
|
|
28
34
|
attr_reader signature_policy: (SignaturePolicy | :implied)?
|
|
29
35
|
attr_reader claimed_roles: Array[String]
|
|
30
36
|
attr_reader data_object_format: DataObjectFormat?
|
|
37
|
+
attr_reader timestamper: _Timestamper?
|
|
38
|
+
attr_reader timestamp_canonicalization_method: Symbol
|
|
39
|
+
attr_reader validation_data: ValidationData?
|
|
31
40
|
|
|
32
41
|
def initialize: (
|
|
33
42
|
?certificate: (Key | OpenSSL::X509::Certificate | String | _ToPath)?,
|
|
@@ -37,10 +46,52 @@ module HankoXml
|
|
|
37
46
|
?data_object_format: (DataObjectFormat | Hash[Symbol, untyped])?,
|
|
38
47
|
?signature_id: String?,
|
|
39
48
|
?template: Symbol,
|
|
49
|
+
?timestamper: _Timestamper?,
|
|
50
|
+
?timestamp_digest_method: Symbol?,
|
|
51
|
+
?timestamp_canonicalization_method: Symbol,
|
|
52
|
+
?validation_data: (ValidationData | Hash[Symbol, untyped])?,
|
|
40
53
|
**untyped
|
|
41
54
|
) ?{ (self) -> void } -> void
|
|
42
55
|
|
|
43
56
|
def signed_properties_id: () -> String
|
|
57
|
+
def signature_timestamp_id: () -> String
|
|
58
|
+
def timestamp_digest_method: () -> Symbol
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# XAdES-LT validation material (#167). Embedded, never trusted.
|
|
62
|
+
class ValidationData
|
|
63
|
+
attr_reader certificates: Array[OpenSSL::X509::Certificate]
|
|
64
|
+
attr_reader crls: Array[OpenSSL::X509::CRL]
|
|
65
|
+
attr_reader ocsp_responses: Array[OpenSSL::OCSP::Response]
|
|
66
|
+
|
|
67
|
+
def initialize: (
|
|
68
|
+
?certificates: Array[OpenSSL::X509::Certificate | String | Key],
|
|
69
|
+
?crls: Array[OpenSSL::X509::CRL | String],
|
|
70
|
+
?ocsp_responses: Array[OpenSSL::OCSP::Response | String]
|
|
71
|
+
) -> void
|
|
72
|
+
def self.coerce: ((ValidationData | Hash[Symbol, untyped])? value) -> ValidationData?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Adds a SignatureTimeStamp and XAdES-LT validation data to an existing signature (#167).
|
|
76
|
+
class Augmenter
|
|
77
|
+
attr_reader timestamper: _Timestamper?
|
|
78
|
+
attr_reader timestamp_digest_method: Symbol
|
|
79
|
+
attr_reader timestamp_canonicalization_method: Symbol
|
|
80
|
+
attr_reader validation_data: ValidationData?
|
|
81
|
+
attr_reader archive_timestamp: bool
|
|
82
|
+
attr_reader archive_canonicalization_method: Symbol
|
|
83
|
+
attr_reader policy: Policy
|
|
84
|
+
|
|
85
|
+
def initialize: (
|
|
86
|
+
?timestamper: _Timestamper?,
|
|
87
|
+
?timestamp_digest_method: Symbol,
|
|
88
|
+
?timestamp_canonicalization_method: Symbol,
|
|
89
|
+
?validation_data: (ValidationData | Hash[Symbol, untyped])?,
|
|
90
|
+
?archive_timestamp: bool,
|
|
91
|
+
?archive_canonicalization_method: Symbol,
|
|
92
|
+
?policy: Policy
|
|
93
|
+
) -> void
|
|
94
|
+
def augment: (untyped source, ?signature: Integer?) -> SignedDocument
|
|
44
95
|
end
|
|
45
96
|
end
|
|
46
97
|
end
|
|
@@ -57,12 +108,51 @@ module HankoXml
|
|
|
57
108
|
attr_reader data_object_formats: Array[Hash[Symbol, String?]]
|
|
58
109
|
end
|
|
59
110
|
|
|
111
|
+
class SignatureTimeStamp
|
|
112
|
+
attr_reader id: String?
|
|
113
|
+
attr_reader time: Time
|
|
114
|
+
attr_reader serial_number: Integer
|
|
115
|
+
attr_reader tsa_certificate: OpenSSL::X509::Certificate?
|
|
116
|
+
attr_reader digest_method: String
|
|
117
|
+
attr_reader policy_id: String?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# The revocation evidence a chain certificate passed with (#168).
|
|
121
|
+
class RevocationStatus
|
|
122
|
+
attr_reader certificate: OpenSSL::X509::Certificate
|
|
123
|
+
attr_reader source: :ocsp | :crl
|
|
124
|
+
attr_reader issued_at: Time
|
|
125
|
+
attr_reader status: :good | :revoked_later
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# A passed XAdES-LT validation (#168).
|
|
129
|
+
class LongTermValidation
|
|
130
|
+
attr_reader time: Time
|
|
131
|
+
attr_reader certificate_chain: Array[OpenSSL::X509::Certificate]
|
|
132
|
+
attr_reader revocation: Array[RevocationStatus]
|
|
133
|
+
end
|
|
134
|
+
|
|
60
135
|
class Verification < HankoXml::Verification
|
|
61
136
|
attr_reader signed_properties: SignedProperties?
|
|
137
|
+
attr_reader signature_timestamps: Array[SignatureTimeStamp]?
|
|
138
|
+
attr_reader long_term_validation: LongTermValidation?
|
|
139
|
+
attr_reader archive_timestamps: Array[SignatureTimeStamp]?
|
|
140
|
+
def timestamp_time: () -> Time?
|
|
62
141
|
end
|
|
63
142
|
|
|
64
143
|
class Verifier < HankoXml::Verifier
|
|
65
|
-
|
|
144
|
+
TIMESTAMP_MODES: Array[Symbol]
|
|
145
|
+
LONG_TERM_MODES: Array[Symbol]
|
|
146
|
+
|
|
147
|
+
def initialize: (
|
|
148
|
+
?signature_policy: (SignaturePolicy | Hash[Symbol, untyped] | :implied)?,
|
|
149
|
+
?timestamps: :verify | :require | :ignore,
|
|
150
|
+
?tsa_store: OpenSSL::X509::Store?,
|
|
151
|
+
?tsa_certificates: Array[OpenSSL::X509::Certificate | String | Key]?,
|
|
152
|
+
?long_term: (:verify | :require | :ignore)?,
|
|
153
|
+
?revocation_grace: Numeric,
|
|
154
|
+
**untyped
|
|
155
|
+
) -> void
|
|
66
156
|
def verify: (untyped xml) -> Verification
|
|
67
157
|
def verify_all: (untyped xml) -> Array[Verification]
|
|
68
158
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hanko_xml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Danimar Ribeiro
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: hanko_xml signs and verifies XML-DSig signatures by binding to libxmlsec1
|
|
14
14
|
through a Rust extension built with Magnus and rb-sys. It works with Nokogiri documents
|
|
@@ -50,6 +50,11 @@ files:
|
|
|
50
50
|
- lib/hanko_xml/verifier.rb
|
|
51
51
|
- lib/hanko_xml/version.rb
|
|
52
52
|
- lib/hanko_xml/xades.rb
|
|
53
|
+
- lib/hanko_xml/xades/augmenter.rb
|
|
54
|
+
- lib/hanko_xml/xades/locator.rb
|
|
55
|
+
- lib/hanko_xml/xades/long_term.rb
|
|
56
|
+
- lib/hanko_xml/xades/timestamp.rb
|
|
57
|
+
- lib/hanko_xml/xades/validation_data.rb
|
|
53
58
|
- lib/hanko_xml/xades/verifier.rb
|
|
54
59
|
- lib/hanko_xml/xml.rb
|
|
55
60
|
- lib/hanko_xml/xmldsig-core-schema.xsd
|