require 'spec_helper' describe Xmldsig::SignedDocument do let(:signed_xml) { File.read("spec/fixtures/signed.xml") } let(:signed_document) { Xmldsig::SignedDocument.new(signed_xml) } let(:unsigned_xml) { File.read("spec/fixtures/unsigned.xml") } let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) } let(:private_key) { OpenSSL::PKey::RSA.new(File.read("spec/fixtures/key.pem")) } let(:certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate.cer")) } let(:other_certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate2.cer")) } describe "#initialize" do it "sets the document to a nokogiri document" do document = described_class.new(signed_xml) document.document.should be_a(Nokogiri::XML::Document) end it "raises on badly formed XML" do badly_formed = <<-EOXML foo bar EOXML expect { described_class.new(badly_formed) }.to raise_error end it "accepts a nokogiri document" do doc = Nokogiri::XML(unsigned_xml) signed_document = described_class.new(doc) signed_document.document.should be_a(Nokogiri::XML::Document) end end describe "#signatures" do let(:unsigned_xml) { File.read("spec/fixtures/unsigned_nested_signature.xml") } let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) } it "returns only the signed nodes" do signed_document.signatures.should be_all { |signature| signature.is_a?(Xmldsig::Signature) } end it "returns the nested signatures first" do unsigned_document.signatures.first.references.first.reference_uri.should == '#baz' end end describe "#signed_nodes" do it "returns only the signed nodes" do signed_document.signed_nodes.collect(&:name).should == %w(Foo) end end describe "#validate" do it "returns true if the signature and digest value are correct" do signed_document.validate(certificate).should be == true end it "returns false if the certificate is not valid" do signed_document.validate(other_certificate).should be == false end it "returns false if there are no signatures and validation is strict" do xml_without_signature = Xmldsig::SignedDocument.new('') xml_without_signature.validate(certificate).should be == false end it "accepts a block" do signed_document.validate do |signature_value, data| certificate.public_key.verify(OpenSSL::Digest::SHA256.new, signature_value, data) end.should be == true end end describe "#sign" do it "returns a signed document" do signed_document = unsigned_document.sign(private_key) Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be == true end it "accepts a block" do signed_document = unsigned_document.sign do |data| private_key.sign(OpenSSL::Digest::SHA256.new, data) end Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be == true end end describe "Nested Signatures" do let(:unsigned_xml) { File.read("spec/fixtures/unsigned_nested_signature.xml") } let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) } let(:signed_document) { unsigned_document.sign(private_key) } it "when signed should be valid" do Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be == true end it "should sign 2 elements" do unsigned_document.signed_nodes.count.should == 2 end it "allows individual signs" do unsigned_document.signatures.last.sign(private_key) unsigned_document.validate(certificate).should be == false unsigned_document.signatures.last.valid?(certificate).should be == true end end end