Class: OpenSSL::PKey::RSA
- Inherits:
-
Object
- Object
- OpenSSL::PKey::RSA
- Defined in:
- lib/openssl/pkey/rsa.rb
Overview
Additional helper methods for RSA keys.
Class Method Summary collapse
-
.from_factors(p, q, e) ⇒ OpenSSL::PKey::RSA
Construct a fully-featured RSA private key from fundamental values.
Instance Method Summary collapse
-
#to_spki(_format = nil) ⇒ OpenSSL::X509::SPKI
Generate an OpenSSL::X509::SPKI structure for this public key.
-
#valid?(extended = true) ⇒ Boolean
Give our best guess as to whether the given RSA private key is valid.
Class Method Details
.from_factors(p, q, e) ⇒ OpenSSL::PKey::RSA
This method does not attempt to validate that the values for ‘p` & `q` are, in fact, primes, nor does it make any value judgments about your choice of `e`.
Construct a fully-featured RSA private key from fundamental values.
Many parts of an RSA key are, in fact, derived from the basic numbers that are (mostly) generated randomly. Whilst it is always better to let OpenSSL generate a whole key for you, in extremely limited circumstances, it can be useful to get a key which has been populated using factors derived from another source.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/openssl/pkey/rsa.rb', line 100 def self.from_factors(p, q, e) p, q = q, p if p < q n = p * q # While `lcm = (p - 1).lcm(q - 1)` produces smaller keys, this version # produces key that are identical to OpenSSL, which is generally our # compatibility target. lcm = (p - 1) * (q - 1) if e < 1 || e >= lcm raise OpenSSL::PKey::PKeyError, "e must be 1 < e < lambda(n)" end if e.gcd(lcm) != 1 raise OpenSSL::PKey::PKeyError, "e must coprime to lambda(n)" end d, _ = egcd(e, lcm) # Ensure that d > 0 d %= lcm if d < 0 dmp1 = d % (p - 1) dmq1 = d % (q - 1) iqmp, _ = egcd(q, p) iqmp += p / p.gcd(q) if iqmp < 0 OpenSSL::PKey::RSA.new.tap do |k| k.set_key(n, e, d) k.set_factors(p, q) k.set_crt_params(dmp1, dmq1, iqmp) end end |
Instance Method Details
#to_spki(_format = nil) ⇒ OpenSSL::X509::SPKI
Generate an OpenSSL::X509::SPKI structure for this public key.
14 15 16 |
# File 'lib/openssl/pkey/rsa.rb', line 14 def to_spki(_format = nil) OpenSSL::X509::SPKI.new(self.public_key.to_der) end |
#valid?(extended = true) ⇒ Boolean
Give our best guess as to whether the given RSA private key is valid.
Applies a set of heuristics to the (private) key, with a view to deciding whether it is correctly formed.
Based on the RSA_check_key OpenSSL function.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/openssl/pkey/rsa.rb', line 33 def valid?(extended = true) # Must have factors and public exponent return false if p.nil? || q.nil? || e.nil? # Public exponent must be odd and greater than one return false if e == 1 return false if e % 2 == 0 # Factors must be prime return false unless p.prime? return false unless q.prime? # All the remaining checks are things that could be fixed with some # arithmetic return true if !extended # Must have private exponent and a modulus return false if d.nil? || n.nil? # Public modulus must be the product of the two prime factors return false unless n == p * q # d * e must equal 1 mod (lcm(p-1,q-1)) return false unless e * d % (p.to_i-1).lcm(q.to_i-1) == 1 # CRT parameters are optional, but if present must be correct unless dmp1.nil? return false unless dmp1 == d % (p-1) end unless dmq1.nil? return false unless dmq1 == d % (q-1) end unless iqmp.nil? t, _ = self.class.egcd(q.to_i, p.to_i) t %= p if t < 0 return false unless iqmp == t end return true end |