Commit 2d34a36

mo <mo.khan@gmail.com>
2017-12-28 17:20:38
move crypto and templating to xml-kit.
1 parent 015370c
exe/saml-kit-create-self-signed-certificate
@@ -3,7 +3,7 @@ require 'saml/kit'
 
 puts "Enter Passphrase:"
 passphrase = STDIN.read.strip
-certificate, private_key = Saml::Kit::SelfSignedCertificate.new(passphrase).create
+certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new(passphrase).create
 
 puts "** BEGIN File Format **"
 print certificate
lib/saml/kit/builders/assertion.rb
@@ -2,7 +2,7 @@ module Saml
   module Kit
     module Builders
       class Assertion
-        include Templatable
+        include XmlTemplatable
         extend Forwardable
 
         def_delegators :@response_builder, :encrypt, :embed_signature, :request, :issuer, :reference_id, :now, :configuration, :user, :version, :destination, :encryption_certificate
lib/saml/kit/builders/authentication_request.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/authentication_request_spec.rb}
       class AuthenticationRequest
-        include Saml::Kit::Templatable
+        include XmlTemplatable
         attr_accessor :id, :now, :issuer, :assertion_consumer_service_url, :name_id_format, :destination
         attr_accessor :version
         attr_reader :configuration
lib/saml/kit/builders/identity_provider_metadata.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/identity_provider_metadata_spec.rb}
       class IdentityProviderMetadata
-        include Saml::Kit::Templatable
+        include XmlTemplatable
         extend Forwardable
         attr_accessor :attributes, :name_id_formats
         attr_accessor :want_authn_requests_signed
lib/saml/kit/builders/logout_request.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/logout_request_spec.rb}
       class LogoutRequest
-        include Saml::Kit::Templatable
+        include XmlTemplatable
         attr_accessor :id, :destination, :issuer, :name_id_format, :now
         attr_accessor :version
         attr_reader :user, :configuration
lib/saml/kit/builders/logout_response.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/logout_response_spec.rb}
       class LogoutResponse
-        include Saml::Kit::Templatable
+        include XmlTemplatable
         attr_accessor :id, :issuer, :version, :status_code, :now, :destination
         attr_reader :request
         attr_reader :configuration
lib/saml/kit/builders/metadata.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/metadata_spec.rb}
       class Metadata
-        include Templatable
+        include XmlTemplatable
 
         attr_accessor :entity_id
         attr_accessor :id
lib/saml/kit/builders/response.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/response_spec.rb}
       class Response
-        include Templatable
+        include XmlTemplatable
         attr_reader :user, :request
         attr_accessor :id, :reference_id, :now
         attr_accessor :version, :status_code
lib/saml/kit/builders/service_provider_metadata.rb
@@ -3,7 +3,7 @@ module Saml
     module Builders
       # {include:file:spec/saml/builders/service_provider_metadata_spec.rb}
       class ServiceProviderMetadata
-        include Saml::Kit::Templatable
+        include XmlTemplatable
         extend Forwardable
         attr_accessor :acs_urls, :logout_urls, :name_id_formats
         attr_accessor :want_assertions_signed
lib/saml/kit/builders.rb
@@ -1,3 +1,4 @@
+require 'saml/kit/xml_templatable'
 require 'saml/kit/builders/assertion'
 require 'saml/kit/builders/authentication_request'
 require 'saml/kit/builders/identity_provider_metadata'
@@ -6,8 +7,6 @@ require 'saml/kit/builders/logout_response'
 require 'saml/kit/builders/metadata'
 require 'saml/kit/builders/response'
 require 'saml/kit/builders/service_provider_metadata'
-require 'saml/kit/builders/xml_encryption'
-require 'saml/kit/builders/xml_signature'
 
 module Saml
   module Kit
lib/saml/kit/configuration.rb
@@ -53,7 +53,7 @@ module Saml
       # @param passphrase [String] the password to decrypt the private key.
       # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
       def add_key_pair(certificate, private_key, passphrase: '', use: :signing)
-        @key_pairs.push(KeyPair.new(certificate, private_key, passphrase, use.to_sym))
+        @key_pairs.push(::Xml::Kit::KeyPair.new(certificate, private_key, passphrase, use.to_sym))
       end
 
       # Generates a unique key pair that can be used for signing or encryption.
@@ -61,7 +61,7 @@ module Saml
       # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
       # @param passphrase [String] the private key passphrase to use.
       def generate_key_pair_for(use:, passphrase: SecureRandom.uuid)
-        certificate, private_key = SelfSignedCertificate.new(passphrase).create
+        certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new(passphrase).create
         add_key_pair(certificate, private_key, passphrase: passphrase, use: use)
       end
 
lib/saml/kit/xml_templatable.rb
@@ -0,0 +1,13 @@
+module Saml
+  module Kit
+    module XmlTemplatable
+      include ::Xml::Kit::Templatable
+
+      def template_path
+        root_path = File.expand_path(File.dirname(__FILE__))
+        template_name = "#{self.class.name.split("::").last.underscore}.builder"
+        File.join(root_path, "builders/templates/", template_name)
+      end
+    end
+  end
+end
lib/saml/kit.rb
@@ -17,7 +17,6 @@ require "xmldsig"
 require "xml/kit"
 
 require "saml/kit/buildable"
-require "saml/kit/templatable"
 require "saml/kit/builders"
 require "saml/kit/namespaces"
 require "saml/kit/serializable"
@@ -33,7 +32,6 @@ require "saml/kit/authentication_request"
 require "saml/kit/bindings"
 require "saml/kit/configuration"
 require "saml/kit/default_registry"
-require "saml/kit/key_pair"
 require "saml/kit/logout_response"
 require "saml/kit/logout_request"
 require "saml/kit/metadata"
@@ -41,11 +39,8 @@ require "saml/kit/composite_metadata"
 require "saml/kit/response"
 require "saml/kit/identity_provider_metadata"
 require "saml/kit/invalid_document"
-require "saml/kit/self_signed_certificate"
 require "saml/kit/service_provider_metadata"
 require "saml/kit/signature"
-require "saml/kit/signatures"
-require "saml/kit/template"
 
 I18n.load_path += Dir[File.expand_path("kit/locales/*.yml", File.dirname(__FILE__))]
 
spec/saml/authentication_request_spec.rb
@@ -80,9 +80,8 @@ RSpec.describe Saml::Kit::AuthenticationRequest do
 
     it 'validates the schema of the request' do
       id = Xml::Kit::Id.generate
-      configuration = Saml::Kit::Configuration.new
-      configuration.generate_key_pair_for(use: :signing)
-      signed_xml = Saml::Kit::Signatures.sign(configuration: configuration) do |xml, signature|
+      key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
+      signed_xml = ::Xml::Kit::Signatures.sign(key_pair: key_pair) do |xml, signature|
         xml.tag!('samlp:AuthnRequest', "xmlns:samlp" => Saml::Kit::Namespaces::PROTOCOL, AssertionConsumerServiceURL: assertion_consumer_service_url, ID: id) do
           signature.template(id)
           xml.Fake do
spec/saml/composite_metadata_spec.rb
@@ -7,10 +7,10 @@ RSpec.describe Saml::Kit::CompositeMetadata do
   let(:sp_logout_service) { FFaker::Internet.uri("https") }
   let(:idp_logout_service) { FFaker::Internet.uri("https") }
   let(:entity_id) { FFaker::Internet.uri("https") }
-  let(:sp_signing_certificate) { Saml::Kit::KeyPair.generate(use: :signing).certificate }
-  let(:sp_encryption_certificate) { Saml::Kit::KeyPair.generate(use: :encryption).certificate }
-  let(:idp_signing_certificate) { Saml::Kit::KeyPair.generate(use: :signing).certificate }
-  let(:idp_encryption_certificate) { Saml::Kit::KeyPair.generate(use: :encryption).certificate }
+  let(:sp_signing_certificate) { ::Xml::Kit::KeyPair.generate(use: :signing).certificate }
+  let(:sp_encryption_certificate) { ::Xml::Kit::KeyPair.generate(use: :encryption).certificate }
+  let(:idp_signing_certificate) { ::Xml::Kit::KeyPair.generate(use: :signing).certificate }
+  let(:idp_encryption_certificate) { ::Xml::Kit::KeyPair.generate(use: :encryption).certificate }
   let(:xml) do
     <<-XML
 <EntityDescriptor xmlns="#{Saml::Kit::Namespaces::METADATA}" ID="#{::Xml::Kit::Id.generate}" entityID="#{entity_id}">
spec/saml/logout_request_spec.rb
@@ -113,9 +113,8 @@ RSpec.describe Saml::Kit::LogoutRequest do
 
     it 'validates the schema of the request' do
       id = Xml::Kit::Id.generate
-      configuration = Saml::Kit::Configuration.new
-      configuration.generate_key_pair_for(use: :signing)
-      signed_xml = Saml::Kit::Signatures.sign(configuration: configuration) do |xml, signature|
+      key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
+      signed_xml = ::Xml::Kit::Signatures.sign(key_pair: key_pair) do |xml, signature|
         xml.LogoutRequest ID: id do
           signature.template(id)
           xml.Fake do
spec/saml/response_spec.rb
@@ -55,9 +55,8 @@ RSpec.describe Saml::Kit::Response do
       allow(registry).to receive(:metadata_for).and_return(metadata)
       allow(metadata).to receive(:matches?).and_return(true)
       id = Xml::Kit::Id.generate
-      configuration = Saml::Kit::Configuration.new
-      configuration.generate_key_pair_for(use: :signing)
-      signed_xml = Saml::Kit::Signatures.sign(configuration: configuration) do |xml, signature|
+      key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
+      signed_xml = ::Xml::Kit::Signatures.sign(key_pair: key_pair) do |xml, signature|
         xml.tag! "samlp:Response", "xmlns:samlp" => Saml::Kit::Namespaces::PROTOCOL, ID: id do
           signature.template(id)
           xml.Fake do
@@ -162,9 +161,7 @@ RSpec.describe Saml::Kit::Response do
     it 'is invalid when there are 2 assertions' do
       id = Xml::Kit::Id.generate
       issuer = FFaker::Internet.uri("https")
-      configuration = Saml::Kit::Configuration.new do |config|
-        config.generate_key_pair_for(use: :signing)
-      end
+      key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
       response_options = {
         ID: id,
         Version: "2.0",
@@ -179,7 +176,7 @@ RSpec.describe Saml::Kit::Response do
         Version: "2.0",
         xmlns: Saml::Kit::Namespaces::ASSERTION,
       }
-      xml = Saml::Kit::Signatures.sign(configuration: configuration) do |xml, signature|
+      xml = ::Xml::Kit::Signatures.sign(key_pair: key_pair) do |xml, signature|
         xml.instruct!
         xml.Response response_options do
           xml.Issuer(issuer, xmlns: Saml::Kit::Namespaces::ASSERTION)
@@ -321,7 +318,7 @@ RSpec.describe Saml::Kit::Response do
     let(:url) { FFaker::Internet.uri("https") }
     let(:certificate) do
       ::Xml::Kit::Certificate.new(
-        Saml::Kit::SelfSignedCertificate.new("password").create[0],
+        ::Xml::Kit::SelfSignedCertificate.new("password").create[0],
         use: :signing
       )
     end
@@ -442,7 +439,7 @@ XML
     end
 
     it 'parses the encrypted assertion' do
-      certificate_pem, private_key_pem = Saml::Kit::SelfSignedCertificate.new(password).create
+      certificate_pem, private_key_pem = ::Xml::Kit::SelfSignedCertificate.new(password).create
       public_key = OpenSSL::X509::Certificate.new(certificate_pem).public_key
       private_key = OpenSSL::PKey::RSA.new(private_key_pem, password)
 
spec/saml/service_provider_metadata_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe Saml::Kit::ServiceProviderMetadata do
     end
 
     it 'returns false when the fingerprint does not match one of the signing certificates' do
-      certificate, _ = Saml::Kit::SelfSignedCertificate.new('password').create
+      certificate, _ = ::Xml::Kit::SelfSignedCertificate.new('password').create
       fingerprint = ::Xml::Kit::Fingerprint.new(certificate)
       expect(subject.matches?(fingerprint)).to be_falsey
     end
lib/saml/kit/builders/templates/certificate.builder → xml-kit/lib/xml/kit/builders/templates/certificate.builder
File renamed without changes
lib/saml/kit/builders/templates/nil_class.builder → xml-kit/lib/xml/kit/builders/templates/nil_class.builder
File renamed without changes
lib/saml/kit/builders/templates/xml_encryption.builder → xml-kit/lib/xml/kit/builders/templates/xml_encryption.builder
File renamed without changes
lib/saml/kit/builders/templates/xml_signature.builder → xml-kit/lib/xml/kit/builders/templates/xml_signature.builder
File renamed without changes
lib/saml/kit/builders/xml_encryption.rb → xml-kit/lib/xml/kit/builders/xml_encryption.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     module Builders
       class XmlEncryption
lib/saml/kit/builders/xml_signature.rb → xml-kit/lib/xml/kit/builders/xml_signature.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     module Builders
       class XmlSignature
@@ -17,22 +17,16 @@ module Saml
           SHA512: "http://www.w3.org/2001/04/xmlenc#sha512",
         }.freeze
 
-        attr_reader :embed_signature, :configuration
-        attr_reader :reference_id
         attr_reader :certificate
+        attr_reader :digest_method
+        attr_reader :reference_id
+        attr_reader :signature_method
 
-        def initialize(reference_id, configuration:, certificate: )
-          @configuration = configuration
-          @reference_id = reference_id
+        def initialize(reference_id, signature_method: :SH256, digest_method: :SHA256, certificate:)
           @certificate = certificate
-        end
-
-        def signature_method
-          SIGNATURE_METHODS[configuration.signature_method]
-        end
-
-        def digest_method
-          DIGEST_METHODS[configuration.digest_method]
+          @digest_method = DIGEST_METHODS[digest_method]
+          @reference_id = reference_id
+          @signature_method = SIGNATURE_METHODS[signature_method]
         end
       end
     end
xml-kit/lib/xml/kit/fingerprint.rb
@@ -2,9 +2,9 @@ module Xml
   module Kit
     # This generates a fingerprint for an X509 Certificate.
     #
-    #   certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
+    #   certificate, _ = Xml::Kit::SelfSignedCertificate.new("password").create
     #
-    #   puts Saml::Kit::Fingerprint.new(certificate).to_s
+    #   puts Xml::Kit::Fingerprint.new(certificate).to_s
     #   # B7:AB:DC:BD:4D:23:58:65:FD:1A:99:0C:5F:89:EA:87:AD:F1:D7:83:34:7A:E9:E4:88:12:DD:46:1F:38:05:93
     #
     # {include:file:spec/saml/fingerprint_spec.rb}
lib/saml/kit/key_pair.rb → xml-kit/lib/xml/kit/key_pair.rb
@@ -1,11 +1,11 @@
-module Saml
+module Xml
   module Kit
     class KeyPair # :nodoc:
       attr_reader :certificate, :private_key, :use
 
       def initialize(certificate, private_key, passphrase, use)
         @use = use
-        @certificate = Xml::Kit::Certificate.new(certificate, use: use)
+        @certificate = ::Xml::Kit::Certificate.new(certificate, use: use)
         @private_key = OpenSSL::PKey::RSA.new(private_key, passphrase)
       end
 
@@ -21,7 +21,7 @@ module Saml
       # @param use [Symbol] Can be either `:signing` or `:encryption`.
       # @param passphrase [String] the passphrase to use to encrypt the private key.
       def self.generate(use:, passphrase: SecureRandom.uuid)
-        certificate, private_key = SelfSignedCertificate.new(passphrase).create
+        certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new(passphrase).create
         new(certificate, private_key, passphrase, use)
       end
     end
lib/saml/kit/self_signed_certificate.rb → xml-kit/lib/xml/kit/self_signed_certificate.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     class SelfSignedCertificate
       SUBJECT="/C=CA/ST=Alberta/L=Calgary/O=SamlKit/OU=SamlKit/CN=SamlKit"
@@ -12,8 +12,8 @@ module Saml
         public_key = rsa_key.public_key
         certificate = OpenSSL::X509::Certificate.new
         certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse(SUBJECT)
-        certificate.not_before = DateTime.now.beginning_of_day
-        certificate.not_after = 30.days.from_now
+        certificate.not_before = Time.now.to_i
+        certificate.not_after = (Date.today + 30).to_time.to_i
         certificate.public_key = public_key
         certificate.serial = 0x0
         certificate.version = 2
lib/saml/kit/signatures.rb → xml-kit/lib/xml/kit/signatures.rb
@@ -1,14 +1,14 @@
-module Saml
+module Xml
   module Kit
     # @!visibility private
     class Signatures # :nodoc:
-      # @!visibility private
-      attr_reader :configuration
+      attr_reader :key_pair, :signature_method, :digest_method
 
       # @!visibility private
-      def initialize(configuration:)
-        @configuration = configuration
-        @key_pair = configuration.key_pairs(use: :signing).last
+      def initialize(key_pair:, signature_method:, digest_method:)
+        @digest_method = digest_method
+        @key_pair = key_pair
+        @signature_method = signature_method
       end
 
       # @!visibility private
@@ -18,21 +18,31 @@ module Saml
 
       # @!visibility private
       def build(reference_id)
-        return nil unless configuration.sign?
-        certificate = @key_pair.certificate
-        Saml::Kit::Builders::XmlSignature.new(reference_id, configuration: configuration, certificate: certificate)
+        return nil if key_pair.nil?
+
+        ::Xml::Kit::Builders::XmlSignature.new(
+          reference_id,
+          certificate: key_pair.certificate,
+          signature_method: signature_method,
+          digest_method: digest_method
+        )
       end
 
       # @!visibility private
       def complete(raw_xml)
-        return raw_xml unless configuration.sign?
-        private_key = @key_pair.private_key
+        return raw_xml if key_pair.nil?
+
+        private_key = key_pair.private_key
         Xmldsig::SignedDocument.new(raw_xml).sign(private_key)
       end
 
       # @!visibility private
-      def self.sign(xml: ::Builder::XmlMarkup.new, configuration: Saml::Kit.configuration)
-        signatures = Saml::Kit::Signatures.new(configuration: configuration)
+      def self.sign(xml: ::Builder::XmlMarkup.new, key_pair:, signature_method: :SHA256, digest_method: :SHA256)
+        signatures = new(
+          key_pair: key_pair,
+          signature_method: signature_method,
+          digest_method: digest_method,
+        )
         yield xml, XmlSignatureTemplate.new(xml, signatures)
         signatures.complete(xml.target!)
       end
lib/saml/kit/templatable.rb → xml-kit/lib/xml/kit/templatable.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     module Templatable
       # Can be used to disable embeding a signature.
@@ -8,7 +8,7 @@ module Saml
 
       # @deprecated Use {#embed_signature=} instead of this method.
       def sign=(value)
-        Saml::Kit.deprecate("sign= is deprecated. Use embed_signature= instead")
+        Xml::Kit.deprecate("sign= is deprecated. Use embed_signature= instead")
         self.embed_signature = value
       end
 
@@ -25,19 +25,24 @@ module Saml
 
       # Allows you to specify which key pair to use for generating an XML digital signature.
       #
-      # @param key_pair [Saml::Kit::KeyPair] the key pair to use for signing.
+      # @param key_pair [Xml::Kit::KeyPair] the key pair to use for signing.
       def sign_with(key_pair)
         signatures.sign_with(key_pair)
       end
 
       # Returns true if an embedded signature is requested and at least one signing certificate is available via the configuration.
       def sign?
-        embed_signature.nil? ? configuration.sign? : embed_signature && configuration.sign?
+        return configuration.sign? if embed_signature.nil?
+        embed_signature && configuration.sign?
       end
 
       # @!visibility private
       def signatures
-        @signatures ||= Saml::Kit::Signatures.new(configuration: configuration)
+        @signatures ||= ::Xml::Kit::Signatures.new(
+          key_pair: configuration.key_pairs(use: :signing).last,
+          digest_method: configuration.digest_method,
+          signature_method: configuration.signature_method,
+        )
       end
 
       # @!visibility private
@@ -46,7 +51,7 @@ module Saml
           temp = ::Builder::XmlMarkup.new
           yield temp
           signed_xml = signatures.complete(temp.target!)
-          xml_encryption = Saml::Kit::Builders::XmlEncryption.new(signed_xml, encryption_certificate.public_key)
+          xml_encryption = ::Xml::Kit::Builders::XmlEncryption.new(signed_xml, encryption_certificate.public_key)
           render(xml_encryption, xml: xml)
         else
           yield xml
@@ -60,7 +65,7 @@ module Saml
 
       # @!visibility private
       def render(model, options)
-        Saml::Kit::Template.new(model).to_xml(options)
+        ::Xml::Kit::Template.new(model).to_xml(options)
       end
     end
   end
lib/saml/kit/template.rb → xml-kit/lib/xml/kit/template.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     class Template
       attr_reader :target
@@ -10,18 +10,17 @@ module Saml
       # Returns the compiled template as a [String].
       #
       # @param options [Hash] The options hash to pass to the template engine.
-      def to_xml(options)
+      def to_xml(options = {})
         template.render(target, options)
       end
 
       private
 
-      def template_name
-        "#{target.class.name.split("::").last.underscore}.builder"
-      end
-
       def template_path
+        return target.template_path if target.respond_to?(:template_path)
+
         root_path = File.expand_path(File.dirname(__FILE__))
+        template_name = "#{target.class.name.split("::").last.underscore}.builder"
         File.join(root_path, "builders/templates/", template_name)
       end
 
xml-kit/lib/xml/kit/xml.rb
@@ -11,7 +11,7 @@ module Xml
       def initialize(raw_xml, namespaces: NAMESPACES)
         @raw_xml = raw_xml
         @namespaces = namespaces
-        @document = Nokogiri::XML(raw_xml)
+        @document = ::Nokogiri::XML(raw_xml)
       end
 
       # Returns the first XML node found by searching the document with the provided XPath.
xml-kit/lib/xml/kit.rb
@@ -1,13 +1,25 @@
 require "active_model"
+require "active_support/core_ext/numeric/time"
 require "base64"
+require "builder"
 require "logger"
+require "nokogiri"
 require "openssl"
+require "tilt"
+require "xmldsig"
 
+require "xml/kit/builders/xml_encryption"
+require "xml/kit/builders/xml_signature"
 require "xml/kit/certificate"
 require "xml/kit/crypto"
 require "xml/kit/fingerprint"
 require "xml/kit/id"
+require "xml/kit/key_pair"
 require "xml/kit/namespaces"
+require "xml/kit/self_signed_certificate"
+require "xml/kit/signatures"
+require "xml/kit/templatable"
+require "xml/kit/template"
 require "xml/kit/version"
 require "xml/kit/xml"
 require "xml/kit/xml_decryption"
xml-kit/spec/fixtures/item.builder
@@ -0,0 +1,4 @@
+xml.instruct!
+xml.Item ID: id do
+  signature_for(reference_id: id, xml: xml)
+end
xml-kit/spec/support/certificate_helper.rb
@@ -1,19 +1,5 @@
 module CertificateHelper
   def generate_key_pair(passphrase)
-    rsa_key = OpenSSL::PKey::RSA.new(2048)
-    public_key = rsa_key.public_key
-    certificate = OpenSSL::X509::Certificate.new
-    subject="/C=CA/ST=Alberta/L=Calgary/O=XmlKit/OU=XmlKit/CN=XmlKit"
-    certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse(subject)
-    certificate.not_before = Time.now.to_i
-    certificate.not_after = (Date.today + 30).to_time.to_i
-    certificate.public_key = public_key
-    certificate.serial = 0x0
-    certificate.version = 2
-    certificate.sign(rsa_key, OpenSSL::Digest::SHA256.new)
-    [
-      certificate.to_pem,
-      rsa_key.to_pem(OpenSSL::Cipher.new('AES-256-CBC'), passphrase)
-    ]
+    ::Xml::Kit::SelfSignedCertificate.new(passphrase).create
   end
 end
spec/saml/signatures_spec.rb → xml-kit/spec/xml/signatures_spec.rb
@@ -1,26 +1,5 @@
-RSpec.describe Saml::Kit::Signatures do
-  let(:configuration) do
-    config = Saml::Kit::Configuration.new
-    config.add_key_pair(certificate, private_key, passphrase: passphrase, use: :signing)
-    config
-  end
-
+RSpec.describe ::Xml::Kit::Signatures do
   let(:reference_id) { Xml::Kit::Id.generate }
-  let(:rsa_key) { OpenSSL::PKey::RSA.new(2048) }
-  let(:public_key) { rsa_key.public_key }
-  let(:certificate) do
-    x = OpenSSL::X509::Certificate.new
-    x.subject = x.issuer = OpenSSL::X509::Name.parse("/C=CA/ST=Alberta/L=Calgary/O=Xsig/OU=Xsig/CN=Xsig")
-    x.not_before = Time.now
-    x.not_after = Time.now + 365 * 24 * 60 * 60
-    x.public_key = public_key
-    x.serial = 0x0
-    x.version = 2
-    x.sign(rsa_key, OpenSSL::Digest::SHA256.new)
-    x.to_pem
-  end
-  let(:private_key) { rsa_key.to_pem(OpenSSL::Cipher.new('des3'), passphrase) }
-  let(:passphrase) { "password" }
 
   it 'generates a signature' do
     options = {
@@ -28,7 +7,8 @@ RSpec.describe Saml::Kit::Signatures do
       "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
       ID: reference_id,
     }
-    signed_xml = described_class.sign(configuration: configuration) do |xml, signature|
+    key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
+    signed_xml = described_class.sign(key_pair: key_pair) do |xml, signature|
       xml.tag!('samlp:AuthnRequest', options) do
         signature.template(reference_id)
         xml.tag!('saml:Issuer', "MyEntityID")
@@ -47,7 +27,7 @@ RSpec.describe Saml::Kit::Signatures do
       { "Algorithm" => "http://www.w3.org/2001/10/xml-exc-c14n#" }
     ])
     expect(signature['SignedInfo']['Reference']['DigestMethod']['Algorithm']).to eql("http://www.w3.org/2001/04/xmlenc#sha256")
-    expected_certificate = certificate.gsub(/\n/, '').gsub(/-----BEGIN CERTIFICATE-----/, '').gsub(/-----END CERTIFICATE-----/, '')
+    expected_certificate = key_pair.certificate.stripped
     expect(signature['KeyInfo']['X509Data']['X509Certificate']).to eql(expected_certificate)
     expect(signature['SignedInfo']['Reference']['DigestValue']).to be_present
     expect(signature['SignatureValue']).to be_present
@@ -55,7 +35,7 @@ RSpec.describe Saml::Kit::Signatures do
   end
 
   it 'does not add a signature' do
-    signed_xml = described_class.sign(configuration: Saml::Kit::Configuration.new) do |xml, signature|
+    signed_xml = described_class.sign(key_pair: nil) do |xml, signature|
       xml.AuthnRequest do
         signature.template(reference_id)
         xml.Issuer "MyEntityID"
xml-kit/spec/xml/xml_spec.rb
@@ -1,22 +1,33 @@
 RSpec.describe Xml::Kit::Xml do
+  class Item
+    include ::Xml::Kit::Templatable
+
+    attr_reader :id, :configuration
+
+    def initialize(configuration)
+      @id = ::Xml::Kit::Id.generate
+      @configuration = configuration
+    end
+
+    def template_path
+      current_path = File.expand_path(File.dirname(__FILE__))
+      File.join(current_path, "../fixtures/item.builder")
+    end
+  end
+
   describe "#valid_signature?" do
     let(:login_url) { "https://#{FFaker::Internet.domain_name}/login" }
     let(:logout_url) { "https://#{FFaker::Internet.domain_name}/logout" }
     let(:configuration) do
-      configuration = Saml::Kit::Configuration.new
-      configuration.generate_key_pair_for(use: :signing)
-      configuration
-    end
-
-    let(:signed_xml) do
-      Saml::Kit::ServiceProviderMetadata.build(configuration: configuration) do |builder|
-        builder.entity_id = FFaker::Movie.title
-        builder.add_assertion_consumer_service(login_url, binding: :http_post)
-        builder.add_assertion_consumer_service(login_url, binding: :http_redirect)
-        builder.add_single_logout_service(logout_url, binding: :http_post)
-        builder.add_single_logout_service(logout_url, binding: :http_redirect)
-      end.to_xml
+      double(
+        :configuration,
+        sign?: true,
+        key_pairs: [::Xml::Kit::KeyPair.generate(use: :signing)],
+        signature_method: :SHA256,
+        digest_method: :SHA256,
+      )
     end
+    let(:signed_xml) { Item.new(configuration).to_xml }
 
     it 'returns true, when the digest and signature is valid' do
       subject = described_class.new(signed_xml)
@@ -24,35 +35,25 @@ RSpec.describe Xml::Kit::Xml do
     end
 
     it 'returns false, when the SHA1 digest is not valid' do
-      subject = described_class.new(signed_xml.gsub("EntityDescriptor", "uhoh"))
+      subject = described_class.new(signed_xml.gsub("Item", "uhoh"))
       expect(subject).to_not be_valid
       expect(subject.errors[:digest_value]).to be_present
     end
 
     it 'it is invalid when digest is incorrect' do
-      old_digest = Hash.from_xml(signed_xml)['EntityDescriptor']['Signature']['SignedInfo']['Reference']['DigestValue']
+      old_digest = Hash.from_xml(signed_xml)['Item']['Signature']['SignedInfo']['Reference']['DigestValue']
+
       subject = described_class.new(signed_xml.gsub(old_digest, 'sabotage'))
       expect(subject).to_not be_valid
       expect(subject.errors[:digest_value]).to be_present
     end
 
     it 'returns false, when the signature is invalid' do
-      old_signature = Hash.from_xml(signed_xml)['EntityDescriptor']['Signature']['SignatureValue']
+      old_signature = Hash.from_xml(signed_xml)['Item']['Signature']['SignatureValue']
       signed_xml.gsub!(old_signature, 'sabotage')
       subject = described_class.new(signed_xml)
       expect(subject).to_not be_valid
       expect(subject.errors[:signature]).to be_present
     end
-
-    it 'is valid' do
-      configuration = Saml::Kit::Configuration.new do |config|
-        5.times { config.generate_key_pair_for(use: :signing) }
-      end
-      signed_xml = Saml::Kit::Metadata.build_xml(configuration: configuration) do |builder|
-        builder.build_identity_provider
-        builder.build_service_provider
-      end
-      expect(described_class.new(signed_xml)).to be_valid
-    end
   end
 end
xml-kit/spec/spec_helper.rb
@@ -1,7 +1,7 @@
 require "bundler/setup"
 require "xml/kit"
 require "ffaker"
-require "saml/kit"
+require "active_support/core_ext/hash/conversions"
 
 Xml::Kit.logger.level = Logger::FATAL
 
xml-kit/xml-kit.gemspec
@@ -22,9 +22,12 @@ Gem::Specification.new do |spec|
   spec.require_paths = ["lib"]
 
   spec.add_dependency "activemodel", ">= 4.2.0"
+  spec.add_dependency "builder", "~> 3.2"
+  spec.add_dependency "nokogiri", "~> 1.8"
+  spec.add_dependency "tilt", "~> 2.0"
+  spec.add_dependency "xmldsig", "~> 0.6"
   spec.add_development_dependency "bundler", "~> 1.16"
   spec.add_development_dependency "ffaker", "~> 2.7"
   spec.add_development_dependency "rake", "~> 10.0"
   spec.add_development_dependency "rspec", "~> 3.0"
-  spec.add_development_dependency "saml-kit", "~> 0.3"
 end