class RSA::KeyPair

An RSA key pair.

Refer to PKCS #1 v2.1, section 3, pp. 6-8.

@see www.rsa.com/rsalabs/node.asp?id=2125 @see en.wikipedia.org/wiki/Public-key_cryptography

Attributes

private[RW]

The RSA private key.

@return [Key]

private_key[RW]

The RSA private key.

@return [Key]

public[RW]

The RSA public key.

@return [Key]

public_key[RW]

The RSA public key.

@return [Key]

Public Class Methods

generate(bits, exponent = 65537) click to toggle source

Generates a new RSA key pair of length `bits`.

By default, the public exponent will be 65537 (0x10001) as recommended by {RSA::PKCS1 PKCS #1}.

@param [Integer, to_i] bits @param [Integer, to_i] exponent @return [KeyPair]

# File lib/rsa-g/openssl.rb, line 16
def self.generate(bits, exponent = 65537)
  pkey = ::OpenSSL::PKey::RSA.generate(bits.to_i, exponent.to_i)
  n, d, e = pkey.n.to_i, pkey.d.to_i, pkey.e.to_i
  self.new(Key.new(n, d), Key.new(n, e))
end
new(private_key, public_key, options = {}) click to toggle source

Initializes a new key pair.

@param [Key] private_key @param [Key] public_key @param [Hash{Symbol => Object}] options

# File lib/rsa-g/key_pair.rb, line 30
def initialize(private_key, public_key, options = {})
  @private_key = private_key
  @public_key  = public_key
  @options     = options.dup
end

Public Instance Methods

bitsize() click to toggle source

Returns the bit size of this key pair.

@return [Integer]

# File lib/rsa-g/key_pair.rb, line 76
def bitsize
  Math.log2(modulus).ceil
end
Also aliased as: size
bytesize() click to toggle source

Returns the byte size of this key pair.

@return [Integer]

# File lib/rsa-g/key_pair.rb, line 68
def bytesize
  Math.log256(modulus).ceil
end
decrypt(ciphertext, options = {}) click to toggle source

Decrypts the given `ciphertext` using the private key from this key pair.

@overload decrypt(ciphertext, options = {})

@param  [Integer]                 ciphertext
@param  [Hash{Symbol => Object}]  options
@return [Integer]

@overload decrypt(ciphertext, options = {})

@param  [String, IO, StringIO]    ciphertext
@param  [Hash{Symbol => Object}]  options
@return [String]

@param [Object] ciphertext @param [Hash{Symbol => Object}] options @option options [Symbol, to_sym] :padding (nil)

# File lib/rsa-g/key_pair.rb, line 144
def decrypt(ciphertext, options = {})
  case ciphertext
    when Integer      then decrypt_integer(ciphertext, options)
    when String       then PKCS1.i2osp(decrypt_integer(PKCS1.os2ip(ciphertext), options))
    when StringIO, IO then PKCS1.i2osp(decrypt_integer(PKCS1.os2ip(ciphertext.read), options))
    else raise ArgumentError, ciphertext.inspect # FIXME
  end
end
encrypt(plaintext, options = {}) click to toggle source

Encrypts the given `plaintext` using the public key from this key pair.

@overload encrypt(plaintext, options = {})

@param  [Integer]                 plaintext
@param  [Hash{Symbol => Object}]  options
@return [Integer]

@overload encrypt(plaintext, options = {})

@param  [String, IO, StringIO]    plaintext
@param  [Hash{Symbol => Object}]  options
@return [String]

@param [Object] plaintext @param [Hash{Symbol => Object}] options @option options [Symbol, to_sym] :padding (nil)

# File lib/rsa-g/key_pair.rb, line 118
def encrypt(plaintext, options = {})
  case plaintext
    when Integer      then encrypt_integer(plaintext, options)
    when String       then PKCS1.i2osp(encrypt_integer(PKCS1.os2ip(plaintext), options))
    when StringIO, IO then PKCS1.i2osp(encrypt_integer(PKCS1.os2ip(plaintext.read), options))
    else raise ArgumentError, plaintext.inspect # FIXME
  end
end
modulus() click to toggle source

Returns the RSA modulus for this key pair.

@return [Integer]

# File lib/rsa-g/key_pair.rb, line 85
def modulus
  private_key ? private_key.modulus : public_key.modulus
end
Also aliased as: n
n()
Alias for: modulus
private?()
Alias for: private_key?
private_key?() click to toggle source

Returns `true` if this key pair contains a private key.

@return [Boolean]

# File lib/rsa-g/key_pair.rb, line 40
def private_key?
  !!private_key
end
Also aliased as: private?
public?()
Alias for: public_key?
public_key?() click to toggle source

Returns `true` if this key pair contains a public key.

@return [Boolean]

# File lib/rsa-g/key_pair.rb, line 49
def public_key?
  !!public_key
end
Also aliased as: public?
sign(plaintext, options = {}) click to toggle source

Signs the given `plaintext` using the private key from this key pair.

@overload sign(plaintext, options = {})

@param  [Integer]                 plaintext
@param  [Hash{Symbol => Object}]  options
@return [Integer]

@overload sign(plaintext, options = {})

@param  [String, IO, StringIO]    plaintext
@param  [Hash{Symbol => Object}]  options
@return [String]

@param [Object] plaintext @param [Hash{Symbol => Object}] options @option options [Symbol, to_sym] :padding (nil)

# File lib/rsa-g/key_pair.rb, line 169
def sign(plaintext, options = {})
  case plaintext
    when Integer      then sign_integer(plaintext, options)
    when String       then PKCS1.i2osp(sign_integer(PKCS1.os2ip(plaintext), options))
    when StringIO, IO then PKCS1.i2osp(sign_integer(PKCS1.os2ip(plaintext.read), options))
    else raise ArgumentError, plaintext.inspect # FIXME
  end
end
size()
Alias for: bitsize
to_hash() click to toggle source

Returns a hash table representation of this key pair.

@example

key_pair.to_hash  #=> {:n => ..., :d => ..., :e => ...}

@return [Hash]

# File lib/rsa-g/key_pair.rb, line 97
def to_hash
  {:n => modulus, :d => private_key ? private_key.exponent : nil, :e => public_key ? public_key.exponent : nil}
end
to_openssl() click to toggle source

Returns this key pair as an `OpenSSL::PKey::RSA` instance.

@return [OpenSSL::PKey::RSA]

# File lib/rsa-g/openssl.rb, line 26
def to_openssl
  @openssl_pkey ||= begin
    pkey   = ::OpenSSL::PKey::RSA.new
    pkey.n = private_key.modulus  if private_key?
    pkey.e = private_key.exponent if private_key?
    pkey.n ||= public_key.modulus if public_key?
    pkey.d = public_key.exponent  if public_key?
    pkey
  end
end
valid?() click to toggle source

Returns `true` if this is a valid RSA key pair according to {RSA::PKCS1 PKCS #1}.

@return [Boolean] @see Key#valid?

# File lib/rsa-g/key_pair.rb, line 60
def valid?
  private_key.valid? && public_key.valid?
end
verify(signature, plaintext, options = {}) click to toggle source

Verifies the given `signature` using the public key from this key pair.

@overload verify(signature, plaintext, options = {})

@param  [Integer]                 signature
@param  [Integer]                 plaintext
@param  [Hash{Symbol => Object}]  options
@return [Boolean]

@overload verify(signature, plaintext, options = {})

@param  [String, IO, StringIO]    signature
@param  [String, IO, StringIO]    plaintext
@param  [Hash{Symbol => Object}]  options
@return [Boolean]

@param [Object] signature @param [Object] plaintext @param [Hash{Symbol => Object}] options @option options [Symbol, to_sym] :padding (nil) @return [Boolean]

# File lib/rsa-g/key_pair.rb, line 199
def verify(signature, plaintext, options = {})
  signature = case signature
    when Integer      then signature
    when String       then PKCS1.os2ip(signature)
    when StringIO, IO then PKCS1.os2ip(signature.read)
    else raise ArgumentError, signature.inspect # FIXME
  end
  plaintext = case plaintext
    when Integer      then plaintext
    when String       then PKCS1.os2ip(plaintext)
    when StringIO, IO then PKCS1.os2ip(plaintext.read)
    else raise ArgumentError, plaintext.inspect # FIXME
  end
  verify_integer(signature, plaintext, options)
end

Protected Instance Methods

decrypt_integer(ciphertext, options = {}) click to toggle source

@private

# File lib/rsa-g/key_pair.rb, line 225
def decrypt_integer(ciphertext, options = {})
  PKCS1.rsadp(private_key, ciphertext)
end
encrypt_integer(plaintext, options = {}) click to toggle source

@private

# File lib/rsa-g/key_pair.rb, line 219
def encrypt_integer(plaintext, options = {})
  PKCS1.rsaep(public_key, plaintext)
end
sign_integer(plaintext, options = {}) click to toggle source

@private

# File lib/rsa-g/key_pair.rb, line 231
def sign_integer(plaintext, options = {})
  PKCS1.rsasp1(private_key, plaintext)
end
verify_integer(signature, plaintext, options = {}) click to toggle source

@private

# File lib/rsa-g/key_pair.rb, line 237
def verify_integer(signature, plaintext, options = {})
  PKCS1.rsavp1(public_key, signature).eql?(plaintext)
end