/usr/lib/ruby/vendor_ruby/net/ssh/transport/openssl.rb is in ruby-net-ssh 1:3.0.1-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | # -*- coding: utf-8 -*-
require 'openssl'
module OpenSSL
# This class is originally defined in the OpenSSL module. As needed, methods
# have been added to it by the Net::SSH module for convenience in dealing with
# SSH functionality.
class BN
# Converts a BN object to a string. The format used is that which is
# required by the SSH2 protocol.
def to_ssh
if zero?
return [0].pack("N")
else
buf = to_s(2)
if buf.getbyte(0)[7] == 1
return [buf.length+1, 0, buf].pack("NCA*")
else
return [buf.length, buf].pack("NA*")
end
end
end
end
module PKey
class PKey
def fingerprint
@fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
end
end
# This class is originally defined in the OpenSSL module. As needed, methods
# have been added to it by the Net::SSH module for convenience in dealing
# with SSH functionality.
class DH
# Determines whether the pub_key for this key is valid. (This algorithm
# lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
def valid?
return false if pub_key.nil? || pub_key < 0
bits_set = 0
pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
return ( bits_set > 1 && pub_key < p )
end
end
# This class is originally defined in the OpenSSL module. As needed, methods
# have been added to it by the Net::SSH module for convenience in dealing
# with SSH functionality.
class RSA
# Returns "ssh-rsa", which is the description of this key type used by the
# SSH2 protocol.
def ssh_type
"ssh-rsa"
end
# Converts the key to a blob, according to the SSH2 protocol.
def to_blob
@blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
end
# Verifies the given signature matches the given data.
def ssh_do_verify(sig, data)
verify(OpenSSL::Digest::SHA1.new, sig, data)
end
# Returns the signature for the given data.
def ssh_do_sign(data)
sign(OpenSSL::Digest::SHA1.new, data)
end
end
# This class is originally defined in the OpenSSL module. As needed, methods
# have been added to it by the Net::SSH module for convenience in dealing
# with SSH functionality.
class DSA
# Returns "ssh-dss", which is the description of this key type used by the
# SSH2 protocol.
def ssh_type
"ssh-dss"
end
# Converts the key to a blob, according to the SSH2 protocol.
def to_blob
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
:bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
end
# Verifies the given signature matches the given data.
def ssh_do_verify(sig, data)
sig_r = sig[0,20].unpack("H*")[0].to_i(16)
sig_s = sig[20,20].unpack("H*")[0].to_i(16)
a1sig = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(sig_r),
OpenSSL::ASN1::Integer(sig_s)
])
return verify(OpenSSL::Digest::DSS1.new, a1sig.to_der, data)
end
# Signs the given data.
def ssh_do_sign(data)
sig = sign( OpenSSL::Digest::DSS1.new, data)
a1sig = OpenSSL::ASN1.decode( sig )
sig_r = a1sig.value[0].value.to_s(2)
sig_s = a1sig.value[1].value.to_s(2)
if sig_r.length > 20 || sig_s.length > 20
raise OpenSSL::PKey::DSAError, "bad sig size"
end
sig_r = "\0" * ( 20 - sig_r.length ) + sig_r if sig_r.length < 20
sig_s = "\0" * ( 20 - sig_s.length ) + sig_s if sig_s.length < 20
return sig_r + sig_s
end
end
if defined?(OpenSSL::PKey::EC)
# This class is originally defined in the OpenSSL module. As needed, methods
# have been added to it by the Net::SSH module for convenience in dealing
# with SSH functionality.
class EC
CurveNameAlias = {
"nistp256" => "prime256v1",
"nistp384" => "secp384r1",
"nistp521" => "secp521r1",
}
CurveNameAliasInv = {
"prime256v1" => "nistp256",
"secp384r1" => "nistp384",
"secp521r1" => "nistp521",
}
def self.read_keyblob(curve_name_in_type, buffer)
curve_name_in_key = buffer.read_string
unless curve_name_in_type == curve_name_in_key
raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
end
public_key_oct = buffer.read_string
begin
key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
group = key.group
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
key.public_key = point
return key
rescue OpenSSL::PKey::ECError
raise NotImplementedError, "unsupported key type `#{type}'"
end
end
# Returns the description of this key type used by the
# SSH2 protocol, like "ecdsa-sha2-nistp256"
def ssh_type
"ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
end
def digester
if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/
curve_size = $1.to_i
if curve_size <= 256
OpenSSL::Digest::SHA256.new
elsif curve_size <= 384
OpenSSL::Digest::SHA384.new
else
OpenSSL::Digest::SHA512.new
end
else
OpenSSL::Digest::SHA256.new
end
end
private :digester
# Converts the key to a blob, according to the SSH2 protocol.
def to_blob
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
:string, CurveNameAliasInv[self.group.curve_name],
:string, self.public_key.to_bn.to_s(2)).to_s
@blob
end
# Verifies the given signature matches the given data.
def ssh_do_verify(sig, data)
digest = digester.digest(data)
a1sig = nil
begin
sig_r_len = sig[0,4].unpack("H*")[0].to_i(16)
sig_l_len = sig[4+sig_r_len,4].unpack("H*")[0].to_i(16)
sig_r = sig[4,sig_r_len].unpack("H*")[0]
sig_s = sig[4+sig_r_len+4,sig_l_len].unpack("H*")[0]
a1sig = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(sig_r.to_i(16)),
OpenSSL::ASN1::Integer(sig_s.to_i(16)),
])
rescue
end
if a1sig == nil
return false
else
dsa_verify_asn1(digest, a1sig.to_der)
end
end
# Returns the signature for the given data.
def ssh_do_sign(data)
digest = digester.digest(data)
sig = dsa_sign_asn1(digest)
a1sig = OpenSSL::ASN1.decode( sig )
sig_r = a1sig.value[0].value
sig_s = a1sig.value[1].value
return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
end
end
else
class OpenSSL::PKey::ECError < RuntimeError
# for compatibility with interpreters
# without EC support (i.e. JRuby)
end
end
end
end
|