def replace_keypair(): username = request.json.get('username') password_digest_str = request.json.get('password_digest_str') if username is None: return jsonify(message="user name is nothing."), 404 user = g.store.read_user(username, 'user_table') if user is None: return jsonify(message='user {0} is not found'.format(username)), 404 if user.password != password_digest_str: return jsonify(message='password is incorrect.'), 404 keypair_old = user.keypair keypair = bbclib.KeyPair() keypair.generate() g.idPubkeyMap = id_lib.BBcIdPublickeyMap(domain_id) g.idPubkeyMap.update(user.user_id, public_key_to_replace=[keypair.public_key], keypair=keypair_old) user.keypair = keypair g.store.update(user, 'user_table') return jsonify( pulic_key_str=bbclib.convert_id_to_string(keypair.public_key), private_key_str=bbclib.convert_id_to_string(keypair.private_key)), 200
def define_user(): if request.method == 'POST': password = request.json.get('password_digest_str') if password is None: abort_by_missing_param('password_digest_str') username = request.json.get('username') if username is None: abort_by_missing_param('username') if g.store.user_exists(username, 'user_table'): return jsonify( message='user {0} is already defined.'.format(username)), 409 idPubkeyMap = id_lib.BBcIdPublickeyMap(domain_id) user_id, keypairs = idPubkeyMap.create_user_id(num_pubkeys=1) g.store.write_user(User(user_id, username, password, keypairs[0]), 'user_table') return jsonify(public_key_str=bbclib.convert_id_to_string( keypairs[0].public_key), private_key_str=bbclib.convert_id_to_string( keypairs[0].private_key)), 200
def create_keypair(): if request.method == 'GET': keypair = bbclib.KeyPair() keypair.generate() return jsonify(private_key_str=bbclib.convert_id_to_string( keypair.private_key), public_key_str=bbclib.convert_id_to_string( keypair.public_key)), 200
def test_01_setup(self): print("\n-----", sys._getframe().f_code.co_name, "-----") global data_handler dummycore = DummyCore() conf = config["domains"][bbclib.convert_id_to_string(domain_id)] data_handler = DataHandler(networking=dummycore.networking, config=conf, workingdir="testdir", domain_id=domain_id) global transactions for i in range(10): txobj = bbclib.BBcTransaction() evt = bbclib.BBcEvent() evt.asset_group_id = asset_group_id1 evt.asset = bbclib.BBcAsset() evt.asset.add(user_id=user_id1, asset_body=b'aaaaaa') rtn = bbclib.BBcRelation() rtn.asset_group_id = asset_group_id2 rtn.asset = bbclib.BBcAsset() rtn.asset.add(user_id=user_id2, asset_body=b'bbbbbb', asset_file=b'cccccccccc%d' % i) ptr = bbclib.BBcPointer() ptr.add(transaction_id=txid1) rtn.add(pointer=ptr) if i > 0: ptr = bbclib.BBcPointer() ptr.add(transaction_id=transactions[-1].transaction_id) rtn.add(pointer=ptr) wit = bbclib.BBcWitness() txobj.add(event=evt, relation=rtn, witness=wit) wit.add_witness(user_id1) sig = txobj.sign(private_key=keypair1.private_key, public_key=keypair1.public_key) txobj.add_signature(user_id=user_id1, signature=sig) txobj.digest() transactions.append(txobj)
def signin(): if request.method == 'GET': return render_template('fileproof/sign-in.html') elif request.method == 'POST': password = request.form.get('password') if password is None or len(password) <= 0: return render_template('fileproof/message.html', message="ERROR: Password is missing.") password_digest = bbclib.get_new_id(password, include_timestamp=False) password_digest_str = bbclib.convert_id_to_string(password_digest) username = request.form.get('username') if username is None or len(username) <= 0: return render_template('fileproof/message.html', message='ERROR: User name is missing.') r = requests.get(PREFIX_API + '/api/user/keypair', params={ 'password_digest_str': password_digest_str, 'username': username }) res = r.json() if r.status_code != 200: return render_template('fileproof/message.html', message=res['message']) session['username'] = username session['user_id_str'] = res['user_id_str'] return render_template('fileproof/message.html', message="Getting keypair was success.")
def get_domain_config(self, domain_id, create_if_new=False): """Return the part of specified domain_id in the config dictionary""" domain_id_str = bbclib.convert_id_to_string(domain_id) conf = self.read_config() if 'domains' in conf and domain_id_str in conf['domains']: self.config['domains'][domain_id_str] = conf['domains'][domain_id_str] if create_if_new and domain_id_str not in self.config['domains']: self.config['domains'][domain_id_str] = { 'storage': { "type": "internal", # or "external" }, 'db': { "db_type": "sqlite", # or "mysql" "db_name": "bbc_ledger.sqlite", "replication_strategy": "all", # or "p2p"/"external" (valid only in db_type=mysql) "db_servers": [{"db_addr": "127.0.0.1", "db_port": 3306, "db_user": "******", "db_pass": "******"}] # valid only in the case of db_type=mysql }, 'static_nodes': { # id : [ipv4, ipv6, port] }, } if domain_id_str in self.config['domains']: return self.config['domains'][domain_id_str] return None
def __init__(self, networking=None, config=None, workingdir=None, domain_id=None, loglevel="all", logname=None): self.networking = networking self.core = networking.core self.stats = networking.core.stats self.logger = logger.get_logger(key="data_handler", level=loglevel, logname=logname) self.domain_id = domain_id self.domain_id_str = bbclib.convert_id_to_string(domain_id) self.config = config self.working_dir = workingdir self.storage_root = os.path.join(self.working_dir, self.domain_id_str) if not os.path.exists(self.storage_root): os.makedirs(self.storage_root, exist_ok=True) self.use_external_storage = self._storage_setup() self.replication_strategy = DataHandler.REPLICATION_ALL self.db_adaptors = list() self.dbs = list() self._db_setup()
def verify_file(): if session.get('username') is None: return redirect('/fileproof/sign-in') if request.method == 'GET': filename = request.args.get('file') fileinfo = get_id_from_mappings(os.path.basename(filename), asset_group_id) if fileinfo is None: return render_template('fileproof/message.html', message="%s is not found." % filename) asset_id = fileinfo['asset_id'] asset_id_str = bbclib.convert_id_to_string(asset_id) r = requests.get(PREFIX_API + '/api/file/verification', params={ 'asset_id_str': asset_id_str, 'asset_group_id_str': asset_group_id_str, 'user_id_str': session['user_id_str'] }) res = r.json() if r.status_code != 200: return render_template('fileproof/message.html', message=res['message']) return render_template('fileproof/message.html', message="%s is valid." % filename)
def list_users(): users = g.store.get_users('uset_table') dics = [{ 'username': user.name, 'user_id': bbclib.convert_id_to_string(user.user_id) } for user in users] return jsonify(users=dics), 200
def get_user_keypair(): username = request.args.get('username') password_digest_str = request.args.get('password_digest_str') user = g.store.read_user(username, 'user_table') if user is None: return jsonify(message='user {0} is not found'.format(username)), 404 if user.password != password_digest_str: return jsonify(message='password is incorrect.'), 404 return jsonify(username=username, user_id_str=bbclib.convert_id_to_string(user.user_id), public_key_str=bbclib.convert_id_to_string( user.keypair.public_key), private_key_str=bbclib.convert_id_to_string( user.keypair.private_key)), 200
def _register_demo(self, count): print("transaction_id's:") for i in range(count): txid = bbclib.get_new_id("dummy %d" % (i)) self.client.register_in_ledger_subsystem(None, txid) dat = wait_check_result_msg_type(self.client.callback, bbclib.MsgType.RESPONSE_REGISTER_HASH_IN_SUBSYS) print(bbclib.convert_id_to_string(txid))
def test_02_add_node(self): print("-----", sys._getframe().f_code.co_name, "-----") domain_id = binascii.a2b_hex("0000000000000000000000000000000000000000000000000000000000000000") dconf = config.get_domain_config(domain_id) assert dconf is not None node_id_str = bbclib.convert_id_to_string(bbclib.get_new_id("testnode1")) dconf['static_nodes'][node_id_str] = [1, 2, 3] config.update_config() with open(".bbc1/config.json", "r") as f: print(f.read())
def _config_demo(self, args): self.client.domain_setup(self.domain_id) dat = wait_check_result_msg_type(self.client.callback, bbclib.MsgType.RESPONSE_SETUP_DOMAIN) if KeyType.reason in dat: print("Failed:", dat[KeyType.reason]) print("domain_id:") print(bbclib.convert_id_to_string(self.domain_id)) args.transactions = 100 args.seconds = 30 self._config_tree(args)
def get_domain_config(self, domain_id, create_if_new=False): """Return the part of specified domain_id in the config dictionary""" domain_id_str = bbclib.convert_id_to_string(domain_id) conf = self.read_config() if 'domains' in conf and domain_id_str in conf['domains']: self.config['domains'][domain_id_str] = conf['domains'][domain_id_str] if create_if_new and domain_id_str not in self.config['domains']: self.config['domains'][domain_id_str] = self.config['domain_default'] if domain_id_str in self.config['domains']: return self.config['domains'][domain_id_str] return None
def save_all_static_node_list(self): """Save all static nodes in the config file""" self.logger.info("Saving the neighbor list") for domain_id in self.domains.keys(): conf = self.config.get_domain_config(domain_id) conf['static_node'] = dict() for node_id, nodeinfo in self.domains[domain_id][ 'neighbor'].nodeinfo_list.items(): if nodeinfo.is_static: nid = bbclib.convert_id_to_string(node_id) info = _convert_to_string( [nodeinfo.ipv4, nodeinfo.ipv6, nodeinfo.port]) conf['static_node'][nid] = info self.config.update_config() self.logger.info("Done...")
def issue_to_user(name, description, dic_services, dic_users): _, service_user = get_selected(dic_services) idPubkeyMap = id_lib.BBcIdPublickeyMap(domain_id) service = ticket_lib.BBcTicketService(domain_id, service_user.user_id, service_user.user_id, idPubkeyMap) spec = ticket_lib.TicketSpec(description=description, value=1, unit="x") ticket_id, _ = service.issue(dic_users[name].user_id, spec, keypair=service_user.keypair) print("ticket %s is issued to %s." % (bbclib.convert_id_to_string(ticket_id), name))
def signup(): if request.method == 'GET': return render_template('fileproof/sign-up.html') elif request.method == 'POST': r = requests.get(PREFIX_API + '/api/domain') res = r.json() if r.status_code != 200: return render_template( 'fileproof/message.html', message="ERROR: Failed to connect core node to domain(%s)." % res['domain_id']) password = request.form.get('password') if password is None or len(password) <= 0: return render_template('fileproof/message.html', message="ERROR: Password is missing.") password_digest = bbclib.get_new_id(password, include_timestamp=False) password_digest_str = bbclib.convert_id_to_string(password_digest) username = request.form.get('username') if username is None or len(username) <= 0: return render_template('fileproof/message.html', message='ERROR: User name is missing.') r = requests.post(PREFIX_API + '/api/user', json={ 'password_digest_str': password_digest_str, 'username': username }) res = r.json() if r.status_code != 200: return render_template('fileproof/message.html', message=res['message']) public_key = bbclib.convert_idstring_to_bytes(res['public_key_str']) private_key = bbclib.convert_idstring_to_bytes(res['private_key_str']) with open(PRIVATE_KEY, "wb") as fout: fout.write(private_key) with open(PUBLIC_KEY, "wb") as fout: fout.write(public_key) return redirect('/fileproof/sign-in')
def redeem_from_user(ticket_id, dic_services, dic_users): _, service_user = get_selected(dic_services) name, user = get_selected(dic_users) idPubkeyMap = id_lib.BBcIdPublickeyMap(domain_id) service = ticket_lib.BBcTicketService(domain_id, service_user.user_id, service_user.user_id, idPubkeyMap) if not service.is_valid_holder(user.user_id, ticket_id): print("%s is not the valid holder." % (name)) return service.redeem(user.user_id, ticket_id, keypair_from=user.keypair, keypair_service=service_user.keypair) print("%s is redeemed from %s." % (bbclib.convert_id_to_string(ticket_id), name))
def get_file(): if session.get('username') is None: return redirect('/fileproof/sign-in') if request.method == 'GET': filename = request.args.get('file') fileinfo = get_id_from_mappings(os.path.basename(filename), asset_group_id) if fileinfo is None: return render_template('fileproof/message.html', message="%s is not found." % filename) r = requests.get(PREFIX_API + '/api/file', params={ 'asset_id_str': bbclib.convert_id_to_string(fileinfo['asset_id']), 'user_id_str': session['user_id_str'], 'asset_group_id_str': asset_group_id_str, }) res = r.json() out_file_name, ext = os.path.splitext(filename) if os.path.exists(filename): current_datetime = datetime.now() time_str = current_datetime.strftime('_%Y%m%d%H%M%S') out_file_name += (time_str + ext) else: out_file_name += ext with open(out_file_name, "wb") as outfile: outfile.write(binascii.a2b_hex(res['file'])) return render_template('fileproof/message.html', message="done get %s" % out_file_name)
def create_new_domain(): domain_id = bbclib.get_new_id("certificate domain") tmpclient = bbc_app.BBcAppClient(port=bbc_config.DEFAULT_CORE_PORT, multiq=False, loglevel="all") tmpclient.domain_setup(domain_id) tmpclient.callback.synchronize() tmpclient.unregister_from_core() print("domain_id:") print(bbclib.convert_id_to_string(domain_id)) idPubkeyMap = id_lib.BBcIdPublickeyMap(domain_id) dic = {} id, keypairs = idPubkeyMap.create_user_id(num_pubkeys=1) dic[KEY_REGISTRY] = User(id, keypairs[0]) id, keypairs = idPubkeyMap.create_user_id(num_pubkeys=1) dic[KEY_USER] = User(id, keypairs[0]) write_dic(domain_id, dic)
def update_file(): if session.get('username') is None: return redirect('/fileproof/sign-in') if request.method == 'GET': return render_template('fileproof/store_file.html', action='/fileproof/update') elif request.method == 'POST': file = request.files.getlist('files')[0] if file and allowed_file(file.filename): data = file.read() data_non_bytes = binascii.b2a_hex(data).decode('utf-8') filename = secure_filename(file.filename) filepath = './' + filename #FIXME specific data directory is needed else: return render_template( 'fileproof/message.html', message='ERROR: file must be selected and allowed file type.') fileinfo = get_id_from_mappings(os.path.basename(filepath), asset_group_id) if fileinfo is None: return render_template('fileproof/message.html', message="ERROR: %s is already existed." % file.filename) user_info = "Owner is %s" % session['username'] transaction_id = fileinfo['transaction_id'] transaction_id_str = bbclib.convert_id_to_string(transaction_id) public_key, private_key = load_keypair() r = requests.post(PREFIX_API + '/api/file', json={ 'asset_body': user_info, 'asset_file': data_non_bytes, 'asset_group_id_str': asset_group_id_str, 'private_key_str': bbclib.convert_id_to_string(private_key), 'public_key_str': bbclib.convert_id_to_string(public_key), 'tx_id_str': transaction_id_str, 'user_id_str': session['user_id_str'] }) res = r.json() if r.status_code != 200: return render_template('fileproof/message.html', message=res['message']) asset_ids = bbclib.convert_idstring_to_bytes(res['asset_ids_str']) transaction_id = bbclib.convert_idstring_to_bytes( res['transaction_id_str']) store_id_mappings(os.path.basename(filepath), asset_group_id, transaction_id=transaction_id, asset_ids=asset_ids) message = "File update was success.\n" message += "asset_ids: %s \n" % res['asset_ids_str'] message += "transaction_id: %s \n" % res['transaction_id_str'] return render_template('fileproof/message.html', message=message)
def store_file(): if request.method == 'GET': asset_id_str = request.args.get('asset_id_str') asset_id = bbclib.convert_idstring_to_bytes(asset_id_str) asset_group_id_str = request.args.get('asset_group_id_str') asset_group_id = bbclib.convert_idstring_to_bytes(asset_group_id_str) user_id_str = request.args.get('user_id_str') user_id = bbclib.convert_idstring_to_bytes(user_id_str) bbc_app_client = setup_bbc_client(domain_id, user_id) ret = bbc_app_client.search_transaction_with_condition( asset_group_id=asset_group_id, asset_id=asset_id, user_id=user_id) assert ret response_data = bbc_app_client.callback.synchronize() if response_data[KeyType.status] < ESUCCESS: return jsonify(message="ERROR: %s" % response_data[KeyType.reason].decode('utf-8')), 404 transactions = [ bbclib.deserialize(data) for data in response_data[KeyType.transactions] ] get_transaction, fmt_type = transactions[0] if KeyType.all_asset_files in response_data: asset_file_dict = response_data[KeyType.all_asset_files] asset_id = get_transaction.relations[0].asset.asset_id data = asset_file_dict[asset_id] else: data = get_transaction.relations[0].asset.asset_body return jsonify({ 'file': binascii.b2a_hex(data).decode('utf-8'), 'message': None, 'status': 'success' }) elif request.method == 'POST': asset_body = request.json.get('asset_body') asset_file = request.json.get('asset_file') asset_file_bytes = binascii.a2b_hex(asset_file) asset_group_id_str = request.json.get('asset_group_id_str') asset_group_id = bbclib.convert_idstring_to_bytes(asset_group_id_str) private_key_str = request.json.get('private_key_str') private_key = bbclib.convert_idstring_to_bytes(private_key_str) public_key_str = request.json.get('public_key_str') public_key = bbclib.convert_idstring_to_bytes(public_key_str) keypair = bbclib.KeyPair(privkey=private_key, pubkey=public_key) tx_id_str = request.json.get('tx_id_str') if tx_id_str is not None: tx_id = bbclib.convert_idstring_to_bytes(tx_id_str) else: tx_id = None user_id_str = request.json.get('user_id_str') user_id = bbclib.convert_idstring_to_bytes(user_id_str) asset_ids, transaction_id, message = \ store_proc(asset_body, asset_file_bytes, asset_group_id, domain_id, keypair, user_id, txid=tx_id) if message is not None: return jsonify(message=message), 404 if asset_ids is None: return jsonify(message="ERROR: asset_id is not found"), 404 if transaction_id is None: return jsonify(message="ERROR: transaction_id is not found"), 404 return jsonify(asset_ids_str=bbclib.convert_id_to_string(asset_ids), transaction_id_str=bbclib.convert_id_to_string( transaction_id)), 200
from bbc1.core import bbclib from bbc1.core.bbc_config import DEFAULT_CORE_PORT MAPPING_FILE = ".bbc_id_mappings" PUBLIC_KEY = ".public_key" PRIVATE_KEY = ".private_key" PREFIX_API = 'http://127.0.0.1:5000' #FIXME to be flexible fileproof = Blueprint('fileproof', __name__, static_folder='./static', template_folder='./templates') asset_group_id = bbclib.get_new_id("file_proof_asset_group", include_timestamp=False) asset_group_id_str = bbclib.convert_id_to_string(asset_group_id) def allowed_file(filename, allowed_ext={'txt'}): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in allowed_ext def get_id_from_mappings(name, asset_group_id): if not os.path.exists(MAPPING_FILE): return None asset_group_id_str = binascii.b2a_hex(asset_group_id).decode() with open(MAPPING_FILE, "r") as f: mapping = json.load(f) if mapping is None: return None
user_id1 = bbclib.get_new_id("destination_id_test1") user_id2 = bbclib.get_new_id("destination_id_test2") domain_id = bbclib.get_new_id("test_domain") asset_group_id1 = bbclib.get_new_id("asset_group_1") asset_group_id2 = bbclib.get_new_id("asset_group_2") txid1 = bbclib.get_new_id("dummy_txid_1") txid2 = bbclib.get_new_id("dummy_txid_2") keypair1 = bbclib.KeyPair() keypair1.generate() transactions = list() data_handler = None config = { "domains": { bbclib.convert_id_to_string(domain_id): { "storage": { "type": "internal", }, "db": { "db_type": "mysql", "db_name": "bbctest", 'replication_strategy': "external", "db_servers": [{ "db_addr": "127.0.0.1", "db_port": 3306, "db_user": "******", "db_pass": "******"
def create_domain(self, domain_id=ZEROS, config=None): """Create domain and register user in the domain Args: domain_id (bytes): target domain_id to create config (dict): configuration for the domain Returns: bool: """ if domain_id in self.domains: return False conf = self.config.get_domain_config(domain_id, create_if_new=True) if config is not None: conf.update(config) if 'node_id' not in conf or conf['node_id'] == "": node_id = bbclib.get_random_id() conf['node_id'] = bbclib.convert_id_to_string(node_id) self.config.update_config() else: node_id = bbclib.convert_idstring_to_bytes(conf.get('node_id')) self.domains[domain_id] = dict() self.domains[domain_id]['node_id'] = node_id self.domains[domain_id]['name'] = node_id.hex()[:4] self.domains[domain_id]['neighbor'] = NeighborInfo( network=self, domain_id=domain_id, node_id=node_id, my_info=self._get_my_nodeinfo(node_id)) self.domains[domain_id]['topology'] = TopologyManagerBase( network=self, domain_id=domain_id, node_id=node_id, logname=self.logname, loglevel=self.loglevel) self.domains[domain_id]['user'] = UserMessageRouting( self, domain_id, logname=self.logname, loglevel=self.loglevel) self.get_domain_keypair(domain_id) workingdir = self.config.get_config()['workingdir'] if domain_id == ZEROS: self.domains[domain_id]['data'] = DataHandlerDomain0( self, domain_id=domain_id, logname=self.logname, loglevel=self.loglevel) self.domain0manager = Domain0Manager(self, node_id=node_id, logname=self.logname, loglevel=self.loglevel) else: self.domains[domain_id]['data'] = DataHandler( self, config=conf, workingdir=workingdir, domain_id=domain_id, logname=self.logname, loglevel=self.loglevel) self.domains[domain_id]['repair'] = RepairManager( self, domain_id, workingdir=workingdir, logname=self.logname, loglevel=self.loglevel) if self.domain0manager is not None: self.domain0manager.update_domain_belong_to() for dm in self.domains.keys(): if dm != ZEROS: self.domains[dm]['neighbor'].my_info.update(domain0=True) self.domains[domain_id]['topology'].update_refresh_timer_entry(1) self.stats.update_stats_increment("network", "num_domains", 1) self.logger.info("Domain %s is created" % (domain_id.hex())) return True
def remove_domain_config(self, domain_id): """Remove the part of specified domain_id in the config dictionary""" domain_id_str = bbclib.convert_id_to_string(domain_id) if domain_id_str in self.config['domains']: del self.config['domains'][domain_id_str] self.update_config()
def get_transactions(): if request.method == 'GET': asset_id_str = request.args.get('asset_id_str') if asset_id_str is not None: asset_id = bbclib.convert_idstring_to_bytes(asset_id_str) else: asset_id = None asset_group_id_str = request.args.get('asset_group_id_str') if asset_group_id_str is not None: asset_group_id = bbclib.convert_idstring_to_bytes( asset_group_id_str) else: asset_group_id = None count = request.args.get('count') if count is None: count = 0 direction = request.args.get('direction') if direction is None: direction = 0 start_from = request.args.get('start_from') if start_from is None: start_from = None until = request.args.get('until') if until is None: until = None user_id_search_str = request.args.get('user_id_search_str') if user_id_search_str is not None: user_id_search = bbclib.convert_idstring_to_bytes( user_id_search_str) else: user_id_search = None user_id_str = request.args.get('user_id_str') user_id = bbclib.convert_idstring_to_bytes(user_id_str) bbc_app_client = setup_bbc_client(domain_id, user_id) ret = bbc_app_client.search_transaction_with_condition( asset_group_id=asset_group_id, asset_id=asset_id, user_id=user_id) assert ret response_data = bbc_app_client.callback.synchronize() if response_data[KeyType.status] < ESUCCESS: return jsonify(message="ERROR: %s" % response_data[KeyType.reason].decode('utf-8')), 404 transactions = [ bbclib.deserialize(data) for data in response_data[KeyType.transactions] ] dics = [] for tx_tuple in transactions: tx, fmt_type = tx_tuple dics.append({ 'transaction_id': bbclib.convert_id_to_string(tx.transaction_id), 'asset_group_id': bbclib.convert_id_to_string(tx.relations[0].asset_group_id), 'asset_id': bbclib.convert_id_to_string(tx.relations[0].asset.asset_id), 'user_id': bbclib.convert_id_to_string(tx.relations[0].asset.user_id), 'timestamp': datetime.fromtimestamp(tx.timestamp / 1000) }) return jsonify(transactions=dics), 200
action='store', help='Seed strings for calculating SHA256') argparser.add_argument('-t', '--timebaseid', action='store_true', default=False, help='Concatenate timestamp with seed strings') argparser.add_argument('-r', '--random', action='store_true', help='Seed strings for calculating SHA256') return argparser.parse_args() if __name__ == '__main__': parsed_args = argument_parser() if parsed_args.string: value = bbclib.get_new_id(parsed_args.string, include_timestamp=parsed_args.timebaseid) print(bbclib.convert_id_to_string(value)) sys.exit(0) if parsed_args.random: value = bbclib.get_random_id() print(bbclib.convert_id_to_string(value)) sys.exit(0) sys.stderr.write("# Either -s or -r is required\n") sys.exit(1)