finalizando trab 2
This commit is contained in:
parent
9fafd82b5c
commit
428122f04e
|
@ -0,0 +1,2 @@
|
||||||
|
*.dat
|
||||||
|
__pycache__
|
|
@ -1,88 +1,76 @@
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
import localtoken
|
import localtoken
|
||||||
|
import os
|
||||||
'''
|
import time
|
||||||
Gerador:
|
|
||||||
Primeira vez criar
|
|
||||||
um usuário
|
|
||||||
uma senha semente (Senha igual a registrada no servidor, senha principal)
|
|
||||||
Um salt (o mesmo do Aplicativo)
|
|
||||||
uma senha local (Senha para acesso ao gerador de senhas somente)
|
|
||||||
Próximas vezes
|
|
||||||
Digitar usuário e a senha local, se correto continua.
|
|
||||||
Quando requisitado gera uma senha(Token).
|
|
||||||
(algoritmo gerador de senhas)
|
|
||||||
A senha (Token) deve ser gerada a partir da hash da senha semente do usuário (diferente da senha do usuário).
|
|
||||||
O aluno deve propor uma variante do algoritmo OTP de Lamport, visto em aula.
|
|
||||||
Este algoritmo deve levar em consideração o tempo (data hora minuto).
|
|
||||||
As senhas devem ter validade de no máximo um minuto e só podem ser usadas uma única vez.(Fazer uma lista de senhas para ser usada no minuto. Ex.lista com 5 senhas para o minuto solicitado)
|
|
||||||
somente gerar lista de senhas para o minuto solicitado.
|
|
||||||
|
|
||||||
Servidor:
|
|
||||||
Quando acessado usa o mesmo algoritmo gerador de senhas anterior. Mas em instância separada.
|
|
||||||
A lista de senha gerada será a mesma nas duas partes, apesar de estarem em aplicativos separados e sem comunicação.
|
|
||||||
Verifica o usuário e se senha digitada esta na lista gerada e não foi usada e nem invalidada.
|
|
||||||
nesta caso apresenta “Chave válida”.
|
|
||||||
Atenção:
|
|
||||||
As senhas devem ter validade de no máximo um minuto e só podem ser usadas uma única vez.
|
|
||||||
Senhas são geradas a partir de outras senhas, e se for usada uma chave todas as chaves geradas pela mesma devem ser invalidadas.
|
|
||||||
Se o cliente digitar uma senha válida o servidor aceita, caso contrario retorna mensagem de erro.
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
USER = ''
|
|
||||||
LOCAL_PASSWORD = ''
|
|
||||||
SEED_PASSWORD = ''
|
|
||||||
SALT = ''
|
|
||||||
|
|
||||||
def check_setup():
|
|
||||||
try:
|
|
||||||
with open('gerador.dat', 'r', newline='') as setup:
|
|
||||||
lines = setup.readlines()
|
|
||||||
if len(lines) != 4:
|
|
||||||
return False
|
|
||||||
|
|
||||||
USER = lines[0]
|
|
||||||
LOCAL_PASSWORD = lines[1]
|
|
||||||
SEED_PASSWORD = lines[2]
|
|
||||||
SALT = lines[3]
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
init_setup()
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def init_setup():
|
def init_setup():
|
||||||
with open('gerador.dat', 'w', newline='') as setup:
|
with open('gerador.dat', 'a', newline='') as setup:
|
||||||
user = input('Digite o usuário: ')
|
user = input('Digite o usuário: ')
|
||||||
local_password = sha256(input('Digite a senha local: ').encode('utf-8')).hexdigest()
|
local_password = sha256(input('Digite a senha local: ').encode('utf-8')).hexdigest()
|
||||||
seed_password = sha256(input('Digite a senha semente: ').encode('utf-8')).hexdigest()
|
seed_password = sha256(input('Digite a senha semente: ').encode('utf-8')).hexdigest()
|
||||||
salt = sha256(input('Digite o salt: ').encode('utf-8')).hexdigest()
|
salt = input('Digite o salt: ')
|
||||||
setup.write(user + '\n')
|
salted_password = localtoken.get_salted_password(seed_password, salt)
|
||||||
setup.write(local_password + '\n')
|
|
||||||
setup.write(seed_password + '\n')
|
|
||||||
setup.write(salt)
|
|
||||||
|
|
||||||
def check_password():
|
line = f'{user},{local_password},{salted_password}\n'
|
||||||
local_password = sha256(input('Digite a senha local: ').encode('utf-8')).hexdigest()
|
setup.write(line)
|
||||||
if local_password == LOCAL_PASSWORD:
|
|
||||||
return True
|
print(f'Usuário [{user}] registrado com sucesso!')
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def generate_token():
|
def generate_token():
|
||||||
token = localtoken.generate_token(SEED_PASSWORD, SALT)
|
user = input('Digite o usuário: ')
|
||||||
print('Token gerado: ' + token[:8])
|
local_password = sha256(input('Digite a senha local: ').encode('utf-8')).hexdigest()
|
||||||
|
salted_password = ''
|
||||||
|
with open('gerador.dat', 'r', newline='') as setup:
|
||||||
|
for line in setup:
|
||||||
|
line = line.replace('\n', '')
|
||||||
|
|
||||||
def main():
|
if line.split(',')[0] == user and line.split(',')[1] == local_password:
|
||||||
if check_setup():
|
salted_password = line.split(',')[2]
|
||||||
if check_password():
|
break
|
||||||
input('Pressione alguma tecla para gerar uma senha...')
|
|
||||||
generate_token()
|
|
||||||
else:
|
else:
|
||||||
print('Usuário ou senha incorretos!')
|
print('Usuário ou senha incorretos!')
|
||||||
else:
|
return
|
||||||
print('Erro ao verificar setup!')
|
|
||||||
|
loop_token(user, salted_password)
|
||||||
|
|
||||||
|
def loop_token(user, salted_password):
|
||||||
|
while True:
|
||||||
|
print(f'Gerando token para [{user}]...')
|
||||||
|
tokens = [localtoken.generate_token(salted_password)]
|
||||||
|
for i in range(4):
|
||||||
|
tokens.append(localtoken.generate_token(tokens[-1]))
|
||||||
|
|
||||||
|
for token in tokens:
|
||||||
|
print(token[:8])
|
||||||
|
|
||||||
|
# sleep until next minute
|
||||||
|
time.sleep(60 - time.time() % 60 + 1)
|
||||||
|
|
||||||
|
# clear console
|
||||||
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
while True:
|
||||||
|
print('Selecione uma opção:')
|
||||||
|
print('1 - Registrar usuário')
|
||||||
|
print('2 - Gerar token')
|
||||||
|
print('0 - Sair')
|
||||||
|
option = input('Opção: ')
|
||||||
|
|
||||||
|
if option == '1':
|
||||||
|
init_setup()
|
||||||
|
elif option == '2':
|
||||||
|
generate_token()
|
||||||
|
elif option == '0':
|
||||||
|
exit()
|
||||||
|
|
||||||
|
def exit():
|
||||||
|
print('Saindo...')
|
||||||
|
quit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
if not os.path.exists('gerador.dat'):
|
||||||
|
open('gerador.dat', 'w').close()
|
||||||
|
|
||||||
main()
|
main()
|
|
@ -1,7 +1,29 @@
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# password = hashed password
|
# token = hashed password + hashed salt
|
||||||
def generate_token(password, salt):
|
def generate_token(token):
|
||||||
time = time.strftime('%d%m%Y%H%M')
|
time = get_timestamp()
|
||||||
token = sha256((password + salt + time).encode('utf-8')).hexdigest()
|
token = sha256((token + time).encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
|
return token
|
||||||
|
|
||||||
|
# password = hashed seed password
|
||||||
|
# salt = hashed salt
|
||||||
|
def get_salted_password(password, salt):
|
||||||
|
return sha256((password + salt).encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
|
def validate_token(salted_password, token, n=5):
|
||||||
|
time = get_timestamp()
|
||||||
|
tokens = []
|
||||||
|
for i in range(n):
|
||||||
|
last = tokens[-1] if len(tokens) > 0 else salted_password
|
||||||
|
tokens.append(generate_token(last))
|
||||||
|
|
||||||
|
if token[:8] == tokens[-1][:8]:
|
||||||
|
return True, i
|
||||||
|
|
||||||
|
return False, -1
|
||||||
|
|
||||||
|
def get_timestamp():
|
||||||
|
return time.strftime('%d%m%Y%H%M')
|
|
@ -1,34 +1,85 @@
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
|
import string
|
||||||
import localtoken
|
import localtoken
|
||||||
|
import random
|
||||||
|
import os
|
||||||
|
|
||||||
'''
|
def register_user():
|
||||||
Quando acessado usa o mesmo algoritmo gerador de senhas anterior. Mas em instância separada.
|
user = input('Digite o usuário: ')
|
||||||
A lista de senha gerada será a mesma nas duas partes, apesar de estarem em aplicativos separados e sem comunicação.
|
seed_password = sha256(input('Digite a senha: ').encode('utf-8')).hexdigest()
|
||||||
Verifica o usuário e se senha digitada esta na lista gerada e não foi usada e nem invalidada.
|
salt = ''.join(random.choice(string.ascii_letters) for i in range(16))
|
||||||
nesta caso apresenta “Chave válida”.
|
salt = sha256(salt.encode('utf-8')).hexdigest()
|
||||||
Atenção:
|
|
||||||
As senhas devem ter validade de no máximo um minuto e só podem ser usadas uma única vez.
|
|
||||||
Senhas são geradas a partir de outras senhas, e se for usada uma chave todas as chaves geradas pela mesma devem ser invalidadas.
|
|
||||||
Se o cliente digitar uma senha válida o servidor aceita, caso contrario retorna mensagem de erro.
|
|
||||||
|
|
||||||
'''
|
line = f'{user},{seed_password},{salt}\n'
|
||||||
|
with open('server.dat', 'a', newline='') as setup:
|
||||||
|
setup.write(line)
|
||||||
|
|
||||||
SALT = ''
|
print(f'Usuário registrado com sucesso! Salt: [{salt}]')
|
||||||
PASSWORD = ''
|
|
||||||
|
|
||||||
def main():
|
def validate_token():
|
||||||
print('Servidor!')
|
user = input('Digite o usuário: ')
|
||||||
SALT = sha256(input('Digite o salt: ').encode('utf-8')).hexdigest()
|
|
||||||
PASSWORD = sha256(input('Digite a senha: ').encode('utf-8')).hexdigest()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
token = input('Digite o token: ')
|
token = input('Digite o token: ')
|
||||||
if localtoken.generate_token(PASSWORD, SALT)[:8] == token[:8]:
|
password = ''
|
||||||
|
salt = ''
|
||||||
|
with open('server.dat', 'r', newline='') as setup:
|
||||||
|
for line in setup:
|
||||||
|
if len(line) == 0:
|
||||||
|
continue
|
||||||
|
line = line.replace('\n', '')
|
||||||
|
|
||||||
|
if line.split(',')[0] == user:
|
||||||
|
password = line.split(',')[1]
|
||||||
|
salt = line.split(',')[2]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print('Usuário incorreto!')
|
||||||
|
return
|
||||||
|
|
||||||
|
used_index = -1
|
||||||
|
used_timestamp = ''
|
||||||
|
with open('used_tokens.dat', 'r', newline='') as used_tokens:
|
||||||
|
for used_token in reversed(list(used_tokens)):
|
||||||
|
used_token = used_token.replace('\n', '')
|
||||||
|
if used_token.split(',')[0] == user:
|
||||||
|
used_index = int(used_token.split(',')[1])
|
||||||
|
used_timestamp = used_token.split(',')[2]
|
||||||
|
break
|
||||||
|
|
||||||
|
password = localtoken.get_salted_password(password, salt)
|
||||||
|
|
||||||
|
valid, index = localtoken.validate_token(password, token)
|
||||||
|
if valid:
|
||||||
|
if used_index <= index and used_timestamp == localtoken.get_timestamp():
|
||||||
|
print('Chave inválida (invalidada)!')
|
||||||
|
else:
|
||||||
print('Chave válida!')
|
print('Chave válida!')
|
||||||
|
with open('used_tokens.dat', 'a', newline='') as used_tokens:
|
||||||
|
line = f'{user},{index},{localtoken.get_timestamp()}'
|
||||||
|
used_tokens.write(line + '\n')
|
||||||
else:
|
else:
|
||||||
print('Chave inválida!')
|
print('Chave inválida!')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
while True:
|
||||||
|
print('Selecione uma opção:')
|
||||||
|
print('1 - Registrar usuário')
|
||||||
|
print('2 - Validar token')
|
||||||
|
print('0 - Sair')
|
||||||
|
|
||||||
|
option = input('Digite a opção: ')
|
||||||
|
|
||||||
|
if option == '1':
|
||||||
|
register_user()
|
||||||
|
elif option == '2':
|
||||||
|
validate_token()
|
||||||
|
elif option == '0':
|
||||||
|
exit()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
if not os.path.exists('server.dat'):
|
||||||
|
open('server.dat', 'w').close()
|
||||||
|
|
||||||
|
if not os.path.exists('used_tokens.dat'):
|
||||||
|
open('used_tokens.dat', 'w').close()
|
||||||
|
|
||||||
main()
|
main()
|
Loading…
Reference in New Issue