# class Gem::Security::Signer

### Constants

DEFAULT_OPTIONS

### Attributes

cert_chain[RW]

The chain of certificates for signing including the signing certificate

digest_algorithm[R]

The digest algorithm used to create the signature

key[RW]

The private key for the signing certificate

options[R]

`Gem::Security::Signer` options

### Public Class Methods

new(key, cert_chain, passphrase = nil, options = {}) click to toggle source

Creates a new signer with an RSA `key` or path to a key, and a certificate `chain` containing X509 certificates, encoding certificates or paths to certificates.

    # File lib/rubygems/security/signer.rb, line 68
    def initialize(key, cert_chain, passphrase = nil, options = {})
      @cert_chain = cert_chain
      @key        = key
      @passphrase = passphrase
      @options = DEFAULT_OPTIONS.merge(options)

      unless @key
        default_key = File.join Gem.default_key_path
        @key = default_key if File.exist? default_key
      end

      unless @cert_chain
        default_cert = File.join Gem.default_cert_path
        @cert_chain = [default_cert] if File.exist? default_cert
      end

      @digest_algorithm = Gem::Security::DIGEST_ALGORITHM
      @digest_name      = Gem::Security::DIGEST_NAME

      if @key && !@key.is_a?(OpenSSL::PKey::RSA)
        @key = OpenSSL::PKey::RSA.new(File.read(@key), @passphrase)
      end

      if @cert_chain
        @cert_chain = @cert_chain.compact.map do |cert|
          next cert if OpenSSL::X509::Certificate === cert

          cert = File.read cert if File.exist? cert

          OpenSSL::X509::Certificate.new cert
        end

        load_cert_chain
      end
    end

re_sign_cert(expired_cert, expired_cert_path, private_key) { |expired_cert_path, new_expired_cert_path| ... } click to toggle source

Attemps to re-sign an expired cert with a given private key

    # File lib/rubygems/security/signer.rb, line 43
    def self.re_sign_cert(expired_cert, expired_cert_path, private_key)
      return unless expired_cert.not_after < Time.now

      expiry = expired_cert.not_after.strftime('%Y%m%d%H%M%S')
      expired_cert_file = "#{File.basename(expired_cert_path)}.expired.#{expiry}"
      new_expired_cert_path = File.join(Gem.user_home, ".gem", expired_cert_file)

      Gem::Security.write(expired_cert, new_expired_cert_path)

      re_signed_cert = Gem::Security.re_sign(
        expired_cert,
        private_key,
        (Gem::Security::ONE_DAY * Gem.configuration.cert_expiration_length_days)
      )

      Gem::Security.write(re_signed_cert, expired_cert_path)

      yield(expired_cert_path, new_expired_cert_path) if block_given?
    end

### Public Instance Methods

sign(data) click to toggle source

Sign data with given digest algorithm

    # File lib/rubygems/security/signer.rb, line 140
    def sign(data)
      return unless @key

      raise Gem::Security::Exception, 'no certs provided' if @cert_chain.empty?

      if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now
        alert("Your certificate has expired, trying to re-sign it...")

        re_sign_key(
          expiration_length: (Gem::Security::ONE_DAY * options[:expiration_length_days])
        )
      end

      full_name = extract_name @cert_chain.last

      Gem::Security::SigningPolicy.verify @cert_chain, @key, {}, {}, full_name

      @key.sign @digest_algorithm.new, data
    end