Método de autenticação HTTP DIGEST
Documentação detalhada: WWW-Authenticate - HTTP | MDN (mozilla.org)
1.O que é
A Autenticação Digest é um método de autenticação usado para verificar a identidade do usuário nas comunicações de rede. É usado principalmente em HTTP e outros protocolos da camada de aplicação.
A autenticação Digest é mais segura que a autenticação básica porque não transmite diretamente senhas em texto não criptografado. Mas também não é uma solução de segurança completa, pois ainda é possível ser atacado em situações como ataques man-in-the-middle. Nas redes modernas, um método de autenticação mais seguro é geralmente um mecanismo de autenticação baseado em token.
2. Processo de avaliação
Semelhante ao processo de certificação básico:
O processo geral de certificação Digest é o seguinte:
-
O cliente envia uma solicitação: O cliente envia uma solicitação ao servidor, e a solicitação contém o caminho para o recurso que precisa ser acessado.
-
O servidor retorna informações de desafio: Após receber a solicitação do cliente, o servidor retorna uma informação de “desafio” (Desafio) ao cliente. Essas informações de desafio são uma sequência que contém um número aleatório, um nome de região e outros parâmetros.
-
O cliente gera resposta: o cliente usa o nome de usuário, a senha e as informações de desafio para gerar uma sequência de resposta. O processo de geração desta sequência de resposta inclui as seguintes etapas:
- Concatenação: Separe o nome de usuário, o nome do domínio e a senha com dois pontos e concatene-os em uma única string.
- Hash da string: Faça hash da string concatenada acima, geralmente usando algoritmos de hash como MD5 ou SHA-1.
-
O cliente envia uma resposta: O cliente envia a string de resposta gerada ao servidor e a coloca no cabeçalho “Autorização” da solicitação.
-
Resposta de verificação do servidor: depois que o servidor recebe a resposta do cliente, ele usa o mesmo método para regenerar a sequência de resposta no lado do servidor. A string de resposta enviada pelo cliente é então comparada com a string de resposta gerada pelo servidor. Se forem iguais, o cliente possui o nome de usuário e a senha corretos.
-
O servidor retorna uma resposta: Se o servidor autenticar com sucesso, ele retornará o conteúdo do recurso solicitado ao cliente e incluirá uma identificação de autenticação bem-sucedida no cabeçalho da resposta.
2.1 Cliente envia solicitação
A primeira solicitação do cliente.
2.2 O servidor retorna as informações do desafio
2.2.1 Parâmetros do desafio
-
qop: Uma string entre aspas indicando o nível de proteção suportado pelo servidor. Isto deve ser fornecido e as opções não reconhecidas devem ser ignoradas.
-
"auth"
:Autenticação"auth-int"
: Autenticação totalmente protegida
-
nonce: uma string entre aspas especificada pelo servidor que o servidor pode usar para verificar as credenciais especificadas durante cada resposta 401. Isso deve ser gerado exclusivamente em cada resposta 401 e pode ser regenerado com mais frequência (por exemplo, permitindo que um resumo seja usado apenas uma vez). Esta especificação contém recomendações sobre o algoritmo para gerar este valor. O valor nonce é opaco para o cliente.
-
opaco: uma string entre aspas especificada pelo servidor que deve ser
Authorization
retornada inalterada em . Isso é opaco para o cliente. É recomendado que o servidor contenha dados Base64 ou hexadecimais. -
<realm>
(Opcional) Uma string indicando o nome de usuário/senha a ser usado. No mínimo, o nome do host deve ser incluído, mas pode indicar usuários ou grupos com acesso. -
domain
(Opcional) Uma lista de prefixos URI separados por espaço que define todos os locais onde as informações de autenticação podem ser usadas. Se esta palavra-chave não for especificada, as informações de autenticação poderão ser usadas em qualquer lugar na raiz da web. -
stale
(Opcional) Um sinalizador que não diferencia maiúsculas de minúsculas indicando ao cliente que a solicitação anteriornonce
foi rejeitada porque era muito antiga (expirada). Nesse caso , você pode tentar novamente a solicitaçãotrue
usando o novo nome de usuário/senha criptografados.nonce
Se for qualquer outro valor, o nome de usuário/senha é inválido e deve ser solicitado novamente ao usuário. -
algorithm
(Opcional) O algoritmo usado para gerar um resumo. Os valores válidos fora da sessão são:"MD5"
(padrão se não for especificado),"SHA-256"
,"SHA-512"
. Os valores de sessão válidos são:"MD5-sess"
,"SHA-256-sess"
,"SHA-512-sess"
. -
charset="UTF-8"
(Opcional) Informe ao cliente o esquema de codificação preferido do servidor ao enviar um nome de usuário e uma senha. Os únicos valores permitidos são strings "UTF-8" que não diferenciam maiúsculas de minúsculas. -
userhash
(Opcional) O servidor pode ser especificado para"true"
indicar que suporta hash de nome de usuário (o padrão é"false"
).
2.2.2 Exemplos de questionamentos
O cliente está tentando acessar http://www.example.org/dir/index.html
o documento em , que é protegido pela autenticação digest. O nome de usuário deste documento é "Mufsas" e sua senha é "Círculo da Vida". Na primeira vez que um cliente solicita o documento, nenhum Authorization
campo de cabeçalho é enviado. Aqui, o servidor responde com uma mensagem HTTP 401, que inclui um desafio para cada algoritmo de resumo que suporta, em ordem de precedência ( SHA256
, então MD5
).
O servidor coloca as informações do desafio no cabeçalho de resposta WWW-Authenticate e as envia ao cliente, conforme mostrado no exemplo a seguir:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest
realm="[email protected]",
qop="auth, auth-int",
algorithm=SHA-256,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
WWW-Authenticate: Digest
realm="[email protected]",
qop="auth, auth-int",
algorithm=MD5,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
2.3 Cliente gera resposta
O cliente recebe uma resposta 401 indicando que a autenticação é necessária, o cliente solicita ao usuário seu nome de usuário e senha e, em seguida, responde com uma nova solicitação que criptografa as credenciais no campo do cabeçalho Authorization
. Se o cliente escolher o resumo MD5, Authorization
os campos de cabeçalho poderão ter esta aparência:
Authorization: Digest username="Mufasa",
realm="[email protected]",
uri="/dir/index.html",
algorithm=MD5,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
nc=00000001,
cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",
qop=auth,
response="8ca523f5e9506fed4657c9700eebdbec",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
Se o cliente escolher o resumo SHA-256, Authorization
o cabeçalho poderá ter esta aparência:
Authorization: Digest username="Mufasa",
realm="[email protected]",
uri="/dir/index.html",
algorithm=SHA-256,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
nc=00000001,
cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",
qop=auth,
response="753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
2.4 Resposta de verificação do servidor
Depois que o servidor recebe a resposta do cliente, ele usa o mesmo método para reproduzir a sequência de resposta no lado do servidor. A string de resposta enviada pelo cliente é então comparada com a string de resposta gerada pelo servidor. Se forem iguais, o cliente possui o nome de usuário e a senha corretos.
2.5 O servidor retorna uma resposta
Se o servidor autenticar com sucesso, ele retornará o conteúdo do recurso solicitado ao cliente e incluirá uma identificação de autenticação bem-sucedida no cabeçalho de resposta.
3. Algoritmo
De acordo com o valor no corpo da solicitação algorithm
:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest
realm="[email protected]",
qop="auth, auth-int",
algorithm=SHA-256,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
A seguir está a descrição no documento padrão, da RFC 7616: HTTP Digest Access Authentication (rfc-editor.org) :
Uma string que indica um algoritmo usado para produzir o resumo e um resumo sem chave. Se não estiver presente, presume-se que seja “MD5”. Se o algoritmo não for compreendido, o desafio DEVE ser ignorado (e utilizado um diferente, se houver mais de um). Quando utilizado com o mecanismo Digest, cada um dos algoritmos possui duas variantes: variante de sessão e variante sem sessão. A variante sem sessão é indicada por “”, por exemplo, “SHA-256”, e a variante de sessão é indicada por “-sess”, por exemplo, “SHA-256-sess”.
Neste documento, a string obtida pela aplicação do algoritmo de digestão aos dados “dados” com segredo “secreto” será denotada por KD (segredo, dados), e a string obtida pela aplicação do algoritmo de digestão sem chave aos dados “dados” será ser denotado H(dados). KD significa Keyed Digest, e a notação unq(X) significa o valor da string entre aspas X sem as aspas circundantes e com as barras de aspas removidas.
For "<algorithm>" and "<algorithm>-sess"
H(data) = <algorithm>(data)
and
KD(secret, data) = H(concat(secret, ":", data))
For example:
For the "SHA-256" and "SHA-256-sess" algorithms
H(data) = SHA-256(data)
For the "MD5" and "MD5-sess" algorithms
H(data) = MD5(data)
ou seja, o resumo é o “” do segredo concatenado com dois pontos concatenados com os dados. O “-sess” tem como objetivo permitir servidores eficientes de autenticação de terceiros; para a diferença de uso, consulte a descrição na Seção 3.4.2.
Uma breve explicação:
- KD (segredo, dados) é a criptografia do algoritmo após concatenação
secret
edata
com dois pontos.:
secret:data
- H (dados) é criptografar diretamente os dados com o algoritmo
- unq(username) é uma string sem aspas
3.1 SHA-256
Podemos nos referir a RFC 7616: Autenticação de acesso HTTP Digest (rfc-editor.org)
3.1.1 Resposta
Se o valor qop for “auth” ou “auth-int”:
response = KD(H(A1),unq(nonce):nc:unq(cnonce):unq(qop):H(A2))
Veja abaixo as definições para A1 e A2.
3.1.2 A1
Se o valor do parâmetro do algoritmo for “”, por exemplo, “SHA-256”,então A1 é:
A1 = unq(username):unq(realm):passwd
where passwd = < user's password >
Se o valor do parâmetro do algoritmo for “-sess”, por exemplo, “SHA-256-sess”, então A1 é calculado usando o valor nonce fornecido no desafio do servidor, e o valor cnonce da solicitação do cliente após o recebimento de um Desafio WWW-Authenticate do servidor. Ele usa o nonce do servidor desse desafio, aqui denominado nonce-prime, e o valor nonce do cliente da resposta, aqui denominado cnonce-prime, para construir A1 da seguinte forma:
A1 = H(unq(username):unq(realm):passwd):unq(nonce-prime):unq(cnonce-prime)
Isso cria uma “chave de sessão” para a autenticação de solicitações e respostas subsequentes que é diferente para cada “sessão de autenticação”, limitando assim a quantidade de material criptografado com qualquer chave. (Nota: veja uma discussão mais detalhada sobre a sessão de autenticação na Seção 3.6.) Como o servidor só precisa usar o hash das credenciais do usuário para criar o valor A1, esta construção pode ser usada em conjunto com um serviço de autenticação de terceiros, de modo que que o servidor web não precisaria do valor real da senha. A especificação de tal protocolo está além do escopo desta especificação.
3.1.3A2
Se o valor do parâmetro qop for “auth” ou não for especificado, então A2 será:
A2 = Method:request-uri
Se o valor qop for “auth-int”, então A2 é:
A2 = Method:request-uri:H(entity-body)
3.2 MD5
Podemos nos referir a RFC 2617 - Autenticação HTTP: Autenticação de acesso básica e resumida (ietf.org)
3.2.1 Solicitação-Resumo
Se o valor “qop” for “auth” ou “auth-int”:
request-digest = KD(H(A1), unq(nonce-value):nc-value:unq(cnonce-value):unq(qop-value):H(A2))
Se a diretiva “qop” não estiver presente (esta construção é para compatibilidade com RFC 2069):
request-digest = KD(H(A1), unq(nonce-value):H(A2))
Veja abaixo as definições para A1 e A2.
3.2.2A1
Se o valor da diretiva “algoritmo” for “MD5” ou não for especificado, então A1 é:
A1 = unq(username-value):unq(realm-value):passwd
where passwd = < user's password >
Se o valor da diretiva do “algoritmo” for “MD5-sess”, então A1 será calculado apenas uma vez - na primeira solicitação do cliente após o recebimento de um desafio WWW-Authenticate do servidor. Ele usa o nonce do servidor desse desafio e o primeiro valor nonce do cliente para construir A1 da seguinte maneira:
A1 = H(unq(username-value):unq(realm-value):passwd):unq(nonce-value):unq(cnonce-value)
Isto cria uma 'chave de sessão' para a autenticação de solicitações e respostas subsequentes que é diferente para cada “sessão de autenticação”, limitando assim a quantidade de material criptografado com qualquer chave. (Nota: veja uma discussão mais detalhada sobre a sessão de autenticação na seção 3.3.) Como o servidor só precisa usar o hash das credenciais do usuário para criar o valor A1, esta construção poderia ser usada em conjunto com um serviço de autenticação de terceiros para que o servidor web não precisaria do valor real da senha. A especificação de tal protocolo está além do escopo desta especificação.
3.2.3 A2
Se o valor da diretiva “qop” for “auth” ou não for especificado, então A2 é:
A2 = Method:digest-uri-value
Se o valor “qop” for “auth-int”, então A2 é:
A2 = Method:digest-uri-value:H(entity-body)
4.Exemplos
Também usamos o exemplo acima para realizar o processamento do algoritmo. algorithm
Se nenhum valor for atribuído, será o padrão MD5
. O nome de usuário ainda será usado Mufasa
e a senha será usada 123456
:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest
realm="[email protected]",
qop="auth",
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
resposta:
Authorization: Digest username="Mufasa",
realm="[email protected]",
uri="/dir/index.html",
algorithm=MD5,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
nc=00000001,
cnonce="nvlfh1ra",
qop=auth,
response="7bddc3c7fceb317dc002c524187fa170",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
Algoritmo completo, aqui devemos prestar muita atenção se há aspas duplas:
// A1 = unq(username-value):unq(realm-value):passwd
String A1 = StrUtil.format("{}:{}:\"{}\"", "Mufasa", "[email protected]", "123456");
// A2 = Method:digest-uri-value
String A2 = StrUtil.format("\"{}\":\"{}\"", "POST", "/dir/index.html");
// request-digest = KD(H(A1), unq(nonce-value):nc-value:unq(cnonce-value):unq(qop-value):H(A2))
String HA1 = SecureUtil.md5(A1);
String HA2 = SecureUtil.md5(A2);
String responseStr = StrUtil.format("\"{}\":{}:\"{}\":{}:{}:\"{}\"", HA1, "7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v","00000001", "nvlfh1ra", "auth", HA2);
String response = SecureUtil.md5(responseStr);