main
1# frozen_string_literal: true
2
3require 'xml/kit/key_info/key_value'
4require 'xml/kit/key_info/retrieval_method'
5require 'xml/kit/key_info/rsa_key_value'
6
7module Xml
8 module Kit
9 # An implementation of the KeyInfo element.
10 # https://www.w3.org/TR/xmldsig-core1/#sec-KeyInfo
11 #
12 # @since 0.3.0
13 class KeyInfo
14 include Templatable
15 attr_accessor :key_name
16 attr_accessor :x509_data
17 attr_accessor :encrypted_key
18
19 def initialize(x509: nil, encrypted_key: nil)
20 @encrypted_key = encrypted_key
21 @x509_data = x509
22 yield self if block_given?
23 end
24
25 def asymmetric_cipher(algorithm: Crypto::RsaCipher::ALGORITHM)
26 return encrypted_key.asymmetric_cipher if encrypted_key
27
28 if x509_data
29 return Crypto.cipher_for(
30 derive_algorithm_from(x509_data.public_key),
31 x509_data.public_key
32 )
33 end
34
35 super(algorithm: algorithm)
36 end
37
38 def symmetric_cipher
39 return super if encrypted_key.nil?
40
41 encrypted_key.symmetric_cipher
42 end
43
44 def key_value
45 @key_value ||= KeyValue.new
46 end
47
48 def retrieval_method
49 @retrieval_method ||= RetrievalMethod.new
50 end
51
52 def subject_key_identifier
53 ski = x509_data.extensions.find { |x| x.oid == 'subjectKeyIdentifier' }
54 return if ski.nil?
55
56 Base64.strict_encode64(ski.value)
57 end
58
59 private
60
61 def derive_algorithm_from(key)
62 case key
63 when OpenSSL::PKey::RSA
64 "#{::Xml::Kit::Namespaces::XMLENC}rsa-1_5"
65 else
66 raise ::Xml::Kit::Error, "#{key.try(:class)} is not supported"
67 end
68 end
69 end
70 end
71end