You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.1 KiB
89 lines
3.1 KiB
#!/usr/bin/python |
|
|
|
"""Extract certificates from a multi-certificate pem file. |
|
|
|
Each certificate in the file is extracted into a format appropriate for use with |
|
Brillo or Android. On success, the contents of the output directory match the |
|
input file exactly. Existing files in the output directory will be deleted. |
|
|
|
The current date will be written into the timestamp file, './TIMESTAMP' by |
|
default. |
|
|
|
Typical usage (extracting from ./roots.pem and output into ./files): |
|
> ./extract_from_pem.py |
|
""" |
|
|
|
import argparse |
|
import datetime |
|
import os |
|
import re |
|
|
|
import M2Crypto # sudo apt-get install python-m2crypto |
|
|
|
|
|
def WriteCertificateFile(content, base_name, output_dir): |
|
"""Writes a certificate file to the output directory. |
|
|
|
Args: |
|
content: The file content to write. |
|
base_name: The file name will be base_name.n where n is the first available |
|
non-negative integer. Ex. if myfile.0 exists and has different |
|
content, the output file will be myfile.1. |
|
output_dir: The output directory. |
|
""" |
|
i = 0 |
|
file_path = os.path.join(output_dir, '%s.%d' % (base_name, i)) |
|
while os.path.exists(file_path): |
|
with open(file_path) as existing_file: |
|
if content == existing_file.read(): |
|
# Ignore identical duplicate. |
|
return |
|
i += 1 |
|
file_path = os.path.join(output_dir, '%s.%d' % (base_name, i)) |
|
with open(file_path, 'w') as new_file: |
|
new_file.write(content) |
|
|
|
|
|
def GetFingerprintString(x509): |
|
"""Computes a fingerprint string as output by 'openssl x509 -fingerprint'. |
|
|
|
Args: |
|
x509: A M2Crypto.X509.X509 object. |
|
|
|
Returns: |
|
The fingerprint as a string. |
|
""" |
|
# Zero filled and with ':' between bytes. |
|
return ':'.join(re.findall(r'..', x509.get_fingerprint('sha1').zfill(40))) |
|
|
|
|
|
def main(): |
|
parser = argparse.ArgumentParser(description='PEM Certificate Importer') |
|
parser.add_argument('--pem_file', nargs='?', default='roots.pem') |
|
parser.add_argument('--output_dir', nargs='?', default='files') |
|
parser.add_argument('--timestamp_file', nargs='?', default='TIMESTAMP') |
|
args = parser.parse_args() |
|
assert os.path.isdir(args.output_dir) and os.path.isfile(args.pem_file) |
|
if 'y' != raw_input('All files in \'%s\' will be deleted. Proceed? [y,N]: ' % |
|
args.output_dir): |
|
print 'Aborted.' |
|
return |
|
for existing_file in os.listdir(args.output_dir): |
|
os.remove(os.path.join(args.output_dir, existing_file)) |
|
with open(args.pem_file) as pem_file: |
|
pattern = r'-----BEGIN CERTIFICATE-----[^-]*-----END CERTIFICATE-----' |
|
pem_certs = re.findall(pattern, pem_file.read()) |
|
for pem_cert in pem_certs: |
|
x509 = M2Crypto.X509.load_cert_string(pem_cert) |
|
content = '%s%sSHA1 Fingerprint=%s\n' % (x509.as_pem(), |
|
x509.as_text(), |
|
GetFingerprintString(x509)) |
|
base_name = '%08x' % x509.get_subject().as_hash() |
|
WriteCertificateFile(content, base_name, args.output_dir) |
|
with open(args.timestamp_file, 'w') as timestamp_file: |
|
timestamp_file.write('Last Update (YYYY-MM-DD): %s\n' % |
|
datetime.date.today().isoformat()) |
|
|
|
|
|
if __name__ == '__main__': |
|
main()
|
|
|