class R509::SPKI

class for loading/generating SPKAC/SPKI requests (typically generated by the <keygen> tag

Attributes

internal_obj[R]
key[R]
spki[R]

Public Class Methods

new(opts = {}) click to toggle source

@option opts [String,OpenSSL::Netscape::SPKI] :spki the spki you want to parse @option opts [R509::PrivateKey,String] :key optional private key to supply. either an unencrypted PEM/DER string or an R509::PrivateKey object (use the latter if you need password/hardware support). if supplied you do not need to pass an spki. @option opts [String] :message_digest Optional digest. sha1, sha224, sha256, sha384, sha512, md5. Defaults to sha256. Only used if you supply a :key and no :spki

# File lib/r509/spki.rb, line 16
def initialize(opts = {})
  if !opts.is_a?(Hash)
    raise ArgumentError, 'Must provide a hash of options'
  elsif !opts.key?(:spki) && !opts.key?(:key)
    raise ArgumentError, 'Must provide either :spki or :key'
  end

  @key = load_private_key(opts)

  if opts.key?(:spki)
    @spki = parse_spki(opts[:spki])
  else
    # create the SPKI from the private key if it wasn't passed in
    @spki = build_spki(opts[:message_digest])
  end
end

Public Instance Methods

public_key() click to toggle source

@return [OpenSSL::PKey::RSA] public key

# File lib/r509/spki.rb, line 34
def public_key
  @spki.public_key
end
signature_algorithm() click to toggle source

Returns the signature algorithm (e.g., RSA-SHA1, ecdsa-with-SHA256)

@return [String] signature algorithm string

# File lib/r509/spki.rb, line 49
def signature_algorithm
  data = OpenSSL::ASN1.decode(self.to_der)
  data.entries[1].value.entries[0].value
end
verify_signature() click to toggle source

Verifies the integrity of the signature on the SPKI @return [Boolean]

# File lib/r509/spki.rb, line 40
def verify_signature
  @spki.verify(public_key)
end

Private Instance Methods

build_spki(md) click to toggle source

Tries to build an SPKI using an existing private key @param [String] md optional message digest @return [OpenSSL::Netscape::SPKI] spki object

# File lib/r509/spki.rb, line 80
def build_spki(md)
  spki = OpenSSL::Netscape::SPKI.new
  spki.public_key = @key.public_key
  if @key.dsa?
    # only DSS1 is acceptable for DSA signing in OpenSSL < 1.0
    # post-1.0 you can sign with anything, but let's be conservative
    # see: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/PKey/DSA.html
    message_digest = R509::MessageDigest.new('dss1')
  else
    message_digest = R509::MessageDigest.new(md)
  end
  spki.sign(@key.key, message_digest.digest)
  spki
end
parse_spki(spki) click to toggle source

Tries to clean and parse an inbound SPKI @param [String] spki string @return [OpenSSL::Netscape::SPKI] spki object

# File lib/r509/spki.rb, line 59
def parse_spki(spki)
  # first let's try cleaning up the input a bit so OpenSSL is happy with it
  # OpenSSL hates SPKAC=
  spki.sub!("SPKAC=", "")
  # it really hates newlines (Firefox loves 'em)
  # so let's normalize line endings
  spki.gsub!(/\r\n?/, "\n")
  # and nuke 'em
  spki.gsub!("\n", "")
  # ...and leading/trailing whitespace
  spki.strip!
  spki = OpenSSL::Netscape::SPKI.new(spki)
  if @key && !spki.verify(@key.public_key)
    raise R509Error, 'Key does not match SPKI.'
  end
  spki
end