summaryrefslogtreecommitdiff
path: root/scripts/rvi_create_device_key.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/rvi_create_device_key.sh')
-rwxr-xr-xscripts/rvi_create_device_key.sh155
1 files changed, 155 insertions, 0 deletions
diff --git a/scripts/rvi_create_device_key.sh b/scripts/rvi_create_device_key.sh
new file mode 100755
index 0000000..060ea8b
--- /dev/null
+++ b/scripts/rvi_create_device_key.sh
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+
+#
+# Copyright (C) 2015, Jaguar Land Rover
+#
+# This program is licensed under the terms and conditions of the
+# Mozilla Public License, version 2.0. T full text of the
+# Mozilla Public License is at https://www.mozilla.org/MPL/2.0/
+#
+#
+# 1. Generate a device key through openssl.
+# 2. Sign the public key using the provided private root key.
+# 3. Create a JWT version of the signed device key.
+#
+
+import getopt
+import sys
+from Crypto.PublicKey import RSA
+import json
+import base64
+import os
+
+# apt-get install python-dev
+# apt-get install libffi-dev
+# pip install cryptography
+# pip install PyJWT
+
+import jwt
+import struct
+
+def long2intarr(long_int):
+ _bytes = []
+ while long_int:
+ long_int, r = divmod(long_int, 256)
+ _bytes.insert(0, r)
+ return _bytes
+
+# copied from https://github.com/rohe/pyjwkest
+def long_to_base64(n):
+ bys = long2intarr(n)
+ data = struct.pack('%sB' % len(bys), *bys)
+ if not len(data):
+ data = '\x00'
+ s = base64.urlsafe_b64encode(data).rstrip(b'=')
+ return s
+
+def usage():
+ print "Usage:", sys.argv[0], "-p <priv_root_key> -o <prefix> -b <bits>"
+ print " -p <priv_root_key> Private root key file to sign public device key with."
+ print " -o <prefix> File name prefix for generated device keys."
+ print " -b <bits> Device key length. Default 2048."
+ sys.exit(255)
+
+opts, args= getopt.getopt(sys.argv[1:], "p:o:b:")
+
+priv_root_key_fname=""
+fname_prefix=""
+key_lenth=2048
+for o, a in opts:
+ if o == "-p":
+ priv_root_key_fname = a
+ elif o == "-b":
+ key_length = int(a)
+ elif o == "-o":
+ fname_prefix = a
+ else:
+ usage()
+
+if priv_root_key_fname == "" or fname_prefix == "":
+ usage()
+
+
+#
+# Generate the device RSA key pair
+#
+new_key = RSA.generate(bits=key_length)
+
+
+#
+# Create private key file, which also contains the public key.
+#
+priv_key_fname = "{}_priv.pem".format(fname_prefix)
+priv_key_file = open(priv_key_fname, 'w')
+priv_key = new_key.exportKey("PEM")
+priv_key_file.write(priv_key)
+priv_key_file.close()
+
+
+# Read the root private key
+priv_root_key_file = open(priv_root_key_fname, 'r')
+priv_root_key = RSA.importKey(priv_root_key_file.read())
+priv_root_key_file.close()
+
+
+#
+# Extract the device public key that we are to sign with the private root key.
+# Dump it in a file to be used by rvi_create_certificate.py
+#
+pub_key_fname = "{}_pub.pem".format(fname_prefix)
+pub_key_file = open(pub_key_fname, 'w')
+pub_key = new_key.publickey()
+pub_key_pem = pub_key.exportKey("PEM")
+pub_key_file.write(pub_key_pem)
+pub_key_file.close()
+
+print "pub_key.e = ", pub_key.e
+print "pub_key.n = ", pub_key.n
+
+key_obj = {
+ 'keys': [{
+ "kty": "RSA",
+ "alg": "RS256",
+ "use": "sig",
+ "e": long_to_base64(pub_key.e),
+ "n": long_to_base64(pub_key.n)
+ }],
+}
+
+# Generate a JWT signature based on the pub key and the private root key
+signature = jwt.encode(key_obj, priv_root_key.exportKey('PEM'), algorithm='RS256')
+
+
+# Verify that we can use the public root key to verify the key.
+pub_root_key = priv_root_key.publickey().exportKey('PEM')
+
+try:
+ jwt.decode(signature, pub_root_key)
+except:
+ print "FAILED VERIFICATION!"
+ print "The public portion of the generated device key, signed by the provided private root key,"
+ print "could not be verified using the public root key."
+ os.remove(priv_key_fname)
+ sys.exit(0)
+
+#
+# Create signed public JWT file
+#
+pub_sign_key_fname = "{}_pub_sign.jwt".format(fname_prefix)
+
+pub_sign_key_file = open(pub_sign_key_fname, 'w')
+pub_sign_key_file.write(signature)
+pub_sign_key_file.close()
+
+print "Device private/public key pair stored in: ", priv_key_fname
+print "Device public-only key stored in: ", pub_key_fname
+print "Device JWT-formatted public key signed by private "
+print " root key, stored in: ", pub_sign_key_fname
+print "Root key used to sign the device public key read from: ", priv_root_key_fname
+print
+print "Set rvi node's device_key_pair config parameter to point to: ", priv_root_key_fname
+print "Set rvi node's authorize_jwt config parameter to point to: ", pub_sign_key_fname
+print
+print "use ./rvi_create_certificate.py ... --device_key={} to include".format(pub_key_fname)
+print "device public key in a certificate."
+