Class: SSHData::PublicKey::ECDSA
- Defined in:
- lib/ssh_data/public_key/ecdsa.rb
Direct Known Subclasses
Constant Summary collapse
- NISTP256 =
"nistp256"
- NISTP384 =
"nistp384"
- NISTP521 =
"nistp521"
- OPENSSL_CURVE_NAME_FOR_CURVE =
{ NISTP256 => "prime256v1", NISTP384 => "secp384r1", NISTP521 => "secp521r1", }
- CURVE_FOR_OPENSSL_CURVE_NAME =
{ "prime256v1" => NISTP256, "secp384r1" => NISTP384, "secp521r1" => NISTP521, }
- DIGEST_FOR_CURVE =
{ NISTP256 => OpenSSL::Digest::SHA256, NISTP384 => OpenSSL::Digest::SHA384, NISTP521 => OpenSSL::Digest::SHA512, }
Instance Attribute Summary collapse
-
#curve ⇒ Object
readonly
Returns the value of attribute curve.
-
#openssl ⇒ Object
readonly
Returns the value of attribute openssl.
-
#public_key_bytes ⇒ Object
readonly
Returns the value of attribute public_key_bytes.
Attributes inherited from Base
Class Method Summary collapse
- .check_algorithm!(algo, curve) ⇒ Object
-
.openssl_signature(sig) ⇒ Object
Convert an SSH encoded ECDSA signature to DER encoding for verification with OpenSSL.
-
.ssh_signature(sig) ⇒ Object
Convert an DER encoded ECDSA signature, as generated by OpenSSL to SSH encoding.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Is this public key equal to another public key?.
-
#digest ⇒ Object
The digest algorithm to use with this key’s curve.
-
#initialize(algo:, curve:, public_key:) ⇒ ECDSA
constructor
A new instance of ECDSA.
-
#rfc4253 ⇒ Object
RFC4253 binary encoding of the public key.
-
#verify(signed_data, signature) ⇒ Object
Verify an SSH signature.
Methods inherited from Base
Constructor Details
#initialize(algo:, curve:, public_key:) ⇒ ECDSA
Returns a new instance of ECDSA.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 78 def initialize(algo:, curve:, public_key:) self.class.check_algorithm!(algo, curve) @curve = curve @public_key_bytes = public_key @openssl = begin OpenSSL::PKey::EC.new(asn1.to_der) rescue ArgumentError raise DecodeError, "bad key data" end super(algo: algo) end |
Instance Attribute Details
#curve ⇒ Object (readonly)
Returns the value of attribute curve.
4 5 6 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 4 def curve @curve end |
#openssl ⇒ Object (readonly)
Returns the value of attribute openssl.
4 5 6 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 4 def openssl @openssl end |
#public_key_bytes ⇒ Object (readonly)
Returns the value of attribute public_key_bytes.
4 5 6 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 4 def public_key_bytes @public_key_bytes end |
Class Method Details
.check_algorithm!(algo, curve) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 68 def self.check_algorithm!(algo, curve) unless [ALGO_ECDSA256, ALGO_ECDSA384, ALGO_ECDSA521].include?(algo) raise DecodeError, "bad algorithm: #{algo.inspect}" end unless algo == "ecdsa-sha2-#{curve}" raise DecodeError, "bad curve: #{curve.inspect}" end end |
.openssl_signature(sig) ⇒ Object
Convert an SSH encoded ECDSA signature to DER encoding for verification with OpenSSL.
sig - A binary String signature from an SSH packet.
Returns a binary String signature, as expected by OpenSSL.
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 34 def self.openssl_signature(sig) r, rlen = Encoding.decode_mpint(sig, 0) s, slen = Encoding.decode_mpint(sig, rlen) if rlen + slen != sig.bytesize raise DecodeError, "unexpected trailing data" end OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::Integer.new(r), OpenSSL::ASN1::Integer.new(s) ]).to_der end |
.ssh_signature(sig) ⇒ Object
Convert an DER encoded ECDSA signature, as generated by OpenSSL to SSH encoding.
sig - A binary String signature, as generated by OpenSSL.
Returns a binary String signature, as found in an SSH packet.
54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 54 def self.ssh_signature(sig) a1 = OpenSSL::ASN1.decode(sig) if a1.tag_class != :UNIVERSAL || a1.tag != OpenSSL::ASN1::SEQUENCE || a1.value.count != 2 raise DecodeError, "bad asn1 signature" end r, s = a1.value if r.tag_class != :UNIVERSAL || r.tag != OpenSSL::ASN1::INTEGER || s.tag_class != :UNIVERSAL || s.tag != OpenSSL::ASN1::INTEGER raise DecodeError, "bad asn1 signature" end [Encoding.encode_mpint(r.value), Encoding.encode_mpint(s.value)].join end |
Instance Method Details
#==(other) ⇒ Object
Is this public key equal to another public key?
other - Another SSHData::PublicKey::Base instance to compare with.
Returns boolean.
127 128 129 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 127 def ==(other) super && other.curve == curve && other.public_key_bytes == public_key_bytes end |
#digest ⇒ Object
The digest algorithm to use with this key’s curve.
Returns an OpenSSL::Digest.
134 135 136 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 134 def digest DIGEST_FOR_CURVE[curve] end |
#rfc4253 ⇒ Object
RFC4253 binary encoding of the public key.
Returns a binary String.
114 115 116 117 118 119 120 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 114 def rfc4253 Encoding.encode_fields( [:string, algo], [:string, curve], [:string, public_key_bytes], ) end |
#verify(signed_data, signature) ⇒ Object
Verify an SSH signature.
signed_data - The String message that the signature was calculated over. signature - The binary String signature with SSH encoding.
Returns boolean.
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/ssh_data/public_key/ecdsa.rb', line 99 def verify(signed_data, signature) sig_algo, ssh_sig, _ = Encoding.decode_signature(signature) if sig_algo != "ecdsa-sha2-#{curve}" raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}" end openssl_sig = self.class.openssl_signature(ssh_sig) digest = DIGEST_FOR_CURVE[curve] openssl.verify(digest.new, openssl_sig, signed_data) end |