Chromium Code Reviews| Index: net/data/verify_certificate_chain_unittest/common.py |
| diff --git a/net/data/verify_certificate_chain_unittest/common.py b/net/data/verify_certificate_chain_unittest/common.py |
| index a3d86420cfeb8aa3e91eb07606d25ca16310d108..bce072d2d3a5ca56b6f5e4937ba75ea65ab5f6b5 100755 |
| --- a/net/data/verify_certificate_chain_unittest/common.py |
| +++ b/net/data/verify_certificate_chain_unittest/common.py |
| @@ -52,14 +52,16 @@ DEFAULT_KEY_PURPOSE = KEY_PURPOSE_SERVER_AUTH |
| g_cur_path_id = {} |
| # Output paths used: |
| -# - g_out_dir: where any temporary files (keys, cert req, signing db etc) are |
| +# - g_out_dir: where any temporary files (cert req, signing db etc) are |
| # saved to. |
| -# - g_out_pem: the path to the final output (which is a .pem file) |
| +# - g_script_name: the name of the invoking script. For instance if this is |
| +# being run by generate-foo.py then g_script_name will be |
| +# 'foo' |
| # |
| # See init() for how these are assigned, based on the name of the calling |
| # script. |
| g_out_dir = None |
| -g_out_pem = None |
| +g_script_name = None |
| # The default validity range of generated certificates. Can be modified with |
| # set_default_validity_range(). |
| @@ -75,6 +77,7 @@ def set_default_validity_range(start_date, end_date): |
| g_default_start_date = start_date |
| g_default_end_date = end_date |
| + |
| def get_unique_path_id(name): |
| """Returns a base filename that contains 'name', but is unique to the output |
| directory""" |
| @@ -93,10 +96,6 @@ def get_path_in_output_dir(name, suffix): |
| return os.path.join(g_out_dir, '%s%s' % (name, suffix)) |
| -def get_unique_path_in_output_dir(name, suffix): |
| - return get_path_in_output_dir(get_unique_path_id(name), suffix) |
| - |
| - |
| class Key(object): |
| """Describes a public + private key pair. It is a dumb wrapper around an |
| on-disk key.""" |
| @@ -110,38 +109,50 @@ class Key(object): |
| return self.path |
| -def generate_rsa_key(size_bits, path=None): |
| - """Generates an RSA private key and returns it as a Key object. If |path| is |
| - specified the resulting key will be saved at that location.""" |
| - if path is None: |
| - path = get_unique_path_in_output_dir('RsaKey', 'key') |
| +def get_or_generate_key(generation_arguments, path): |
| + """Helper function to either retrieve a key from an existing file |path|, or |
| + generate a new one using the command line |generation_arguments|.""" |
| + |
| + generation_arguments_str = ' '.join(generation_arguments) |
| - # Ensure the path doesn't already exists (otherwise will be overwriting |
| - # something). |
| - assert not os.path.isfile(path) |
| + # If the file doesn't already exist, generate a new key using the generation |
| + # parameters. |
| + if not os.path.isfile(path): |
| + key_contents = subprocess.check_output(generation_arguments) |
| - subprocess.check_call( |
| - ['openssl', 'genrsa', '-out', path, str(size_bits)]) |
| + # Prepend the generation parameters to the key file. |
| + write_string_to_file(generation_arguments_str + '\n' + key_contents, |
| + path) |
| + else: |
| + # If the path already exists, confirm that it is for the expected key type. |
| + file_contents = read_file_to_string(path) |
| + if not file_contents.startswith(generation_arguments_str): |
|
mattm
2017/04/07 22:01:27
This could just match part of the generation args
eroman
2017/04/07 23:36:33
Good point! Done.
|
| + sys.stderr.write( |
| + ('The existing key file %s is not compatible with the ' |
| + 'requested parameters:\n%s.\n') % (path, generation_arguments_str)) |
|
mattm
2017/04/07 22:01:27
might be helpful to mention you can delete the key
eroman
2017/04/07 23:36:33
Done. I also print out the contradiction explicitl
|
| + sys.exit(1) |
| return Key(path) |
| -def generate_ec_key(named_curve, path=None): |
| - """Generates an EC private key for the certificate and returns it as a Key |
| - object. |named_curve| can be something like secp384r1. If |path| is specified |
| - the resulting key will be saved at that location.""" |
| - if path is None: |
| - path = get_unique_path_in_output_dir('EcKey', 'key') |
| +def get_or_generate_rsa_key(size_bits, path): |
| + """Retrieves an existing key from a file if the path exists. Otherwise |
| + generates an RSA key with the specified bit size and saves it to the path.""" |
| + return get_or_generate_key(['openssl', 'genrsa', str(size_bits)], path) |
| - # Ensure the path doesn't already exists (otherwise will be overwriting |
| - # something). |
| - assert not os.path.isfile(path) |
| - subprocess.check_call( |
| - ['openssl', 'ecparam', '-out', path, |
| - '-name', named_curve, '-genkey']) |
| +def get_or_generate_ec_key(named_curve, path): |
| + """Retrieves an existing key from a file if the path exists. Otherwise |
| + generates an EC key with the specified named curve and saves it to the |
| + path.""" |
| + return get_or_generate_key(['openssl', 'ecparam', '-name', named_curve, |
| + '-genkey'], path) |
| - return Key(path) |
| + |
| +def create_key_path(base_name): |
| + """Generates a name that contains |base_name| in it, and is relative to the |
| + "keys/" directory""" |
| + return get_unique_path_id('keys/' + g_script_name + '_' + base_name) + '.key' |
|
mattm
2017/04/07 22:01:27
This may work a bit less well for other scripts th
eroman
2017/04/07 23:36:33
I made a few changes which hopefully address those
|
| class Certificate(object): |
| @@ -255,7 +266,8 @@ class Certificate(object): |
| def get_key(self): |
| if self.key is None: |
| - self.set_key_internal(generate_rsa_key(2048, path=self.get_path(".key"))) |
| + self.set_key_internal( |
| + get_or_generate_rsa_key(2048, create_key_path(self.name))) |
| return self.key |
| @@ -284,8 +296,7 @@ class Certificate(object): |
| self.finalize() |
| # Read the certificate data. |
| - with open(self.get_cert_path(), 'r') as f: |
| - return f.read() |
| + return read_file_to_string(self.get_cert_path()) |
| def finalize(self): |
| @@ -480,7 +491,9 @@ def write_test_file(description, chain, trust_anchor, utc_time, key_purpose, |
| if errors is not None: |
| test_data += '\n' + text_data_to_pem('ERRORS', errors) |
| - write_string_to_file(test_data, out_pem if out_pem else g_out_pem) |
| + if not out_pem: |
| + out_pem = g_script_name + '.pem' |
| + write_string_to_file(test_data, out_pem) |
| def write_string_to_file(data, path): |
| @@ -488,6 +501,11 @@ def write_string_to_file(data, path): |
| f.write(data) |
| +def read_file_to_string(path): |
| + with open(path, 'r') as f: |
| + return f.read() |
| + |
| + |
| def init(invoking_script_path): |
| """Creates an output directory to contain all the temporary files that may be |
| created, as well as determining the path for the final output. These paths |
| @@ -495,7 +513,7 @@ def init(invoking_script_path): |
| """ |
| global g_out_dir |
| - global g_out_pem |
| + global g_script_name |
| # Base the output name off of the invoking script's name. |
| out_name = os.path.splitext(os.path.basename(invoking_script_path))[0] |
| @@ -512,7 +530,7 @@ def init(invoking_script_path): |
| shutil.rmtree(g_out_dir, True) |
| os.makedirs(g_out_dir) |
| - g_out_pem = os.path.join('%s.pem' % (out_name)) |
| + g_script_name = out_name |
| def create_self_signed_root_certificate(name): |