def sign(certificate, key,
                 method: Signature::PKCS7_DETACHED,
                 ca: [],
                 annotation: nil,
                 issuer: nil,
                 location: nil,
                 contact: nil,
                 reason: nil)

            unless certificate.is_a?(OpenSSL::X509::Certificate)
                raise TypeError, "A OpenSSL::X509::Certificate object must be passed."
            end

            unless key.is_a?(OpenSSL::PKey::RSA)
                raise TypeError, "A OpenSSL::PKey::RSA object must be passed."
            end

            unless ca.is_a?(::Array)
                raise TypeError, "Expected an Array of CA certificates."
            end

            unless annotation.nil? or annotation.is_a?(Annotation::Widget::Signature)
                raise TypeError, "Expected a Annotation::Widget::Signature object."
            end

            #
            # XXX: Currently signing a linearized document will result in a broken document.
            # Delinearize the document first until we find a proper way to handle this case.
            #
            if self.linearized?
                self.delinearize!
            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]
            end

            annotation.V = digsig
            add_fields(annotation)
            self.Catalog.AcroForm.SigFlags =
                InteractiveForm::SigFlags::SIGNATURES_EXIST | InteractiveForm::SigFlags::APPEND_ONLY

            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

            # 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) }
                    end
            end

            #
            #  Flattening the PDF to get file view.
            #
            compile

            #
            # Creating an empty Xref table to compute signature byte range.
            #
            rebuild_dummy_xrefs

            sig_offset = get_object_offset(digsig.no, digsig.generation) + digsig.signature_offset

            digsig.ByteRange[0] = 0
            digsig.ByteRange[1] = sig_offset
            digsig.ByteRange[2] = sig_offset + digsig.Contents.to_s.bytesize

            until digsig.ByteRange[3] == filesize - digsig.ByteRange[2]
                digsig.ByteRange[3] = filesize - digsig.ByteRange[2]
            end

            # From that point on, the file size remains constant

            #
            # Correct Xrefs variations caused by ByteRange modifications.
            #
            rebuild_xrefs

            file_data = output()
            signable_data = file_data[digsig.ByteRange[0],digsig.ByteRange[1]] +
                file_data[digsig.ByteRange[2],digsig.ByteRange[3]]

            #
            # 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.
            #
            self.freeze
        end
def sign(certificate, key,
                 method: Signature::PKCS7_DETACHED,
                 ca: [],
                 annotation: nil,
                 issuer: nil,
                 location: nil,
                 contact: nil,
                 reason: nil)

            unless certificate.is_a?(OpenSSL::X509::Certificate)
                raise TypeError, "A OpenSSL::X509::Certificate object must be passed."
            end

            unless key.is_a?(OpenSSL::PKey::RSA)
                raise TypeError, "A OpenSSL::PKey::RSA object must be passed."
            end

            unless ca.is_a?(::Array)
                raise TypeError, "Expected an Array of CA certificates."
            end

            unless annotation.nil? or annotation.is_a?(Annotation::Widget::Signature)
                raise TypeError, "Expected a Annotation::Widget::Signature object."
            end

            #
            # XXX: Currently signing a linearized document will result in a broken document.
            # Delinearize the document first until we find a proper way to handle this case.
            #
            if self.linearized?
                self.delinearize!
            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]
            end

            annotation.V = digsig
            add_fields(annotation)
            self.Catalog.AcroForm.SigFlags =
                InteractiveForm::SigFlags::SIGNATURES_EXIST | InteractiveForm::SigFlags::APPEND_ONLY

            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

            # 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) }
                    end
            end

            #
            #  Flattening the PDF to get file view.
            #
            compile

            #
            # Creating an empty Xref table to compute signature byte range.
            #
            rebuild_dummy_xrefs

            sig_offset = get_object_offset(digsig.no, digsig.generation) + digsig.signature_offset

            digsig.ByteRange[0] = 0
            digsig.ByteRange[1] = sig_offset
            digsig.ByteRange[2] = sig_offset + digsig.Contents.to_s.bytesize

            until digsig.ByteRange[3] == filesize - digsig.ByteRange[2]
                digsig.ByteRange[3] = filesize - digsig.ByteRange[2]
            end

            # From that point on, the file size remains constant

            #
            # Correct Xrefs variations caused by ByteRange modifications.
            #
            rebuild_xrefs

            file_data = output()
            signable_data = file_data[digsig.ByteRange[0],digsig.ByteRange[1]] +
                file_data[digsig.ByteRange[2],digsig.ByteRange[3]]

            #
            # 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.
            #
            self.freeze
        end
Sign the document with the given key and x509 certificate.
 _certificate_:: The X509 certificate containing the public key.
 _key_:: The private key associated with the certificate.
 _method_:: The PDF signature identifier.
 _ca_:: Optional CA certificates used to sign the user certificate.
 _annotation_:: Annotation associated with the signature.
 _issuer_:: Issuer name.
 _location_:: Signature location.
 _contact_:: Signer contact.
 _reason_:: Signing reason.