Pergunta

Em primeiro lugar, o contexto: Eu estou tentando criar uma ferramenta baseada em linha de comando (Linux) que requer login. Contas sobre esta ferramenta tem nada a ver com sistema de nível de contas -. nenhum dos Isto olha / etc / passwd

Estou a planear usuário armazenar contas em um arquivo de texto usando o mesmo formato (mais ou menos) como / etc / passwd.

Apesar de não usar os arquivos de senha de nível de sistema, usando cripta parecia para ser uma boa prática para o uso, ao invés de armazenar senhas em Texto claro. (Enquanto cripta é certamente melhor do que o armazenamento em senhas cleartext, estou aberto a outras maneiras de fazer isso.)

Meu conhecimento cripta é baseado no seguinte: https://docs.python.org/2/library/crypt.html

A documentação parece pedir algo que não é possível: "ele É recomendável usar a senha crypted completo como sal ao verificar para uma senha. "

Huh? Se eu estou criando a senha crypted (como, ao criar um usuário registro) como posso usar a senha encriptada como um sal? isto não existe ainda. (Estou assumindo que você deve usar o mesmo sal para a criação e verificação de uma senha.)

Eu tentei usar a senha de texto como um sal. Isso faz funcionar, mas tem dois problemas; um facilmente superada, e um sério:

1) As duas primeiras letras da senha de texto estão incluídos no crypted password. Você pode corrigir isto não escrever os dois primeiros caracteres para o arquivo:

user_record = '%s:%s:%s' % (user_name, crypted_pw[2:], user_type)

2) usando a senha de texto simples como o sal, você pareceria ser reduzir a quantidade de entropia no sistema. Possivelmente eu sou mal-entendido a propósito do sal.

A melhor prática eu tenho sido capaz de obter é usar os dois primeiros caracteres a partir do nome de utilizador na forma de sal. Será que isso é apropriado, ou há algo que eu perdi que faz que uma má jogada?

O meu entendimento de um sal é que ele impede a senha pré-computação hashes de um dicionário. Eu poderia usar um sal padrão para todos senhas (como as minhas iniciais, "JS"), mas que parece ser menos de um fardo para um atacante do que usar dois caracteres de nome de usuário de cada usuário.

Foi útil?

Solução

Para a utilização do módulo cripta:

Ao gerar a senha crypted, você fornecer o sal. Ele poderia muito bem ser aleatório para aumentar a resistência à bruta-forçando, desde que respeite as condições referidas. Ao verificar uma senha, você deve fornecer o valor de getpwname, no caso de você estiver em um sistema que os tamanhos e sal suportes maiores não gerou-lo sozinho.

Comentários gerais:

Se isto não tem nada a ver w / logins do sistema real, não há nada impedindo que você use um método mais forte do que cripta. Pode-se gerar aleatoriamente N caracteres de sal por pelo utilizador, para ser combinado com palavra-passe do utilizador num hash SHA-1.

string_to_hash = user.stored_salt + entered_password
successful_login = (sha1(string_to_hash) == user.stored_password_hash)

UPDATE: Embora este seja muito mais seguro contra tabelas do arco-íris, o método acima ainda tem deficiências criptográficas. aplicação correcta de um algoritmo HMAC pode aumentar ainda mais a sua segurança, mas está além do meu domínio de especialização.

Outras dicas

A cripta de Python () é um wrapper para a função do sistema de crypt (). A partir da página man Linux crypt ():

char *crypt(const char *key, const char *salt);

key is a user’s typed password.
salt is a two-character string chosen from the set [a–zA–Z0–9./]. 
This string is used to perturb the algorithm in one of 4096 
different ways.

A ênfase está em " de dois caracteres string". Agora, se você olhar para crypt () 's comportamento em Python:

>>> crypt.crypt("Hello", "World")
'Wo5pEi/H5/mxU'
>>> crypt.crypt("Hello", "ABCDE")
'AB/uOsC7P93EI'

você descobre que os dois primeiros caracteres do resultado sempre coincidem com os dois primeiros caracteres do sal original, que na verdade formam o verdadeiro si de dois caracteres-sal. Ou seja, o resultado da cripta () tem a forma 2char-sal +-passe encriptada. Assim, não há diferença no resultado se, em vez de passar o de dois caracteres-sal ou a muitos-personagens-sal original que você passar a senha criptografada todo.

Nota: o conjunto [a-zA-Z0-9./] contém 64 caracteres, e de 64 * 64 = 4096. Veja como dois personagens se relacionam com " 4096 maneiras diferentes".

Você está mal-entendido a documentação; ele diz que desde que o comprimento do sal pode variar dependendo da implementação cripta subjacente (), você deve fornecer toda a senha encriptada como o valor sal ao verificar senhas . Ou seja, em vez de puxar os dois primeiros caracteres fora para ser o sal, simplesmente atirar na coisa toda.

A sua ideia de ter o sal inicial basear-se no nome de usuário parece bem.

Aqui estão alguns conselhos gerais sobre senhas de salga:

  1. Em geral, os sais são usados ??para fazer ranbow tabelas muito caro para calcular. Assim, você deve adicionar um pouco de sal randomizado para todos os seus hashes de senha, e apenas armazená-lo em texto simples ao lado do valor hash de senha.
  2. HMAC - é um bom padrão, e é mais seguro do que concatenar a senha e sal.
  3. Use SHA1: MD5 é quebrado. Sem querer ofender se você soubesse isso, apenas estar completa. ;)

I não iria tem o sal ser uma função da senha. Um invasor teria que gerar uma tabela de arco-íris de ter um banco de dados instantânea pesquisa de senhas, mas eles só teria que fazer isso uma vez. Se você escolher um inteiro de 32 bits aleatórios, eles teriam que gerar 2 ^ 32 mesas, que (ao contrário de um sal determinista) custa maneira, de forma demasiada memória (e tempo).

Para alguns maior resistência, você pode obter o módulo cripta para uso md5 usando um sal no formato.

$1$ABCDEFGH$

onde ABCDEFGH é sua seqüência de sal.

>>> p = crypt.crypt('password', '$1$s8Ty3/f$')
>>> p
Out: '$1$s8Ty3/f$0H/M0JswK9pl3X/e.n55G1'
>>> p == crypt.crypt('password', p)
Out: True

(note que esta é uma extensão GNU a cripta, consulte "homem crypt" em um sistema Linux). MD5 (e agora até mesmo SHA1) pode ser "quebrado", mas eles ainda são relativamente bom para os hashes de senha, e MD5 ainda é o padrão para Linux senhas locais.

A palavra-passe, ou qualquer coisa derivada da senha, nunca deve ser usado como sal. O sal de uma senha especial deve ser imprevisível.

Um nome de usuário ou parte do nome de usuário é tolerável, mas melhor ainda seria bytes aleatórios de uma RNG criptográfica.

Use PBKDF2, consulte este comentário em um segmento diferente ( inclui a implementação Python).

Dê uma olhada no artigo TrueCrypt explicou por Björn Edström . Ele contém fácil de entender a explicação de como truecrypt funciona e uma implementação simples Python de algumas das funcionalidades do truecrypt incluindo gerenciamento de senha .

Ele está falando sobre o módulo Python crypt (), não sobre TrueCrypt em Python

Padrão crypt.crypt() em Python 2 não é muito seguro e o artigo explica como alternativas mais seguras poderia funcionar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top