Skip to content

Commit 4dfa677

Browse files
committed
Hash for revocation in scan_dcc.py
1 parent 517f6be commit 4dfa677

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

tests/scan_dcc.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
from base45 import b45decode
1111
from cose.messages import Sign1Message
1212
from datetime import datetime
13+
from hashlib import sha256
14+
from base64 import b64encode
1315

1416
def main(args):
1517
if args.algorithm:
16-
with_all_dccs( print_algorithm, error_handler=_throw, exclude='venv*' )
18+
with_all_dccs( print_algorithm, error_handler=_throw )
1719
if not args.validity_at is None:
1820
validation_clock = datetime.fromisoformat(args.validity_at)
19-
with_all_dccs( lambda f: validity_at(validation_clock, f), error_handler=_throw, exclude='venv*' )
21+
with_all_dccs( lambda f: validity_at(validation_clock, f), error_handler=_throw )
22+
if args.hash:
23+
with_all_dccs( print_hashes, error_handler=_display )
2024

2125
def with_all_dccs( function, error_handler=None, exclude="" ):
2226
''' Walks through the current directory and all subdirectories and calls
@@ -29,13 +33,12 @@ def with_all_dccs( function, error_handler=None, exclude="" ):
2933
fqfn = str(Path(base, file)) # fully qualified file name
3034
try:
3135
if not fnmatch( fqfn, exclude ):
32-
function(fqfn )
36+
function( fqfn )
3337
except Exception as error:
3438
if not error_handler is None:
3539
error_handler( fqfn, error)
3640

3741

38-
3942
def load_dcc( file ):
4043
'''Load QR code from image file and return Sign1Message and Payload
4144
Usage: s1msg, payload = load_dcc('my_dcc.png')
@@ -54,10 +57,6 @@ def load_dcc_with_rawdata( file ):
5457
logging.debug('Decoding/Decompressing Base45 data')
5558
decompressed = zlib.decompress(b45decode(qr_code_data[4:]))
5659
s1msg = Sign1Message.decode(decompressed)
57-
# print(cbor2.loads(decompressed))
58-
# print(f'Unprotected Header: {cose_data.uhdr}')
59-
# print(f'Protected Header: {cose_data.phdr}')
60-
# print(f'KID = {get_kid_b64(cose_data)}')
6160
payload = cbor2.loads(s1msg.payload)
6261
return s1msg, payload, qr_code_data
6362

@@ -69,6 +68,36 @@ def _throw( file, error ):
6968
print('Error reading', file)
7069
raise error
7170

71+
def _display( file, error ):
72+
print('Error reading', file)
73+
74+
75+
def get_hashes(file):
76+
def hashfunc( value ):
77+
'First 16 bytes only, base64-encoded'
78+
if isinstance( value, str ):
79+
value = value.encode('utf-8')
80+
return b64encode(sha256(value).digest()[:16]).decode('utf-8')
81+
82+
83+
s1msg, payload = load_dcc(file)
84+
country_code = payload[1]
85+
inner = payload[-260][1]
86+
uci = inner['v' if 'v' in inner.keys() else 't' if 't' in inner.keys() else 'r'][0]['ci']
87+
if get_algorithm(s1msg) == 'ES256':
88+
signature = s1msg.signature[:len(s1msg.signature)//2]
89+
else:
90+
signature = s1msg.signature
91+
92+
return {
93+
'UCI' : hashfunc(uci),
94+
'COUNTRYCODEUCI' : hashfunc(country_code+uci),
95+
'SIGNATURE' : hashfunc(signature)
96+
}
97+
98+
def print_hashes(file):
99+
print(f'{file}\t{get_hashes(file)}')
100+
72101
def validity_at( validation_clock, file ):
73102
s1msg, payload = load_dcc(file)
74103
dcc_from = datetime.fromtimestamp(payload[6])
@@ -78,22 +107,24 @@ def validity_at( validation_clock, file ):
78107
print( '\t'.join([file, validity, validation_clock.isoformat()]))
79108

80109

81-
def print_algorithm( file ):
110+
def get_algorithm( s1msg ):
82111
'''Print the algorithm of a DCC
83112
ES256 = SHA256 with ECDSA
84113
PS256 = RSASSA-PSS using SHA-256
85114
'''
86-
s1msg, payload = load_dcc(file)
87115
for key,value in s1msg.phdr.items():
88116
_key = key.fullname
89117
if _key == 'ALG':
90-
_value = value.fullname
91-
print( '\t'.join([file, _value]))
92-
118+
return value.fullname
119+
93120

121+
def print_algorithm( file ):
122+
s1msg, payload = load_dcc(file)
123+
print( '\t'.join([file, get_algorithm(s1msg)]))
94124

95125
if __name__ == '__main__':
96126
parser = ArgumentParser(description='Scan all DCCs for something')
127+
parser.add_argument('--hash', action='store_true', help='Print hashes')
97128
parser.add_argument('--algorithm', action='store_true', help='Print algorithm')
98129
parser.add_argument('--validity-at', action='store', default=None, help='Check validity at ISO date')
99130
args = parser.parse_args()

0 commit comments

Comments
 (0)