class Mysql::Authenticator::CachingSha2Password

Public Class Methods

new(protocol) click to toggle source

@param protocol [Mysql::Protocol]

# File lib/mysql/authenticator/caching_sha2_password.rb, line 7
def initialize(protocol)
  @protocol = protocol
end

Public Instance Methods

authenticate(passwd, scramble) { |hash_password(passwd, scramble)| ... } click to toggle source

@param passwd [String] @param scramble [String] @yield [String] hashed password @return [Mysql::Packet]

# File lib/mysql/authenticator/caching_sha2_password.rb, line 20
def authenticate(passwd, scramble)
  yield hash_password(passwd, scramble)
  pkt = @protocol.read
  data = pkt.to_s
  if data.size == 2 && data[0] == "\x01"
    case data[1]
    when "\x03"  # fast_auth_success
      # OK
    when "\x04"  # perform_full_authentication
      if @protocol.client_flags & CLIENT_SSL != 0
        @protocol.write passwd+"\0"
      elsif !@protocol.get_server_public_key
        raise 'Authentication requires secure connection'
      else
        @protocol.write "\2"  # request public key
        pkt = @protocol.read
        pkt.utiny # skip
        pubkey = pkt.to_s
        hash = (passwd+"\0").unpack("C*").zip(scramble.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
        enc = OpenSSL::PKey::RSA.new(pubkey).public_encrypt(hash, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
        @protocol.write enc
      end
    else
      raise "invalid auth reply packet: #{data.inspect}"
    end
    pkt = @protocol.read
  end
  return pkt
end
hash_password(passwd, scramble) click to toggle source

@param passwd [String] @param scramble [String] @return [String] hashed password

# File lib/mysql/authenticator/caching_sha2_password.rb, line 53
def hash_password(passwd, scramble)
  return '' if passwd.nil? or passwd.empty?
  hash1 = Digest::SHA256.digest(passwd)
  hash2 = Digest::SHA256.digest(hash1)
  hash3 = Digest::SHA256.digest(hash2 + scramble)
  hash1.unpack("C*").zip(hash3.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
end
name() click to toggle source

@return [String]

# File lib/mysql/authenticator/caching_sha2_password.rb, line 12
def name
  'caching_sha2_password'
end