class Rack::Auth::Digest::MD5


opaque needs to be set to a constant base64/hexadecimal string.
and a block that looks up a plaintext password for a given username.
Initialize with the [Rack] application that you want protecting,
HTTP Digest Authentication, as per RFC 2617.
Rack::Auth::Digest::MD5 implements the MD5 algorithm version of

def A1(auth, password)

def A1(auth, password)
  "#{auth.username}:#{auth.realm}:#{password}"
end

def A2(auth)

def A2(auth)
  "#{auth.method}:#{auth.uri}"
end

def KD(secret, data)

def KD(secret, data)
  H "#{secret}:#{data}"
end

def call(env)

def call(env)
  auth = Request.new(env)
  unless auth.provided?
    return unauthorized
  end
  if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth)
    return bad_request
  end
  if valid?(auth)
    if auth.nonce.stale?
      return unauthorized(challenge(stale: true))
    else
      env['REMOTE_USER'] = auth.username
      return @app.call(env)
    end
  end
  unauthorized
end

def challenge(hash = {})

def challenge(hash = {})
  "Digest #{params(hash)}"
end

def digest(auth, password)

def digest(auth, password)
  password_hash = passwords_hashed? ? password : H(A1(auth, password))
  KD password_hash, "#{auth.nonce}:#{auth.nc}:#{auth.cnonce}:#{QOP}:#{H A2(auth)}"
end

def initialize(app, realm = nil, opaque = nil, &authenticator)

def initialize(app, realm = nil, opaque = nil, &authenticator)
  @passwords_hashed = nil
  if opaque.nil? and realm.respond_to? :values_at
    realm, opaque, @passwords_hashed = realm.values_at :realm, :opaque, :passwords_hashed
  end
  super(app, realm, &authenticator)
  @opaque = opaque
end

def md5(data)

def md5(data)
  ::Digest::MD5.hexdigest(data)
end

def params(hash = {})

def params(hash = {})
  Params.new do |params|
    params['realm'] = realm
    params['nonce'] = Nonce.new.to_s
    params['opaque'] = H(opaque)
    params['qop'] = QOP
    hash.each { |k, v| params[k] = v }
  end
end

def passwords_hashed?

def passwords_hashed?
  !!@passwords_hashed
end

def valid?(auth)

def valid?(auth)
  valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
end

def valid_digest?(auth)

def valid_digest?(auth)
  pw = @authenticator.call(auth.username)
  pw && Rack::Utils.secure_compare(digest(auth, pw), auth.response)
end

def valid_nonce?(auth)

def valid_nonce?(auth)
  auth.nonce.valid?
end

def valid_opaque?(auth)

def valid_opaque?(auth)
  H(opaque) == auth.opaque
end

def valid_qop?(auth)

def valid_qop?(auth)
  QOP == auth.qop
end