-
Notifications
You must be signed in to change notification settings - Fork 2
/
doubleslow-base.py
144 lines (107 loc) · 5.16 KB
/
doubleslow-base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python3
from Crypto.Util.RFC1751 import english_to_key
from Crypto.Util.RFC1751 import key_to_english
from hashlib import sha256
from hashlib import blake2b
import sys
from doubleslow_module import SlowKDF
from doubleslow_module import make_digest_for_export_160_bits
from doubleslow_module import get_memory
from doubleslow_module import get_big_enough_chunk_of_salt
from doubleslow_module import get_passphrase
from doubleslow_module import print_the_secrets
from doubleslow_module import print_security_warning
if len(sys.argv) > 2:
print("Too many arguments.")
quit()
elif len(sys.argv) == 2:
if sys.argv[1] == "one":
print("The external key stretching will NOT be performed.")
external_key_stretching = "no"
else:
print("Invalid argument.")
quit()
elif len(sys.argv) == 1:
print("The external key stretching will be performed. If you don't want this stop the script and run it with argument \"one\" or enter 0 when asked for number of iterations on the second stage.")
external_key_stretching = "yes"
print_security_warning()
mysalt = get_big_enough_chunk_of_salt()
def get_iterations_for_stage_1():
while True:
my_input = input("Number of iterations: ")
if my_input == "":
return 1
try:
iterations = int(my_input)
except ValueError as detail:
print(" Wrong input.", detail)
continue
if iterations < 1:
print("The number of iterations should be at least 1.")
else:
return iterations
def get_iterations_for_stage_2():
while True:
my_input = input("Number of iterations on the second stage (external key stretching): ")
if my_input == "":
return 0
try:
iterations = int(my_input)
except ValueError as detail:
print(" Wrong input.", detail)
continue
if iterations > 65535:
print ("Invalid number, it should be no more than 65535 (because we use two bytes to encode it)")
elif iterations < 1:
return 0
else:
return iterations
iterations_stage_1 = get_iterations_for_stage_1()
if external_key_stretching == "yes":
iterations_stage_2 = get_iterations_for_stage_2()
if iterations_stage_2 == 0:
print("The external key stretching was disabled, the key will be stretched only on this computer.")
external_key_stretching = "no"
mymemory_stage_1 = get_memory(32 , 16 * 1024, "Please enter the memory (for the first stage) in MiB (must be power of two): ")
mymemory_stage_1 = mymemory_stage_1 * 1024 # KiB
if external_key_stretching == "yes":
mymemory_stage_2 = get_memory(32 , 16 * 1024, "Please enter the memory (for the second stage) in MiB (must be power of two): ")
mypassphrase_bytestring = get_passphrase()
digest_512_bits = SlowKDF(mypassphrase_bytestring, mysalt, mymemory_stage_1, iterations_stage_1)
if external_key_stretching == "yes":
# up to 65535 - every number is encoded in two bytes
second_stage_bytes = mymemory_stage_2.to_bytes(2, 'big') + iterations_stage_2.to_bytes(2, 'big')
data_for_export_192_bits = second_stage_bytes + make_digest_for_export_160_bits(digest_512_bits)
print ("\n\nRFC1751 words:\n\n", key_to_english(data_for_export_192_bits))
print ("\n\nHash for detecting errors:\t", key_to_english(blake2b(data_for_export_192_bits,digest_size=8).digest()))
print ("\nPlease run the doubleslow-external.py script on the powerful computer and enter the above RFC1751 words there. Then, write below the output from the doubleslow-external.py script. \n\n")
while True:
try:
words = input("RFC1751 words: ")
digest_external = english_to_key(words)
except ValueError as detail:
print("Error: ", detail,"\n")
print("Please write the correct word sequence.\n")
continue
if data_for_export_192_bits == digest_external:
print("You should not enter the above words here.")
print("You should enter the above words where the doubleslow-external.py script is asking for them.")
print("You should enter the output from the doubleslow-external.py script below.\n")
continue
the_length_of_the_digest=len(digest_external)
if the_length_of_the_digest != 32:
print("We expected 32 bytes, got", the_length_of_the_digest, "instead. Please write the correct word sequence.\n")
continue
print ("\nThe word sequence looks valid. The hash is:\n\n", key_to_english(blake2b(digest_external,digest_size=8).digest()))
answer=input("\n\nPlease verify that the hash is correct and type \"yes\" to continue: ").lower()
if answer == "yes":
break
elif answer == "quit":
quit()
else:
continue
else:
digest_external=b''
digest_from_additional_hashing = SlowKDF(mypassphrase_bytestring+digest_512_bits+digest_external, mysalt, mymemory_stage_1, 1)
digest256_final = sha256(digest_from_additional_hashing+mypassphrase_bytestring+digest_512_bits+digest_external+mysalt).digest()
print_the_secrets(digest256_final)