File indexing completed on 2024-11-24 04:44:41
0001 #!/usr/bin/env python3 0002 # SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org> 0003 # SPDX-License-Identifier: LGPL-2.0-or-later 0004 0005 import argparse 0006 import os 0007 import subprocess 0008 import pyasn1 0009 import shutil 0010 0011 from pyasn1.codec.der.decoder import decode 0012 from pyasn1.codec.der.encoder import encode 0013 0014 derFileNames = [] 0015 0016 def writeToFile(fileName, content): 0017 f = open(fileName, 'wb') 0018 f.write(content) 0019 f.close(); 0020 0021 def runOpenSsl(args, data = None): 0022 proc = subprocess.Popen(f"openssl {args}", shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 0023 if data != None: 0024 proc.stdin.write(data) 0025 proc.stdin.close() 0026 return proc.stdout.read() 0027 0028 def removeExistingCerts(): 0029 for certFile in os.listdir(arguments.output): 0030 path = os.path.join(arguments.output, certFile) 0031 if certFile.endswith('.der'): 0032 os.remove(path) 0033 elif os.path.isdir(path): 0034 shutil.rmtree(path) 0035 0036 def unpackMlFile(mlFileName): 0037 print (f"processing {mlFileName}") 0038 mlPemFile = runOpenSsl(f"cms -inform der -noverify -verify -in {mlFileName}") 0039 pems, _ = pyasn1.codec.der.decoder.decode(mlPemFile) 0040 keyData = {} 0041 i = 0 0042 while True: 0043 pemObj = pems.getComponentByPosition(1).getComponentByPosition(i, instantiate=False, default=None) 0044 if pemObj == None: 0045 break; 0046 pemData = pyasn1.codec.der.encoder.encode(pemObj) 0047 keyId = runOpenSsl('x509 -inform der -text -noout | grep -A1 "Subject Key Identifier" | tail -n 1', pemData).strip().decode().replace(':', '').lower() 0048 serial = runOpenSsl('x509 -inform der -serial -noout', pemData).strip().decode().replace('serial=', '').lower() 0049 if not keyId in keyData: 0050 keyData[keyId] = [] 0051 keyData[keyId].append((pemData, serial)) 0052 i += 1 0053 0054 # write certificates 0055 for keyId in keyData: 0056 if len(keyData[keyId]) == 1: 0057 writeToFile(os.path.join(arguments.output, f"{keyId}.der"), keyData[keyId][0][0]) 0058 derFileNames.append(f"{keyId}.der") 0059 else: 0060 os.mkdir(os.path.join(arguments.output, keyId)) 0061 for (cert,serial) in keyData[keyId]: 0062 writeToFile(os.path.join(arguments.output, keyId, f"{serial}.der"), cert) 0063 derFileNames.append(f"{keyId}/{serial}.der") 0064 0065 def writeQrcFile(): 0066 derFileNames.sort() 0067 qrcFile = open(os.path.join(arguments.output, 'icao-csca-certs.qrc'), 'w') 0068 qrcFile.write("""<!-- 0069 SPDX-FileCopyrightText: none 0070 SPDX-License-Identifier: CC0-1.0 0071 --> 0072 <RCC> 0073 <qresource prefix="/org.kde.khealthcertificate/icao/certs"> 0074 """) 0075 for derFileName in derFileNames: 0076 qrcFile.write(f" <file>{derFileName}</file>\n") 0077 qrcFile.write(" </qresource>\n</RCC>") 0078 qrcFile.close() 0079 0080 0081 parser = argparse.ArgumentParser(description='Download and unpack ICAO CSCA master lists.') 0082 parser.add_argument('--output', type=str, required=True, help='Path to which the output should be written to') 0083 arguments = parser.parse_args() 0084 0085 removeExistingCerts() 0086 0087 #unpackMlFile('ICAO_health_ml_27May2022.ml') 0088 #unpackMlFile('ICAO_ml_June_2022.ml') 0089 0090 # from https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/ElekAusweise/CSCA/GermanMasterList.zip 0091 unpackMlFile('20220623_DEMasterList.ml') 0092 0093 writeQrcFile()