gen-miniroon.py (2310B)
1 #!/usr/bin/env python3 2 import argparse 3 import base64 4 import hmac 5 import json 6 import os 7 import sys 8 9 10 class NetString(bytes): 11 @classmethod 12 def from_any(cls, data): 13 if isinstance(data, NetString): 14 return cls(data) 15 if isinstance(data, bytes): 16 return cls(to_ns(data)) 17 if isinstance(data, str): 18 return cls(to_ns(data.encode('ascii'))) 19 assert not isinstance(data, dict) 20 return cls(to_ns(to_ns_list(data))) 21 22 23 def to_ns(b): 24 assert isinstance(b, bytes) 25 return NetString(b'%d:%s,' % (len(b), b)) 26 27 28 def to_ns_list(data): 29 assert not isinstance(data, (dict, bytes, str)) 30 return b''.join(NetString.from_any(i) for i in data) 31 32 33 def miniroon_hmac(key, msg): 34 assert len(key) == 32 35 print('miniroon_hmac%r' % ((key, msg),), file=sys.stderr) 36 #return hmac.digest(key, msg, 'blake2s') 37 return hmac.digest(key, msg, 'sha256') 38 39 40 def make_miniroon(name, action='invoke-once', secret=b'\0'*32, caveats=(), version='capv0', unwrap=False): 41 hdr = b''.join(NetString.from_any(i) for i in (version, name, action)) 42 caveats_ns = [to_ns_list(c) for c in caveats] 43 sig = miniroon_hmac(secret, hdr) 44 for c in caveats_ns: 45 sig = miniroon_hmac(sig, c) 46 if unwrap: 47 return b''.join(map(NetString.from_any, (hdr, caveats_ns, sig))) 48 else: 49 return NetString.from_any([hdr, caveats_ns, sig]) 50 51 52 def main_old(): 53 import os 54 # os.write(1, make_miniroon(name='ccx')) 55 os.write(1, make_miniroon(name='ccx', caveats=[ 56 ('env-is', 'var1', 'hello'), 57 ('env-absent', 'var2'), 58 ('env-glob', 'var3', '_*'), 59 # ('x-glob', 'var3', '_*'), 60 ('env-is', 'var3', '_hello'), 61 ])) 62 63 64 argument_parser = argparse.ArgumentParser() 65 argument_parser.add_argument('--unwrap', action='store_true', default=False) 66 argument_parser.add_argument('json_in', type=argparse.FileType(mode='r'), nargs="?", default=sys.stdin) 67 68 69 def main(): 70 args = argument_parser.parse_args() 71 data = json.load(args.json_in) 72 data['unwrap'] = args.unwrap 73 assert isinstance(data, dict) 74 if 'secret_b64' in data: 75 assert 'secret' not in data 76 data['secret'] = base64.b64decode(data['secret_b64']) 77 os.write(1, make_miniroon(**data)) 78 79 80 if __name__ == '__main__': 81 main()