Last active
December 19, 2016 13:18
-
-
Save ciihla/54a3c335578235bab35f5ed01a541d3f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
module Akami | |
class WSSE | |
class Signature | |
# For a +Savon::WSSE::Certs+ object. To hold the certs we need to sign. | |
attr_accessor :certs, :digest | |
SHA256DigestAlgorithm = 'http://www.w3.org/2001/04/xmlenc#sha256' | |
RSASHA256SignatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' | |
def initialize(certs = Certs.new, options = {}) | |
@certs = certs | |
@digest = (options[:digest] || 'sha1').upcase | |
end | |
private | |
def signed_info | |
{ | |
'SignedInfo' => { | |
'CanonicalizationMethod/' => nil, | |
'SignatureMethod/' => nil, | |
'Reference' => [ | |
# signed_info_transforms.merge(signed_info_digest_method).merge({ "DigestValue" => timestamp_digest }), | |
signed_info_transforms.merge(signed_info_digest_method).merge('DigestValue' => body_digest) | |
], | |
:attributes! => { | |
'CanonicalizationMethod/' => { 'Algorithm' => ExclusiveXMLCanonicalizationAlgorithm }, | |
'SignatureMethod/' => { 'Algorithm' => Signature.const_get("RSA#{digest}SignatureAlgorithm") }, | |
'Reference' => { 'URI' => ["##{body_id}"] } | |
}, | |
:order! => ['CanonicalizationMethod/', 'SignatureMethod/', 'Reference'] | |
} | |
} | |
end | |
def the_signature | |
raise MissingCertificate, 'Expected a private_key for signing' unless certs.private_key | |
signed_info = at_xpath(@document, '//Envelope/Header/Security/Signature/SignedInfo') | |
signed_info = signed_info ? canonicalize(signed_info) : '' | |
signature = certs.private_key.sign(digest_class.new, signed_info) | |
Base64.encode64(signature).delete("\n") # TODO: DRY calls to Base64.encode64(...).gsub("\n", '') | |
end | |
def body_digest | |
body = canonicalize(at_xpath(@document, '//Envelope/Body')) | |
Base64.encode64(digest_class.digest(body)).strip | |
end | |
def signed_info_digest_method | |
{ 'DigestMethod/' => nil, :attributes! => { 'DigestMethod/' => { 'Algorithm' => Signature.const_get("#{digest}DigestAlgorithm") } } } | |
end | |
def uid | |
digest_class.hexdigest([Time.now, rand].collect(&:to_s).join('/')) | |
end | |
def digest_class | |
"OpenSSL::Digest::#{digest}".constantize | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment