From 137f50857a909c41ca09c12ec61aa6c68a9aff76 Mon Sep 17 00:00:00 2001 From: Anson Fan Date: Mon, 30 Nov 2015 09:58:12 -0800 Subject: Renamed rvi_create_certificate.py -> rvi_create_certificate_key.sh and rvi_create_device_key.py -> rvi_create_device_key.sh to allow for sudo make install to properly install --- scripts/rvi_create_certificate.py | 254 ---------------------------------- scripts/rvi_create_certificate_key.sh | 254 ++++++++++++++++++++++++++++++++++ scripts/rvi_create_device_key.py | 155 --------------------- scripts/rvi_create_device_key.sh | 155 +++++++++++++++++++++ 4 files changed, 409 insertions(+), 409 deletions(-) delete mode 100755 scripts/rvi_create_certificate.py create mode 100755 scripts/rvi_create_certificate_key.sh delete mode 100755 scripts/rvi_create_device_key.py create mode 100755 scripts/rvi_create_device_key.sh (limited to 'scripts') diff --git a/scripts/rvi_create_certificate.py b/scripts/rvi_create_certificate.py deleted file mode 100755 index 6e09fdc..0000000 --- a/scripts/rvi_create_certificate.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/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/ -# -# Create a certificate giving the sender the right to invoke and -# - -import getopt -import sys -from Crypto.PublicKey import RSA - -# apt-get install python-dev -# apt-get install libffi-dev -# pip install cryptography -# pip install PyJWT - -import jwt -import time -import json -import base64 -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], "--id= --invoke='' -register='' \\" - print " --root_key= --start='' --stop='' \\" - print " --out=" - print - print " --id= System-wide unique certificate ID" - print - print " --invoke='' Right to invoke service. Space separate multiple services." - print - print " --register='' Right to register service. Space separate multiple services." - print " At least one --invoke or --register must be given." - print - print " --root_key= Private root key to sign certificate with" - print " Mandatory" - print - print " --device_key= Public device key to include in certificate" - print " Mandatory" - print - print " --start='' Date and time when certificate is activated." - print " Default: current time." - print - print " --stop='' Date and time when certificate is deactivated." - print " Default: 365 days from current time" - print - print " --jwt_out= File name to store JWT-encoded certificate in." - print " Default: stdout" - print - print " --cert_out= File name to unencoded JSON certificate in." - print " Default: Do not store certificate" - print - print " --issuer=issuer Name of the issuer. Default: jaguarlandrover.com" - print - print "Root key file is generated by rvi_create_root_key.sh" - print - print "Device key is the '_pub.pem'-suffixed file created by rvi_create_device_key.py" - print - print "Certificate file specified by out should be placed in 'priv/certs'" - print - print - print "Example:" - print "./rvi_create_certificate.py --id=317624d8-2ccf-11e5-993c-7f3b5182c649 \\" - print " --device_key=device_key_pub.pem \\" - print " --start='2015-12-01 00:00:00' \\" - print " --stop='2015-12-31 23:59:59' \\" - print " --root_key=root_key_priv.pem \\" - print " --register='jlr.com/vin/abc/unlock jlr.com/vin/abc/lock' \\" - print " --invoke='jlr.com/backend/report jlr.com/backend/set_state' \\" - print " --jwt_out=lock_cert.jwt \\" - print " --cert_out=lock_cert.json" - sys.exit(255) - -try: - opts, args = getopt.getopt(sys.argv[1:], "", [ 'issuer=', 'invoke=', 'register=', - 'root_key=', 'start=', - 'stop=', 'cert_out=', 'id=', - 'jwt_out=', 'device_key=']) -except getopt.GetoptError as e: - print - print e - print - usage() - -start=int(time.time()) -stop=int(time.time()) + 86400 * 365 - -issuer='jaguarlandrover.com' -invoke=None -register=None -root_key=None -device_key=None -jwt_out_file=None -cert_out_file=None -id_string=None -for o, a in opts: - if o == "--start": - try: - start = int(time.mktime(time.strptime(a, "%Y-%m-%d %H:%M:%S"))) - except: - print - print "Incorrect start time: {}".format(a) - print - usage() - - elif o == '--root_key': - try: - root_key_fname = a - root_key_file = open(root_key_fname, "r") - root_key = RSA.importKey(root_key_file.read()) - root_key_file.close() - except IOError as e: - print "Coould read root cert from {0}: {1}".format(a, e.strerror) - sys.exit(255) - - elif o == '--device_key': - try: - device_key_file = open(a, "r") - device_key = RSA.importKey(device_key_file.read()) - device_key_file.close() - except IOError as e: - print "Coould read root cert from {0}: {1}".format(a, e.strerror) - sys.exit(255) - - elif o == "--stop": - try: - stop = int(time.mktime(time.strptime(a, "%Y-%m-%d %H:%M:%S"))) - except: - print - print "Incorrect stop time: {}".format(a) - print - usage() - - elif o == '--invoke': - invoke=a.split(' ') - - elif o == '--register': - register=a.split(' ') - - elif o == '--id': - id_string=a - - elif o == '--issuer': - issuer=a - - elif o == '--jwt_out': - try: - jwt_out_file = open(a, "w") - except IOError as e: - print "Coould write to JWT file {0}: {1}".format(a, e.strerror) - sys.exit(255) - - elif o == '--cert_out': - try: - cert_out_file = open(a, "w") - except IOError as e: - print "Coould write to certificate file {0}: {1}".format(a, e.strerror) - sys.exit(255) - - else: - print - print "Unknown command line argument: {}".format(o) - print - usage() - -if jwt_out_file == None: - jwt_out_file = sys.stdout - -if not invoke and not register: - print - print "At least one --invoke or --register service must be specified." - print - usage() - -if not root_key: - print - print "No --root_key= specified" - print - usage() - -if not device_key: - print - print "No --device_key= specified" - print - usage() - -if not id_string: - print - print "No --id= specified" - print - usage() - - -# Create a JSON Web Key based off our public device key PEM file - - -cert = { - 'iss': issuer, - 'id': id_string, - 'sources': register, - 'destinations': invoke, - 'create_timestamp': int(time.time()), - 'keys': [{ - "kty": "RSA", - "alg": "RS256", - "use": "sig", - "e": long_to_base64(device_key.e), - "n": long_to_base64(device_key.n) - }], - 'validity': { - 'start': start, - 'stop': stop - } -} - - -encoded = jwt.encode(cert, root_key.exportKey("PEM"), algorithm='RS256') - -# Validate -try: - jwt.decode(encoded, root_key.publickey().exportKey("PEM")) -except: - print "FAILED: Could not verify signed JSON Web Token using public part of" - print " root key {}".format(root_key_fname) - - -jwt_out_file.write(encoded) -jwt_out_file.close() - -if cert_out_file: - cert_out_file.write(json.dumps(cert, sort_keys=True, indent=4, separators=(',', ': ')) + '\n') - cert_out_file.close() - diff --git a/scripts/rvi_create_certificate_key.sh b/scripts/rvi_create_certificate_key.sh new file mode 100755 index 0000000..6e09fdc --- /dev/null +++ b/scripts/rvi_create_certificate_key.sh @@ -0,0 +1,254 @@ +#!/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/ +# +# Create a certificate giving the sender the right to invoke and +# + +import getopt +import sys +from Crypto.PublicKey import RSA + +# apt-get install python-dev +# apt-get install libffi-dev +# pip install cryptography +# pip install PyJWT + +import jwt +import time +import json +import base64 +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], "--id= --invoke='' -register='' \\" + print " --root_key= --start='' --stop='' \\" + print " --out=" + print + print " --id= System-wide unique certificate ID" + print + print " --invoke='' Right to invoke service. Space separate multiple services." + print + print " --register='' Right to register service. Space separate multiple services." + print " At least one --invoke or --register must be given." + print + print " --root_key= Private root key to sign certificate with" + print " Mandatory" + print + print " --device_key= Public device key to include in certificate" + print " Mandatory" + print + print " --start='' Date and time when certificate is activated." + print " Default: current time." + print + print " --stop='' Date and time when certificate is deactivated." + print " Default: 365 days from current time" + print + print " --jwt_out= File name to store JWT-encoded certificate in." + print " Default: stdout" + print + print " --cert_out= File name to unencoded JSON certificate in." + print " Default: Do not store certificate" + print + print " --issuer=issuer Name of the issuer. Default: jaguarlandrover.com" + print + print "Root key file is generated by rvi_create_root_key.sh" + print + print "Device key is the '_pub.pem'-suffixed file created by rvi_create_device_key.py" + print + print "Certificate file specified by out should be placed in 'priv/certs'" + print + print + print "Example:" + print "./rvi_create_certificate.py --id=317624d8-2ccf-11e5-993c-7f3b5182c649 \\" + print " --device_key=device_key_pub.pem \\" + print " --start='2015-12-01 00:00:00' \\" + print " --stop='2015-12-31 23:59:59' \\" + print " --root_key=root_key_priv.pem \\" + print " --register='jlr.com/vin/abc/unlock jlr.com/vin/abc/lock' \\" + print " --invoke='jlr.com/backend/report jlr.com/backend/set_state' \\" + print " --jwt_out=lock_cert.jwt \\" + print " --cert_out=lock_cert.json" + sys.exit(255) + +try: + opts, args = getopt.getopt(sys.argv[1:], "", [ 'issuer=', 'invoke=', 'register=', + 'root_key=', 'start=', + 'stop=', 'cert_out=', 'id=', + 'jwt_out=', 'device_key=']) +except getopt.GetoptError as e: + print + print e + print + usage() + +start=int(time.time()) +stop=int(time.time()) + 86400 * 365 + +issuer='jaguarlandrover.com' +invoke=None +register=None +root_key=None +device_key=None +jwt_out_file=None +cert_out_file=None +id_string=None +for o, a in opts: + if o == "--start": + try: + start = int(time.mktime(time.strptime(a, "%Y-%m-%d %H:%M:%S"))) + except: + print + print "Incorrect start time: {}".format(a) + print + usage() + + elif o == '--root_key': + try: + root_key_fname = a + root_key_file = open(root_key_fname, "r") + root_key = RSA.importKey(root_key_file.read()) + root_key_file.close() + except IOError as e: + print "Coould read root cert from {0}: {1}".format(a, e.strerror) + sys.exit(255) + + elif o == '--device_key': + try: + device_key_file = open(a, "r") + device_key = RSA.importKey(device_key_file.read()) + device_key_file.close() + except IOError as e: + print "Coould read root cert from {0}: {1}".format(a, e.strerror) + sys.exit(255) + + elif o == "--stop": + try: + stop = int(time.mktime(time.strptime(a, "%Y-%m-%d %H:%M:%S"))) + except: + print + print "Incorrect stop time: {}".format(a) + print + usage() + + elif o == '--invoke': + invoke=a.split(' ') + + elif o == '--register': + register=a.split(' ') + + elif o == '--id': + id_string=a + + elif o == '--issuer': + issuer=a + + elif o == '--jwt_out': + try: + jwt_out_file = open(a, "w") + except IOError as e: + print "Coould write to JWT file {0}: {1}".format(a, e.strerror) + sys.exit(255) + + elif o == '--cert_out': + try: + cert_out_file = open(a, "w") + except IOError as e: + print "Coould write to certificate file {0}: {1}".format(a, e.strerror) + sys.exit(255) + + else: + print + print "Unknown command line argument: {}".format(o) + print + usage() + +if jwt_out_file == None: + jwt_out_file = sys.stdout + +if not invoke and not register: + print + print "At least one --invoke or --register service must be specified." + print + usage() + +if not root_key: + print + print "No --root_key= specified" + print + usage() + +if not device_key: + print + print "No --device_key= specified" + print + usage() + +if not id_string: + print + print "No --id= specified" + print + usage() + + +# Create a JSON Web Key based off our public device key PEM file + + +cert = { + 'iss': issuer, + 'id': id_string, + 'sources': register, + 'destinations': invoke, + 'create_timestamp': int(time.time()), + 'keys': [{ + "kty": "RSA", + "alg": "RS256", + "use": "sig", + "e": long_to_base64(device_key.e), + "n": long_to_base64(device_key.n) + }], + 'validity': { + 'start': start, + 'stop': stop + } +} + + +encoded = jwt.encode(cert, root_key.exportKey("PEM"), algorithm='RS256') + +# Validate +try: + jwt.decode(encoded, root_key.publickey().exportKey("PEM")) +except: + print "FAILED: Could not verify signed JSON Web Token using public part of" + print " root key {}".format(root_key_fname) + + +jwt_out_file.write(encoded) +jwt_out_file.close() + +if cert_out_file: + cert_out_file.write(json.dumps(cert, sort_keys=True, indent=4, separators=(',', ': ')) + '\n') + cert_out_file.close() + diff --git a/scripts/rvi_create_device_key.py b/scripts/rvi_create_device_key.py deleted file mode 100755 index 060ea8b..0000000 --- a/scripts/rvi_create_device_key.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/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 -o -b " - print " -p Private root key file to sign public device key with." - print " -o File name prefix for generated device keys." - print " -b 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." - 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 -o -b " + print " -p Private root key file to sign public device key with." + print " -o File name prefix for generated device keys." + print " -b 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." + -- cgit v1.2.1