This repository was archived by the owner on Nov 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathkeycreation.py
More file actions
executable file
·154 lines (122 loc) · 5.09 KB
/
Copy pathkeycreation.py
File metadata and controls
executable file
·154 lines (122 loc) · 5.09 KB
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
143
144
145
146
147
148
149
150
151
152
153
154
#!/bin/env python3
'''
Copyright (c) 2019 Nitrokey UG
This file is part of Nitroinit.
Nitroinit is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
Nitroinit is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Nitroinit. If not, see <http://www.gnu.org/licenses/>.
SPDX-License-Identifier: GPL-3.0
'''
""" Create a new PGP key and store it on disk for backup purposes """
import gpg
import os
import sys
def input_keyattr():
algorithms = {
1: "rsa2048",
2: "rsa3072",
3: "rsa4096",
4: "NIST P-256",
5: "NIST P-384", #FIXME GPG Agent returns "Invalid length"
6: "NIST P-521", #FIXME GPG Agent returns "Invalid length"
7: "brainpoolP256r1",
8: "brainpoolP384r1", #FIXME GPG Agent returns "Invalid length"
9: "brainpoolP512r1", #FIXME GPG Agent returns "Invalid length"
#10: "cv25519", TODO -> only NK Start can use this, thus more code is necessary
}
print("Please select the algorithm and size you want:")
print(" (1) RSA 2048")
print(" (2) RSA 3072")
print(" (3) RSA 4096")
print(" (4) NIST P-256")
#print(" (5) NIST P-384")
#print(" (6) NIST P-521")
print(" (7) Brainpool P-256")
#print(" (8) Brainpool P-384")
#print(" (9) Brainpool P-512")
#print(" (10) Curve 25519") TODO -> only NK Start can use this, thus more code is necessary
algo = int(input("Your selection? "))
print()
if algo in range(1,9):
return algorithms[algo]
else:
raise ValueError("Wrong selection, please choose a value between 1 and 9")
return algorithm
def input_userid():
uid = {}
print("Please provide a user ID to identify your key.")
uid['name'] = input("Enter the name for the user ID: ")
uid['email'] = input("Enter the email address for the user ID: ")
uid['cmnt'] = input("Enter a comment to include (optional): ")
print()
return uid
def create_key(expert=False):
# TODO do not use rsa3072 for NK Start
algorithm = "rsa3072" # default values
exp_time = 0
expires = False
c = gpg.Context()
# let user change key attributes
if expert:
algorithm = input_keyattr()
# ask user for User ID
uid = input_userid() # FIXME ask for expiration time here as well
# craft userid
if len(uid['cmnt']) > 0:
userid = "{0} ({1}) <{2}>".format(uid['name'], uid['cmnt'], uid['email'])
else:
userid = "{0} <{1}>".format(uid['name'], uid['email'])
# generate main key, encryption subkey and authentication subkey
newkey = c.create_key(userid, algorithm, exp_time, expires, certify=True, sign=True)
key = c.get_key(newkey.fpr, secret=True) # create_subkey can not be used with "newkey" var
esub = c.create_subkey(key, algorithm, exp_time, expires, encrypt=True)
if algorithm[0:4] == "NIST" or algorithm[0:4] == "brai":
# Due to a bug we need to add the algorithm for NISTP and Brainpool to work
# See here https://lists.gnupg.org/pipermail/gnupg-users/2018-July/060755.html
asub = c.create_subkey(key, algorithm+"/ecdsa", exp_time, expires, authenticate=True)
else:
asub = c.create_subkey(key, algorithm, exp_time, expires, authenticate=True)
# FIXME ask for desired location of backup keys
keyfile = os.path.expanduser("~/{0} <{1}>-sec.gpg".format(uid['name'], uid['email']))
keyfile_pub = os.path.expanduser("~/{0} <{1}>-pub.gpg".format(uid['name'], uid['email']))
# export secret and public keys to files for backup
try:
pubdata = c.key_export(newkey.fpr)
secdata = c.key_export_secret(newkey.fpr)
except:
raise
if pubdata is not None:
with open(keyfile_pub, "wb") as f:
f.write(pubdata)
else:
pass # TODO add proper exception
if secdata is not None:
with open(keyfile, "wb") as f:
f.write(secdata)
os.chmod(keyfile, 0o600)
else:
pass # TODO add proper exception
print("Keys exported as {0} and {1}.".format(keyfile, keyfile_pub))
# delete secret key from keyring (as it will be imported to the Nitrokey)
# op_delete_ext accepts two flags which can be set bit-wise
# 1 - delete secret keys; 2 - do not ask user before deletion
# we want both, thus using flag value '3'
c.op_delete_ext(key, 3) # TODO add error handling
# import public key again
with open(keyfile_pub, "rb") as f:
pubkey = f.read()
c.key_import(pubkey) # TODO add error handling
# provide path to secret keyfile
return keyfile
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == "--expert":
create_key(expert=True)
else:
create_key()