1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# frozen_string_literal: true
module Xml
module Kit
module Templatable
# Can be used to disable embeding a signature.
# By default a signature will be embedded if a signing
# certificate is available.
attr_accessor :embed_signature
# Used to enable/disable encrypting the document.
attr_accessor :encrypt
# The [Xml::Kit::KeyPair] to use for generating a signature.
attr_accessor :signing_key_pair
# The [Xml::Kit::Certificate] that contains the public key to use for encrypting the document.
attr_accessor :encryption_certificate
# Allows you to specify the digest method algorithm. (Default: SHA256)
# A list of digest methods can be found in [Xml::Kit::Signature].
attr_accessor :digest_method
# Allows you to specify the signature method algorithm. (Default: SHA256)
# A list of signature methods can be found in [Xml::Kit::Signature].
attr_accessor :signature_method
# Returns the generated XML document with an XML Digital Signature and XML Encryption.
def to_xml(xml: ::Builder::XmlMarkup.new, pretty: false)
result = signatures.complete(render(self, xml: xml))
pretty ? Nokogiri::XML(result).to_xml(indent: 2) : result
end
# Generates an {#Xml::Kit::EncryptedKey} section. https://www.w3.org/TR/xmlenc-core1/#sec-EncryptedKey
#
# @since 0.3.0
# @param xml [Builder::XmlMarkup] the xml builder instance
# @param id [String] the id of EncryptedKey element
def encrypt_key_for(xml:, id:, key_info: nil)
::Xml::Kit::EncryptedKey.new(
id: id,
asymmetric_cipher: asymmetric_cipher,
symmetric_cipher: symmetric_cipher,
key_info: key_info
).to_xml(xml: xml)
end
# @deprecated Use {#encrypt_data_for} instead of this
def encryption_for(*args, &block)
::Xml::Kit.deprecate(
'encryption_for is deprecated. Use encrypt_data_for instead.'
)
encrypt_data_for(*args, &block)
end
# Generates an {#Xml::Kit::EncryptedData} section. https://www.w3.org/TR/xmlenc-core1/#sec-EncryptedData
#
# @since 0.3.0
# @param xml [Builder::XmlMarkup] the xml builder instance
# @param key_info [Xml::Kit::KeyInfo] the key info to render in the EncryptedData
def encrypt_data_for(xml:, key_info: nil)
return yield xml unless encrypt?
temp = ::Builder::XmlMarkup.new
yield temp
::Xml::Kit::EncryptedData.new(
signatures.complete(temp.target!),
symmetric_cipher: symmetric_cipher,
asymmetric_cipher: asymmetric_cipher,
key_info: key_info
).to_xml(xml: xml)
end
# Provides a default RSA asymmetric cipher. Can be overridden to provide custom ciphers.
#
# @abstract
# @since 0.3.0
def asymmetric_cipher(algorithm: Crypto::RsaCipher::ALGORITHM)
raise Xml::Kit::Error, 'encryption_certificate is not specified.' unless encryption_certificate
@asymmetric_cipher ||= Crypto.cipher_for(
algorithm,
encryption_certificate.public_key
)
end
# Provides a default aes256-cbc symmetric cipher. Can be overridden to provide custom ciphers.
#
# @abstract
# @since 0.3.0
def symmetric_cipher
@symmetric_cipher ||= Crypto::SymmetricCipher.new
end
def render(model, options)
::Xml::Kit::Template.new(model).to_xml(options)
end
def signature_for(reference_id:, xml:)
return unless sign?
signatures.build(reference_id).to_xml(xml: xml)
end
# Allows you to specify which key pair to use for generating an XML digital signature.
#
# @param key_pair [Xml::Kit::KeyPair] the key pair to use for signing.
def sign_with(key_pair, signature_method: :SHA256, digest_method: :SHA256)
self.signing_key_pair = key_pair
self.embed_signature = true
self.signature_method = signature_method
self.digest_method = digest_method
signatures.sign_with(key_pair)
end
# Allows you to specify which public key to use for generating an XML encrypted element.
#
# @param certificate [Xml::Kit::Certificate] the certificate containing the public key to use for encryption.
def encrypt_with(certificate)
self.encrypt = true
self.encryption_certificate = certificate
end
private
def sign?
embed_signature
end
# @!visibility private
def signatures
@signatures ||= ::Xml::Kit::Signatures.new(
key_pair: signing_key_pair,
digest_method: digest_method || :SHA256,
signature_method: signature_method || :SHA256
)
end
# @!visibility private
def encrypt?
encrypt && encryption_certificate
end
end
end
end
|