A um tempo atras precisei implementar uma receita do Yocto Project onde alguns usuários deveriam ser criados, porém enfrentei dois problemas.
1) Teria que criar algumas senhas e criptografar elas e como eram usuários Unix teria que ser no formato “compativel” com /etc/shadow
2) Pode ser que o operador pude-se adicionar a senha ou alterar sem criar usuário e/ou executar um passwd
Sem muito esforço já havia utilizado a crypt.h em C e nativamente o Python possui o modulo crypt, deve-se atentar sobre as versões Python 2.6, 2.7, 3.2 e Python 3.3 ou superior, pois na versão <= 3.2 existe uma implementação e na versão superior a 3.2 possui a mesma porém com alguns adendos, da implementação do crypt usando Python 2.6, 2.7 ou 3.2 irá funcionar nas versões mais nova o contrario não.
Olhe nos links abaixo a diferença.
https://docs.python.org/2/library/crypt.html
https://docs.python.org/3.3/library/crypt.html
Vamos ao primeiro exemplo básico e já funcional:
#! /usr/bin/python import crypt def gerar_passwd(): minha_senha = raw_input('Digite a senha: ') senha_gerada = crypt.crypt(minha_senha, "$6$SalG4ndo$") return senha_gerada if __name__ == '__main__': print gerar_passwd()
Executando o script acima e para a senha 123456:
$ python gerarsenha.py Digite a senha: 123456 $6$SalG4ndo$sS2p7vKgvM/vEsKrceXlFe.9YAbDz4jB7ify.l0FEK84jHGAt5UUqkJWRNhwTv0WfyW $ sudo cat /etc/shadow | grep user1 user1:$6$SalG4ndo$sS2p7vKgvM/vEsKrceXlFe.9YAbDz4jB7ify.l0FEK84jHGAt5UUqkJWRNhwTv0WfyW:16441:0:99999:7:::
Ok, bateu, mas que magia negra é aquele “$6$SalG4ndo$“? Vamos ver agora.
Primeiro que não foi de primeira que cheguei no hash que esperava, e segundo que houve uma analise necessária para obter os parâmetros corretos para gerar o hash correto para o /etc/shadow em uso que pode variar e deve-se atentar aos 3 itens a seguir.
1) Verificar no seu Linux qual o método de encriptação configurado, pode obter facilmente com o comando abaixo:
$ cat /etc/login.defs | grep ^ENCRYPT_METHOD ENCRYPT_METHOD SHA512
2) Eu não comentei do crypt do Linux? Vamos ver este cara que é a base para entendermos o crypt do Python
$ man 3 crypt ... NOTES Glibc notes The glibc2 version of this function supports additional encryption algorithms. If salt is a character string starting with the characters "$id$" followed by a string terminated by "$": $id$salt$encrypted then instead of using the DES machine, id identifies the encryption method used and this then determines how the rest of the password string is interpreted. The following values of id are supported: ID | Method ───────────────────────────────────────────────────────── 1 | MD5 2a | Blowfish (not in mainline glibc; added in some | Linux distributions) 5 | SHA-256 (since glibc 2.7) 6 | SHA-512 (since glibc 2.7) So $5$salt$encrypted is an SHA-256 encoded password and $6$salt$encrypted is an SHA-512 encoded one. "salt" stands for the up to 16 characters following "$id$" in the salt. The encrypted part of the password string is the actual computed password. The size of this string is fixed: MD5 | 22 characters SHA-256 | 43 characters SHA-512 | 86 characters The characters in "salt" and "encrypted" are drawn from the set [a–zA–Z0–9./]. In the MD5 and SHA implementations the entire key is significant (instead of only the first 8 bytes in DES).
Eu cortei boa parte do man e peguei apenas o que analisei para entender do que precisaria. Pode ver completo no link a seguir.
http://linux.die.net/man/3/crypt
3) Precisaria então algo assim no crypt do Python:
#! /usr/bin/python print crypt.crypt("123456","$6$salt$") """ Onde: "123456" minha senha $6 defini ser SHA512 que vi no ENCRYPT_METHOD do /etc/login.defs $salt string para "salgar" atrapalhar o algoritmo para gerar o hash da senha """
Você pode ser mais hardcore e fazer direto no terminal com Python, usando o poder/facilidade do Python para isso:
$ python -c 'import crypt; print crypt.crypt("123456","$6$salt$")' $6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w.igcOo1R7vBYR65JquIQ/7siC7VRpmteKvZmfSkNc69.
Então os métodos disponíveis e mais usados são:
$1 : MD5
$5 : SHA256
$6 : SHA512
$salt : String para embaralhar
Eu nunca usei “salt” como string, alguns casos gerei randomicamente, adaptei nosso primeiro exemplo para o a seguir onde a string salt é gerada randomicamente com 16 caracteres e estou usando encode base-64 ([A-Za-z0-9], “/” e “+”), pode usar outros modos de encode como hex para hexadecimal, e logo em seguida eu fatio do 2º ao 9º caractere ficando com 8 caracteres e adiciono $6$ e $ ao final da string.
#! /usr/bin/python import crypt import os """ @Generate random string to salt with 8 characters """ custom_salt = "$6$"+os.urandom(16).encode('base64')[2:10]+"$" def gerar_passwd(): minha_senha = raw_input('Digite a senha: ') print("Salt: %s" % custom_salt) hash_senha = crypt.crypt(minha_senha,custom_salt) return hash_senha if __name__ == '__main__': print("HASH: %s" % gerar_passwd())
Executando:
$ python gerarsenha.py Digite a senha: 123456 Salt: $6$HLqZzbwe$ HASH: $6$HLqZzbwe$/DPwX2tsKDpigk0yYNw9RAO65BBS5nWeqmYJbvHpM/hR8j6mwOE5gqrC2ORC1siWJY7UfJOmd9B8xwBfyPh.d1
E assim ficou o script dentro da distribuição que gerei com Yocto Project e que também pode ser chamada para as senhas dos usuários já criados e que pode ser utilizado para qualquer Linux.
Espero que tenham gostado, futuramente em um artigo de Yocto Project vou mostrar como adicionar um usuário e poder já inserir esta senha criada em uma receita.
Até a próxima!
Referências
https://docs.python.org/2/library/crypt.html
https://docs.python.org/3.3/library/crypt.html
http://linux.die.net/man/3/crypt
http://cleitonbueno.com/yocto-project-introducao/
http://www.gnu.org/software/libc/manual/html_node/crypt.html
Python – Criando senhas criptografadas para usuários Linux by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.