-
Notifications
You must be signed in to change notification settings - Fork 2
/
snap2luks.py
73 lines (63 loc) · 2.55 KB
/
snap2luks.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
#!/usr/bin/python3
import argparse
import struct
import sys
import os
from re import match as regexmatch
def main ():
parser = argparse.ArgumentParser(description='Convert Snap TPM-FDE recovery key to LUKS key-file.')
parser.add_argument('-o','--outfile', dest='outfile', default='./key.out', help='Path to the raw key-file generated.')
parser.add_argument('--stdout', dest='stdout', action='store_true', default=False, help='Print key to stdout instead of writing to a file.')
recovery_string = parser.add_mutually_exclusive_group(required=True)
recovery_string.add_argument('-s', '--string', dest='string', help='The Snapd TPM-FDE recovery-key string to convert.')
recovery_string.add_argument('-i', '--infile', dest='infile', help='The path to a file containing your recovery-key string.')
cmdline = parser.parse_args()
if cmdline.string:
vd_string = validate_string(cmdline.string)
elif cmdline.infile:
vd_string = validate_string(extract_key_string(cmdline.infile))
else:
sys.exit('Unknown error while retrieving the recovery key string')
fmt_string = format_string(vd_string)
if cmdline.stdout:
stdout_key(fmt_string)
else:
write_key(fmt_string, cmdline.outfile)
def extract_key_string(path):
if os.path.isfile(path):
with open(path, 'r') as keyfile:
recovery_key_string = keyfile.readline()
return recovery_key_string
else:
sys.exit(f"File, {path}, not found.")
def validate_string (recovery_string):
# Accept formatted recovery keys containing '-' characters
s = str.replace(recovery_string,'-','')
# Strip whitespace
s = s.strip()
# Validate string length
if len(s) != 40:
sys.exit('Recovery string is not exactly 40 digits.')
# Validate string content
if not regexmatch('[0-9]', s):
sys.exit('Recovery string should only contain numbers.')
return s
def format_string (stripped_recovery_string):
chunk_len = int(len(stripped_recovery_string)/8)
key_array = []
for i in range(0, len(stripped_recovery_string), chunk_len):
key_array.append(int(stripped_recovery_string[i : i + chunk_len]))
return key_array
def stdout_key (key_array):
# Write each number as UInt16 Little-Endian binary to a file
for i in key_array:
packed_data = struct.pack('<H', i)
print(packed_data, end='')
def write_key (key_array, outfile):
realpath = os.path.realpath(outfile)
with open(realpath, 'wb') as keyfile:
# Write each number as UInt16 Little-Endian binary to a file
for i in key_array:
packed_data = struct.pack('<H', i)
keyfile.write(packed_data)
main()