lib/origami/signature.rb in origami-2.0.4 vs lib/origami/signature.rb in origami-2.1.0
- old
+ new
@@ -47,21 +47,11 @@
data = extract_signed_data(digsig)
signature = digsig[:Contents]
subfilter = digsig.SubFilter.value
- case subfilter
- when Signature::DigitalSignature::PKCS7_DETACHED
- Signature.verify_pkcs7_detached_signature(data, signature, store, flags)
-
-
- when Signature::DigitalSignature::PKCS7_SHA1
- Signature.verify_pkcs7_sha1_signature(data, signature, store, flags)
-
- else
- raise NotImplementedError, "Unsupported method #{digsig.SubFilter}"
- end
+ Signature.verify(subfilter.to_s, data, signature, store, flags)
end
#
# Sign the document with the given key and x509 certificate.
# _certificate_:: The X509 certificate containing the public key.
@@ -73,11 +63,11 @@
# _location_:: Signature location.
# _contact_:: Signer contact.
# _reason_:: Signing reason.
#
def sign(certificate, key,
- method: "adbe.pkcs7.detached",
+ method: Signature::PKCS7_DETACHED,
ca: [],
annotation: nil,
issuer: nil,
location: nil,
contact: nil,
@@ -97,45 +87,10 @@
unless annotation.nil? or annotation.is_a?(Annotation::Widget::Signature)
raise TypeError, "Expected a Annotation::Widget::Signature object."
end
- case method
- when 'adbe.pkcs7.detached'
- signfield_size = -> (crt, pkey, certs) do
- OpenSSL::PKCS7.sign(
- crt,
- pkey,
- "",
- certs,
- OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
- ).to_der.size
- end
-
- when 'adbe.pkcs7.sha1'
- signfield_size = -> (crt, pkey, certs) do
- OpenSSL::PKCS7.sign(
- crt,
- pkey,
- Digest::SHA1.digest(''),
- certs,
- OpenSSL::PKCS7::BINARY
- ).to_der.size
- end
-
- when 'adbe.x509.rsa_sha1'
- signfield_size = -> (_crt, pkey, _certs) do
- pkey.private_encrypt(
- Digest::SHA1.digest('')
- ).size
- end
- raise NotImplementedError, "Unsupported method #{method.inspect}"
-
- else
- raise NotImplementedError, "Unsupported method #{method.inspect}"
- end
-
digsig = Signature::DigitalSignature.new.set_indirect(true)
if annotation.nil?
annotation = Annotation::Widget::Signature.new
annotation.Rect = Rectangle[:llx => 0.0, :lly => 0.0, :urx => 0.0, :ury => 0.0]
@@ -144,22 +99,23 @@
annotation.V = digsig
add_fields(annotation)
self.Catalog.AcroForm.SigFlags =
InteractiveForm::SigFlags::SIGNATURES_EXIST | InteractiveForm::SigFlags::APPEND_ONLY
- digsig.Type = :Sig #:nodoc:
- digsig.Contents = HexaString.new("\x00" * signfield_size[certificate, key, ca]) #:nodoc:
- digsig.Filter = :"Adobe.PPKLite" #:nodoc:
- digsig.SubFilter = Name.new(method) #:nodoc:
- digsig.ByteRange = [0, 0, 0, 0] #:nodoc:
+ digsig.Type = :Sig
+ digsig.Contents = HexaString.new("\x00" * Signature::required_size(method, certificate, key, ca))
+ digsig.Filter = :"Adobe.PPKLite"
+ digsig.SubFilter = Name.new(method)
+ digsig.ByteRange = [0, 0, 0, 0]
digsig.Name = issuer
digsig.Location = HexaString.new(location) if location
digsig.ContactInfo = HexaString.new(contact) if contact
digsig.Reason = HexaString.new(reason) if reason
- if method == 'adbe.x509.rsa_sha1'
+ # PKCS1 signatures require a Cert entry.
+ if method == Signature::PKCS1_RSA_SHA1
digsig.Cert =
if ca.empty?
HexaString.new(certificate.to_der)
else
[ HexaString.new(certificate.to_der) ] + ca.map{ |crt| HexaString.new(crt.to_der) }
@@ -195,34 +151,14 @@
file_data = output()
signable_data = file_data[digsig.ByteRange[0],digsig.ByteRange[1]] +
file_data[digsig.ByteRange[2],digsig.ByteRange[3]]
- signature =
- case method
- when 'adbe.pkcs7.detached'
- OpenSSL::PKCS7.sign(
- certificate,
- key,
- signable_data,
- ca,
- OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
- ).to_der
-
- when 'adbe.pkcs7.sha1'
- OpenSSL::PKCS7.sign(
- certificate,
- key,
- Digest::SHA1.digest(signable_data),
- ca,
- OpenSSL::PKCS7::BINARY
- ).to_der
-
- when 'adbe.x509.rsa_sha1'
- key.private_encrypt(Digest::SHA1.digest(signable_data))
- end
-
+ #
+ # Computes and inserts the signature.
+ #
+ signature = Signature.compute(method, signable_data, certificate, key, ca)
digsig.Contents[0, signature.size] = signature
#
# No more modification are allowed after signing.
#
@@ -246,19 +182,12 @@
# Enable the document Usage Rights.
# _rights_:: list of rights defined in UsageRights::Rights
#
def enable_usage_rights(cert, pkey, *rights)
- signfield_size = -> (crt, key, ca) do
- OpenSSL::PKCS7.sign(
- crt,
- key,
- '',
- ca,
- OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
- ).to_der.size
- end
+ # Always uses a detached PKCS7 signature for UR.
+ method = Signature::PKCS7_DETACHED
#
# Load key pair
#
key = pkey.is_a?(OpenSSL::PKey::RSA) ? pkey : OpenSSL::PKey::RSA.new(pkey)
@@ -270,25 +199,25 @@
digsig = Signature::DigitalSignature.new.set_indirect(true)
self.Catalog.AcroForm ||= InteractiveForm.new
#self.Catalog.AcroForm.SigFlags = InteractiveForm::SigFlags::APPEND_ONLY
- digsig.Type = :Sig #:nodoc:
- digsig.Contents = HexaString.new("\x00" * signfield_size[certificate, key, []]) #:nodoc:
- digsig.Filter = :"Adobe.PPKLite" #:nodoc:
- digsig.Name = "ARE Acrobat Product v8.0 P23 0002337" #:nodoc:
- digsig.SubFilter = :"adbe.pkcs7.detached" #:nodoc:
- digsig.ByteRange = [0, 0, 0, 0] #:nodoc:
+ digsig.Type = :Sig
+ digsig.Contents = HexaString.new("\x00" * Signature.required_size(method, certificate, key, []))
+ digsig.Filter = :"Adobe.PPKLite"
+ digsig.Name = "ARE Acrobat Product v8.0 P23 0002337"
+ digsig.SubFilter = Name.new(method )
+ digsig.ByteRange = [0, 0, 0, 0]
- sigref = Signature::Reference.new #:nodoc:
- sigref.Type = :SigRef #:nodoc:
- sigref.TransformMethod = :UR3 #:nodoc:
+ sigref = Signature::Reference.new
+ sigref.Type = :SigRef
+ sigref.TransformMethod = :UR3
sigref.Data = self.Catalog
sigref.TransformParams = UsageRights::TransformParams.new
- sigref.TransformParams.P = true #:nodoc:
- sigref.TransformParams.Type = :TransformParams #:nodoc:
+ sigref.TransformParams.P = true
+ sigref.TransformParams.Type = :TransformParams
sigref.TransformParams.V = UsageRights::TransformParams::VERSION
rights.each do |right|
sigref.TransformParams[right.first] ||= []
sigref.TransformParams[right.first].concat(right[1..-1])
@@ -328,17 +257,11 @@
file_data = output()
signable_data = file_data[digsig.ByteRange[0],digsig.ByteRange[1]] +
file_data[digsig.ByteRange[2],digsig.ByteRange[3]]
- signature = OpenSSL::PKCS7.sign(
- certificate,
- key,
- signable_data,
- [],
- OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
- ).to_der
+ signature = Signature.compute(method, signable_data, certificate, key, [])
digsig.Contents[0, signature.size] = signature
#
# No more modification are allowed after signing.
#
@@ -397,26 +320,57 @@
field :UR3, :Type => Dictionary, :Version => "1.6"
end
module Signature
- # Verifies a PKCS7 detached signature.
- def self.verify_pkcs7_detached_signature(data, signature, store, flags)
- pkcs7 = OpenSSL::PKCS7.new(signature)
- raise SignatureError, "Not a PKCS7 detached signature" unless pkcs7.detached?
+ PKCS1_RSA_SHA1 = "adbe.x509.rsa_sha1"
+ PKCS7_SHA1 = "adbe.pkcs7.sha1"
+ PKCS7_DETACHED = "adbe.pkcs7.detached"
- flags |= OpenSSL::PKCS7::DETACHED
- pkcs7.verify([], store, data, flags)
+ def self.verify(method, data, signature, store, flags)
+ case method
+ when PKCS7_DETACHED
+ pkcs7 = OpenSSL::PKCS7.new(signature)
+ raise SignatureError, "Not a PKCS7 detached signature" unless pkcs7.detached?
+ flags |= OpenSSL::PKCS7::DETACHED
+ pkcs7.verify([], store, data, flags)
+
+ when PKCS7_SHA1
+ pkcs7 = OpenSSL::PKCS7.new(signature)
+ pkcs7.verify([], store, nil, flags) and pkcs7.data == Digest::SHA1.digest(data)
+
+ else
+ raise NotImplementedError, "Unsupported signature method #{method.inspect}"
+ end
end
- # Verifies a PKCS7-SHA1 signature.
- def self.verify_pkcs7_sha1_signature(data, signature, store, flags)
- pkcs7 = OpenSSL::PKCS7.new(signature)
- pkcs7.verify([], store, nil, flags) and pkcs7.data == Digest::SHA1.digest(data)
+ #
+ # Computes the required size in bytes for storing the signature.
+ #
+ def self.required_size(method, certificate, key, ca)
+ self.compute(method, "", certificate, key, ca).size
end
#
+ # Computes the signature using the specified subfilter method.
+ #
+ def self.compute(method, data, certificate, key, ca)
+ case method
+ when PKCS7_DETACHED
+ OpenSSL::PKCS7.sign(certificate, key, data, ca, OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der
+
+ when PKCS7_SHA1
+ OpenSSL::PKCS7.sign(certificate, key, Digest::SHA1.digest(data), ca, OpenSSL::PKCS7::BINARY).to_der
+
+ when PKCS1_RSA_SHA1
+ key.sign(OpenSSL::Digest::SHA1.new, data)
+ else
+ raise NotImplementedError, "Unsupported signature method #{method.inspect}"
+ end
+ end
+
+ #
# Class representing a signature which can be embedded in DigitalSignature dictionary.
# It must be a direct object.
#
class Reference < Dictionary
include StandardObject
@@ -503,13 +457,9 @@
#
# Class representing a digital signature.
#
class DigitalSignature < Dictionary
include StandardObject
-
- PKCS1_RSA_SHA1 = :"adbe.x509.rsa_sha1"
- PKCS7_SHA1 = :"adbe.pkcs7.sha1"
- PKCS7_DETACHED = :"adbe.pkcs7.detached"
field :Type, :Type => Name, :Default => :Sig
field :Filter, :Type => Name, :Default => :"Adobe.PPKLite", :Required => true
field :SubFilter, :Type => Name
field :Contents, :Type => String, :Required => true