forked from cottonbeckfield/python-csr
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcsrgen35.py
More file actions
executable file
·133 lines (110 loc) · 4.11 KB
/
csrgen35.py
File metadata and controls
executable file
·133 lines (110 loc) · 4.11 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
#!/usr/bin/env python3
#
# Generate a key, self-signed certificate, and certificate request.
# Usage: csrgen <fqdn>
#
# When more than one hostname is provided, a SAN (Subject Alternate Name)
# certificate and request are generated. This can be acheived by adding -s.
# Usage: csrgen <hostname> -s <san0> <san1>
#
# Author: Courtney Cotton <cotton@cottoncourtney.com> 06-25-2014
# mod'd for python 3.5
# Libraries/Modules
from OpenSSL import crypto, SSL
import argparse
# Generate Certificate Signing Request (CSR)
def generateCSR(nodename, sans=[]):
while True:
C = input("Enter your Country Name (2 letter code) [US]: ")
if len(C) != 2:
print("You must enter two letters. You entered %r" % (C))
continue
ST = input("Enter your State or Province <full name> []:California: ")
if len(ST) == 0:
print("Please enter your State or Province.")
continue
L = input("Enter your (Locality Name (eg, city) []:San Francisco: ")
if len(L) == 0:
print("Please enter your City.")
continue
O = input("Enter your Organization Name (eg, company) []:FTW Enterprise: ")
if len(L) == 0:
print("Please enter your Organization Name.")
continue
OU = input("Enter your Organizational Unit (eg, section) []:IT: ")
if len(OU) == 0:
print("Please enter your OU.")
continue
# Allows you to permanently set values required for CSR
# To use, comment raw_input and uncomment this section.
# C = 'US'
# ST = 'New York'
# L = 'Location'
# O = 'Organization'
# OU = 'Organizational Unit'
csrfile = 'host.csr'
keyfile = 'host.key'
TYPE_RSA = crypto.TYPE_RSA
# Appends SAN to have 'DNS:'
ss = []
for i in sans:
ss.append("DNS: %s" % i)
ss = ", ".join(ss)
req = crypto.X509Req()
req.get_subject().CN = nodename
req.get_subject().countryName = C
req.get_subject().stateOrProvinceName = ST
req.get_subject().localityName = L
req.get_subject().organizationName = O
req.get_subject().organizationalUnitName = OU
# Add in extensions
# added bytearray to string
# before -> "keyUsage"
# after -> b"keyUsage"
base_constraints = ([
crypto.X509Extension(b"keyUsage", False, b"Digital Signature, Non Repudiation, Key Encipherment"),
crypto.X509Extension(b"basicConstraints", False, b"CA:FALSE"),
])
x509_extensions = base_constraints
# If there are SAN entries, append the base_constraints to include them.
if ss:
san_constraint = crypto.X509Extension(b"subjectAltName", False, ss)
x509_extensions.append(san_constraint)
req.add_extensions(x509_extensions)
# Utilizes generateKey function to kick off key generation.
key = generateKey(TYPE_RSA, 2048)
req.set_pubkey(key)
# change to sha 256?
# req.sign(key, "sha1")
req.sign(key, "sha256")
generateFiles(csrfile, req)
generateFiles(keyfile, key)
return req
# Generate Private Key
def generateKey(type, bits):
key = crypto.PKey()
key.generate_key(type, bits)
return key
# Generate .csr/key files.
def generateFiles(mkFile, request):
if mkFile == 'host.csr':
f = open(mkFile, "wb")
f.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, request))
f.close()
# print test
#print(crypto.dump_certificate_request(crypto.FILETYPE_PEM, request))
elif mkFile == 'host.key':
f = open(mkFile, "wb")
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, request))
f.close()
else:
print("Failed.")
exit()
# Run Portion
parser = argparse.ArgumentParser()
parser.add_argument("name", help="Provide the FQDN", action="store")
parser.add_argument("-s", "--san", help="SANS", action="store", nargs='*', default="")
args = parser.parse_args()
hostname = args.name
sans = args.san
generateCSR(hostname, sans)