Commit d3caa66

mokha <mo@mokhan.ca>
2019-01-22 21:00:37
add x509 data to key info
1 parent 1ad8d91
lib/xml/kit/templates/key_info.builder
@@ -2,6 +2,10 @@ xml.KeyInfo xmlns: ::Xml::Kit::Namespaces::XMLDSIG do
   xml.KeyName key_name if key_name
   render(key_value, xml: xml) if @key_value
   render(retrieval_method, xml: xml) if @retrieval_method
+  xml.X509Data do
+    xml.X509SKI subject_key_identifier
+    xml.X509Certificate ::Xml::Kit::Certificate.strip(x509_data.to_pem)
+  end if x509_data
   xml.EncryptedKey xmlns: ::Xml::Kit::Namespaces::XMLENC do
     xml.EncryptionMethod Algorithm: algorithm
     xml.CipherData do
lib/xml/kit/key_info.rb
@@ -22,6 +22,7 @@ module Xml
       include Templatable
       attr_reader :algorithm, :cipher_value
       attr_accessor :key_name
+      attr_accessor :x509_data
 
       def initialize(algorithm:, cipher_value:)
         @algorithm = algorithm
@@ -35,6 +36,13 @@ module Xml
       def retrieval_method
         @retrieval_method ||= RetrievalMethod.new
       end
+
+      def subject_key_identifier
+        ski = x509_data.extensions.find { |x| x.oid == "subjectKeyIdentifier" }&.value
+        return if ski.nil?
+
+        Base64.strict_encode64(ski)
+      end
     end
   end
 end
lib/xml/kit/self_signed_certificate.rb
@@ -30,6 +30,12 @@ module Xml
         certificate.public_key = public_key
         certificate.serial = 0x0
         certificate.version = 2
+
+        extension_factory = OpenSSL::X509::ExtensionFactory.new
+        extension_factory.subject_certificate = certificate
+        extension_factory.issuer_certificate = certificate
+        certificate.add_extension(extension_factory.create_extension("subjectKeyIdentifier", "hash", false))
+
         certificate
       end
     end
spec/xml/kit/key_info_spec.rb
@@ -51,5 +51,19 @@ RSpec.describe Xml::Kit::KeyInfo do
       specify { expect(result['KeyInfo']['RetrievalMethod']['URI']).to eql(uri) }
       specify { expect(result['KeyInfo']['RetrievalMethod']['Type']).to eql(type) }
     end
+
+    context "with x509 data" do
+      let(:key_pair) { ::Xml::Kit::KeyPair.generate(use: :encryption) }
+      let(:x509_certificate) { key_pair.certificate.x509 }
+      let(:subject_key_identifier) { x509_certificate.extensions.find { |x| x.oid == "subjectKeyIdentifier" }.value  }
+      let(:result) { Hash.from_xml(subject.to_xml) }
+
+      before do
+        subject.x509_data = x509_certificate
+      end
+
+      specify { expect(result['KeyInfo']['X509Data']['X509SKI']).to eql(Base64.strict_encode64(subject_key_identifier)) }
+      specify { expect(result['KeyInfo']['X509Data']['X509Certificate']).to eql(key_pair.certificate.stripped) }
+    end
   end
 end