def create(self): self.created = datetime.datetime.utcnow() self.valid = datetime.datetime.utcnow() + datetime.timedelta(days=365) self.mp, self.ms = nacl.crypto_sign_keypair() self.sp, self.ss = nacl.crypto_sign_keypair() self.cp, self.cs = nacl.crypto_box_keypair() self.save()
def register(team_name): team_name = to_unicode(team_name) log.info('updating subrepo') SubRepo.pull() log.info('registering new team: %s' % team_name) team = Team(name=team_name) if team.exists(): log.fail('team is already registered') return False log.info('generating encryption keypair') crypt_pk, crypt_sk = pysodium.crypto_box_keypair() log.info('generating signature keypair') sign_pk, sign_sk = pysodium.crypto_sign_keypair() team.update({'crypt_pk': crypt_pk, 'sign_pk': sign_pk}) team.validate() team.save() SubRepo.push(commit_message='Register team %s' % team_name) log.success('team %s added successfully' % team_name) write_team_secrets(team.id, crypt_sk, sign_sk) return True
def test_url_protocol_id(self, mocked_get_secret_key): """ PUSHTOKEN: Test url protocol id customization """ public_key, secret_key = crypto_sign_keypair() mocked_get_secret_key.return_value = secret_key user_public_key = base64.b64encode(public_key) fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with nested(patch.dict(config), request_context_safety()): if 'mobile_app_protocol_id' in config: del config['mobile_app_protocol_id'] request_context['hsm'] = fake_hsm_wrapper # if no mobile_app_protocol_id is set, it should default # to lseqr message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') self.assertTrue(url.startswith('lseqr://')) # ------------------------------------------------------------------ -- fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with nested(patch.dict(config, {'mobile_app_protocol_id': 'yolo'}), request_context_safety()): request_context['hsm'] = fake_hsm_wrapper message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') self.assertTrue(url.startswith('yolo://'))
def __init_cryptokey(self, file): self._logger.warning("Initializing new CryptoKey file %s", file) pk,sk = pysodium.crypto_sign_keypair() self._logger.warning(" Public key: %s", pysodium.crypto_sign_sk_to_pk(sk).hex()) with open(file, "wb") as f: f.write(msgpack.packb([sk,pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES)], use_bin_type=True)) self._logger.warning(" CryptoKey Initialized. Provisioning required for successful operation.")
def getkey(keydir): datadir = os.path.expanduser(keydir) esk = None try: with open(datadir + 'server-key', 'rb') as fd: esk = fd.read(pysodium.crypto_sign_SECRETKEYBYTES) with open(datadir + 'server-xkey', 'rb') as fd: xsk = fd.read(pysodium.crypto_box_SECRETKEYBYTES) with open(datadir + 'server-xkey.pub', 'rb') as fd: xpk = fd.read(pysodium.crypto_box_PUBLICKEYBYTES) return esk, xsk, xpk except FileNotFoundError: print("no server key found, generating...") if not os.path.exists(datadir): os.mkdir(datadir, 0o700) if esk is None: epk, esk = pysodium.crypto_sign_keypair() else: epk = pysodium.crypto_sign_sk_to_pk(esk) xsk = pysodium.crypto_sign_sk_to_box_sk(esk) xpk = pysodium.crypto_sign_pk_to_box_pk(epk) with open(datadir + 'server-key', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(esk) with open(datadir + 'server-key.pub', 'wb') as fd: fd.write(epk) with open(datadir + 'server-xkey', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(xsk) with open(datadir + 'server-xkey.pub', 'wb') as fd: fd.write(xpk) print("please share `%s` with all clients" % (datadir + 'server-key.pub')) return esk, xsk, xpk
def test_blake2b(): """ Used generic hash in LibSodium which is Blake2b Also hash std lib """ # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES verkey = b'Z\x80s\x81\xd3\xf4\xaa\x94\x80\x86\x9bH\x8ay\xc2\xf9\x89k_\x946\xf1_`\x8c\xa9\xd8\xd2b\xe4\x00\x08' # digest of publickey digest = pysodium.crypto_generichash(verkey) assert len(digest) == 32 == pysodium.crypto_generichash_BYTES assert digest == ( b'\xf9\xa4\xe3\x87\x05\xc9\xf8\x9b\x18pI\xf3\xb5G@\xdf\x03\xbe\xcc\x9b)\xe7u\xeaH\x19\x1d\xe6*4Yp' ) digestbig = pysodium.crypto_generichash(verkey, outlen=64) assert len(digestbig) == 64 # assert digestbig[:32] == digest # not true for blake2b dig = hashlib.blake2b(verkey, digest_size=32).digest() assert dig == ( b'\xf9\xa4\xe3\x87\x05\xc9\xf8\x9b\x18pI\xf3\xb5G@\xdf\x03\xbe\xcc\x9b)\xe7u\xeaH\x19\x1d\xe6*4Yp' ) assert len(dig) == 32 assert dig == digest digbig = hashlib.blake2b(verkey).digest() assert len(digbig) == 64 assert digbig == digestbig """
def test_sha2(): """ Used pysoidium.crypto_hash_sha256(message) """ # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES verkey = b'Z\x80s\x81\xd3\xf4\xaa\x94\x80\x86\x9bH\x8ay\xc2\xf9\x89k_\x946\xf1_`\x8c\xa9\xd8\xd2b\xe4\x00\x08' # digest of publickey digest = pysodium.crypto_hash_sha256(verkey) assert len(digest) == 32 == pysodium.crypto_generichash_BYTES assert digest == ( b'\x81\xce\x15L\x8b3\xb1mI\x9bF\xd9(\x0e\x99\x08SH6\xb9\xb5)\xf6\x93\xd0\x7f\x85\xe1r\xa7\x13\xd7' ) digestbig = pysodium.crypto_hash_sha512(verkey) assert len(digestbig) == 64 # assert digestbig[:32] == digest # not true for sha256 sha512 dig = hashlib.sha256(verkey).digest() assert len(dig) == 32 assert dig == digest digbig = hashlib.sha512(verkey).digest() assert len(digbig) == 64 assert digbig == digestbig """
def test_sha3(): """ Used pysoidium.crypto_hash_sha256(message) """ # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES verkey = b'Z\x80s\x81\xd3\xf4\xaa\x94\x80\x86\x9bH\x8ay\xc2\xf9\x89k_\x946\xf1_`\x8c\xa9\xd8\xd2b\xe4\x00\x08' dig = hashlib.sha3_256(verkey).digest() assert len(dig) == 32 assert dig == ( b'\xd6\x00\xac_&\xeb\xd5"\xbaP\xdc\xb7\x06\x91^{\xa3\x18\xca\n+t\xbe\x1c7\xebY5ww\xdd7' ) digbig = hashlib.sha3_512(verkey).digest() assert len(digbig) == 64 assert digbig == ( b'X\x0e\t\x03{--\xf1oms6\xb0\xb2\x94m.\xe1=?\xee\xbe\xd18\xa7\x90\x04\xc6' b'd\xbd):\x9d\xaf\xd3\xc3\xb4V\xb3s8]G\x92F\x92\x0c\xb1\x86\xd1\x13\x88' b':\xd5\xd6\x84%\x18\x94u\xf2\xff\xd5|') # assert digbig[:32] == dig # not true for sha256 sha512 """
def test_crypto_sign_open(self): pk, sk = pysodium.crypto_sign_keypair() signed = pysodium.crypto_sign(b'howdy', sk) changed = signed[:pysodium.crypto_sign_BYTES] + b'0' + signed[ pysodium.crypto_sign_BYTES + 1:] pysodium.crypto_sign_open(signed, pk) self.assertRaises(ValueError, pysodium.crypto_sign_open, changed, pk)
def as_bytes(self): # magic signature datagram = bytearray("GARLICKYCLIENT", "ascii") # protocol version number datagram.extend(struct.pack(">H", 0)) # generate ephemeral key self.eph_pk, self.eph_sk = pysodium.crypto_kx_keypair() assert len(self.eph_pk) == 32 datagram.extend(self.eph_pk) # generate keypair for signature self.sign_pk, self.sign_sk = pysodium.crypto_sign_keypair() assert len(self.sign_pk) == 32 datagram.extend(self.sign_pk) # sign the ephemeral key cus untrusted apparently :/ # print(pysodium.sodium.crypto_sign_ed25519_detached) sig = ctypes.create_string_buffer(pysodium.crypto_sign_BYTES) check(pysodium.sodium.crypto_sign_ed25519_detached( sig, ctypes.c_void_p(0), self.eph_pk, ctypes.c_ulonglong(len(self.eph_pk)), self.sign_sk, )) assert len(sig) == 64 # pysodium.crypto_sign_detached(eph_pk, sign_sk) datagram.extend(sig) assert len(datagram) == 144 return datagram
def _generate_new(privkey=None): pk, sk = pysodium.crypto_sign_keypair() save_privkey(binascii.b2a_hex(sk)) save_pubkey(binascii.b2a_hex(pk)) address = binascii.b2a_hex(pysodium.crypto_generichash_blake2b_salt_personal(pk, key = "ZibbitZibbit")[12:]) save_address(address)
def test_sk_to_pk(): #pk, sk = pysodium.crypto_box_keypair() pk, sk = pysodium.crypto_sign_keypair() pk2 = pysodium.crypto_sign_sk_to_pk(sk) print(pk == pk2)
def test_url_protocol_id(self, base_app, mocked_get_secret_key): """ PUSHTOKEN: Test url protocol id customization """ public_key, secret_key = crypto_sign_keypair() mocked_get_secret_key.return_value = secret_key user_public_key = base64.b64encode(public_key) fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with base_app.test_request_context(): if 'mobile_app_protocol_id' in config: del config['mobile_app_protocol_id'] request_context['hsm'] = fake_hsm_wrapper # if no mobile_app_protocol_id is set, it should default # to lseqr message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') assert url.startswith('lseqr://') # ------------------------------------------------------------------ -- fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with base_app.test_request_context(): config['mobile_app_protocol_id'] = 'yolo' request_context['hsm'] = fake_hsm_wrapper message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') assert url.startswith('yolo://')
def signature_keys_generate () : log ("[744dd497]", "[crypto][signature]", "generating signature public-private keys...") _local_sign_pub_key, _local_sign_priv_key = pysodium.crypto_sign_keypair () log ("[1f11c829]", "[crypto][signature]", "generated signature private key `%s`;", _local_sign_priv_key.encode ("b64")) log ("[2708e032]", "[crypto][signature]", "generated signature public key `%s`;", _local_sign_pub_key.encode ("b64")) return _local_sign_pub_key, _local_sign_priv_key
def key_pair(seed: Optional[bytes] = None) -> Tuple[bytes, bytes]: """A new public key and secret key pair. :param seed: Seed value. Must be at least 32 characters in length """ if seed: if len(seed) < crypto_sign_SEEDBYTES: message = "'seed' argument must be of length > {}" raise ValueError(message.format(crypto_sign_SEEDBYTES)) return crypto_sign_seed_keypair(seed) return crypto_sign_keypair()
def getkey(self): datadir = os.path.expanduser(self.datadir) try: fd = open(datadir + 'key', 'rb') key = fd.read() fd.close() return key except FileNotFoundError: if not os.path.exists(datadir): os.mkdir(datadir, 0o700) pk, sk = pysodium.crypto_sign_keypair() with open(datadir + 'key', 'wb') as fd: if not win: os.fchmod(fd.fileno(), 0o600) fd.write(sk) return sk
def make_keypair(): public_key, private_key = pysodium.crypto_sign_keypair() print 'Do you wish to encrypt the private key under a password? (y/n)' answer = raw_input().lower() if answer not in ['y', 'n']: raise SystemExit('Invalid answer') if answer == 'y': salt = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES) key = hash_password(prompt_for_new_password(), salt) nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) cyphertext = pysodium.crypto_secretbox(private_key, nonce, key) private_key = b'y' + salt + nonce + cyphertext else: private_key = b'n' + private_key return base64.b64encode(private_key), base64.b64encode(public_key)
def test(n_nodes, n_turns): kps = [crypto_sign_keypair() for _ in range(n_nodes)] network = {} stake = {kp[0]: 1 for kp in kps} nodes = [Node(kp, network, n_nodes, stake) for kp in kps] for n in nodes: network[n.pk] = n.ask_sync mains = [n.main() for n in nodes] for m in mains: next(m) for i in range(n_turns): r = randrange(n_nodes) print('working node: %i, event number: %i' % (r, i)) next(mains[r]) return nodes
def generate_identity(): pk, sk, handle = None, None, None while True: pk, sk = pysodium.crypto_sign_keypair() if hash_pubkey(pk): break while True: enc = pysodium.randombytes(16) try: handle = hash_pubkey(pk) + hx(enc) expand_handle(handle) except: continue break return Identity(pk=pk, sk=sk, \ enc=enc, handle=handle)
def main(): if len(sys.argv) == 2: path = sys.argv[1] else: path = os.path.join(sys.argv[1], "node" + sys.argv[2]) dump_path = os.path.join(path, "privkey") pk, sk = pysodium.crypto_sign_keypair() f = open(dump_path, "w") f.write(binascii.b2a_hex(sk)) f.close() auth_path = os.path.join(sys.argv[1], "authorities") authority = binascii.b2a_hex( pysodium.crypto_generichash_blake2b_salt_personal( pk, key="CryptapeCryptape")[12:]) auth_file = open(auth_path, "a") auth_file.write("0x" + authority + "\n") auth_file.close()
def test_blake2s(): """ Used hash std lib """ # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES verkey = b'Z\x80s\x81\xd3\xf4\xaa\x94\x80\x86\x9bH\x8ay\xc2\xf9\x89k_\x946\xf1_`\x8c\xa9\xd8\xd2b\xe4\x00\x08' dig = hashlib.blake2s(verkey, digest_size=32).digest() assert dig == ( b'E(\x89\xec\xfc\xe4\x02\xba\x05\xcc\xf35=\xfa\xfa\xb1\x87\t\x99\xd0Q:\t\x80f^\xe4J\x17\xe9\x9d\x1a' ) assert len(dig) == 32 """
def getkey(keydir): datadir = os.path.expanduser(keydir) try: with open(datadir + 'server-key', 'rb') as fd: key = fd.read() return key except FileNotFoundError: print("no server key found, generating...") if not os.path.exists(datadir): os.mkdir(datadir, 0o700) pk, sk = pysodium.crypto_sign_keypair() with open(datadir + 'server-key', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(sk) with open(datadir + 'server-key.pub', 'wb') as fd: fd.write(pk) print("please share `%s` with all clients" % (datadir + 'server-key.pub')) return sk
def make_keypair() -> Tuple[bytes, bytes]: public_key, private_key = pysodium.crypto_sign_keypair() print('Do you wish to encrypt the private key under a password? (y/n)') answer: str while True: answer = input('>').lower() if answer not in ['y', 'n']: print('Invalid answer') else: break if answer == 'y': salt: bytes = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES) key: bytes = hash_password(prompt_for_new_password(), salt) nonce: bytes = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) cyphertext: bytes = pysodium.crypto_secretbox(private_key, nonce, key) private_key = b'y' + salt + nonce + cyphertext else: private_key = b'n' + private_key return base64.b64encode(private_key), base64.b64encode(public_key)
def test_repairing_fail_sig(self): """ PushToken: Check if repairing fails correctly (wrong sig) """ user_token_id = self.execute_correct_pairing() # temporarily switch the secret key (used for signature) tmp_secret_key = self.secret_key _public_key, self.secret_key = crypto_sign_keypair() # ------------------------------------------------------------------ -- # send repairing pairing response pairing_response = self.create_pairing_response_by_serial( user_token_id) response_dict = self.send_pairing_response(pairing_response) # ------------------------------------------------------------------ -- # check if returned json is correct self.assertIn('result', response_dict) result = response_dict.get('result') self.assertIn('value', result) value = result.get('value') self.assertFalse(value) self.assertIn('status', result) status = result.get('status') self.assertFalse(status) # ------------------------------------------------------------------ -- # reset the secret key self.secret_key = tmp_secret_key
def test_blake3(): """ Test needed functions from blake3 https://github.com/BLAKE3-team/BLAKE3/ """ # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES verkey = b'Z\x80s\x81\xd3\xf4\xaa\x94\x80\x86\x9bH\x8ay\xc2\xf9\x89k_\x946\xf1_`\x8c\xa9\xd8\xd2b\xe4\x00\x08' # digest of publickey digest = blake3.blake3(verkey).digest() assert len(digest) == 32 == blake3.OUT_LEN assert digest == b'\xb4\xaf\xd5,G\x97\xaf\x06\xda\xbbTNs\xcbM4\xa81\xb8\xcd\xc60\xc7c"\xe2B\xe5_\x96\xcb\x95' digestbig = blake3.blake3(verkey).digest(length=64) assert len(digestbig) == 64 assert digestbig[:32] == digest """
def test_repairing_fail_sig(self): """ PushToken: Check if repairing fails correctly (wrong sig) """ user_token_id = self.execute_correct_pairing() # temporarily switch the secret key (used for signature) tmp_secret_key = self.secret_key _public_key, self.secret_key = crypto_sign_keypair() # ------------------------------------------------------------------ -- # send repairing pairing response pairing_response = self.create_pairing_response_by_serial( user_token_id) response_dict = self.send_pairing_response(pairing_response) # ------------------------------------------------------------------ -- # check if returned json is correct assert 'result' in response_dict result = response_dict.get('result') assert 'value' in result value = result.get('value') assert not value assert 'status' in result status = result.get('status') assert not status # ------------------------------------------------------------------ -- # reset the secret key self.secret_key = tmp_secret_key
def mock_app(): app = Flask(__name__) app.config['PASETO_SECRET_KEY'] = '0' * 32 # must be 32 byte pk, sk = pysodium.crypto_sign_keypair() app.config['PASETO_PRIVATE_KEY'] = sk app.config['PASETO_PUBLIC_KEY'] = pk paseto = Paseto(app) @app.route('/protected/local/') @paseto_required def protected(): claims = get_paseto_claim() return jsonify(claims), 200 @app.route('/create/local/token/') def create_token(): ret = {'access_token': create_access_token({'test user': '******'})} return jsonify(ret), 200 @app.route('/create/public/token/') def create_public_token(): ret = { 'access_token': create_access_token_public({'public test user': '******'}) } return jsonify(ret), 200 @app.route('/protected/public/') @paseto_required def protected_public(): claims = get_paseto_claim_public() return jsonify(claims), 200 return app
def test_crypto_sign_sk_to_pk(self): pk, sk = pysodium.crypto_sign_keypair() pk2 = pysodium.crypto_sign_sk_to_pk(sk) self.assertEqual(pk, pk2)
def __init__(self, n_nodes): self.i = 0 kps = [crypto_sign_keypair() for _ in range(n_nodes)] stake = {kp[0]: 1 for kp in kps} network = {} self.nodes = [Node(kp, network, n_nodes, stake) for kp in kps] for n in self.nodes: network[n.pk] = n.ask_sync self.ids = {kp[0]: i for i, kp in enumerate(kps)} self.main_its = [n.main() for n in self.nodes] for m in self.main_its: next(m) def toggle(): if play.label == '► Play': play.label = '❚❚ Pause' curdoc().add_periodic_callback(self.animate, 50) else: play.label = '► Play' curdoc().remove_periodic_callback(self.animate) play = Button(label='► Play', width=60) play.on_click(toggle) def sel_node(new): self.active = new node = self.nodes[new] self.tbd = {} self.tr_src.data, self.links_src.data = self.extract_data( node, bfs((node.head, ), lambda u: node.hg[u].p), 0) for u, j in tuple(self.tbd.items()): self.tr_src.data['line_alpha'][j] = 1 if node.famous.get( u) else 0 if u in node.idx: self.tr_src.data['round_color'][j] = idx_color(node.idx[u]) self.tr_src.data['idx'][j] = node.idx.get(u) if u in node.idx and u in node.famous: del self.tbd[u] print('updated') self.tr_src.trigger('data', None, self.tr_src.data) selector = RadioButtonGroup( labels=['Node %i' % i for i in range(n_nodes)], active=0, name='Node to inspect') selector.on_click(sel_node) plot = figure( plot_height=700, plot_width=900, y_range=(0, 30), tools=[ PanTool(), HoverTool(tooltips=[('round', '@round'), ( 'hash', '@hash'), ('timestamp', '@time'), ('payload', '@payload'), ('number', '@idx')]) ]) plot.xgrid.grid_line_color = None plot.xaxis.minor_tick_line_color = None plot.ygrid.grid_line_color = None plot.yaxis.minor_tick_line_color = None self.links_src = ColumnDataSource(data={ 'x0': [], 'y0': [], 'x1': [], 'y1': [], 'width': [] }) #self.links_rend = plot.add_layout( # Arrow(end=NormalHead(fill_color='black'), x_start='x0', y_start='y0', x_end='x1', # y_end='y1', source=self.links_src)) self.links_rend = plot.segment(color='#777777', x0='x0', y0='y0', x1='x1', y1='y1', source=self.links_src, line_width='width') self.tr_src = ColumnDataSource( data={ 'x': [], 'y': [], 'round_color': [], 'idx': [], 'line_alpha': [], 'round': [], 'hash': [], 'payload': [], 'time': [] }) self.tr_rend = plot.circle(x='x', y='y', size=20, color='round_color', line_alpha='line_alpha', source=self.tr_src, line_width=5) sel_node(0) curdoc().add_root( row([widgetbox(play, selector, width=300), plot], sizing_mode='fixed'))
def __init__(self, n_nodes): self.i = 0 kps = [crypto_sign_keypair() for _ in range(n_nodes)] stake = {kp[0]: 1 for kp in kps} network = {} self.nodes = [Node(kp, network, n_nodes, stake) for kp in kps] for n in self.nodes: network[n.pk] = n.ask_sync self.ids = {kp[0]: i for i, kp in enumerate(kps)} self.main_its = [n.main() for n in self.nodes] for m in self.main_its: next(m) def toggle(): if play.label == '► Play': play.label = '❚❚ Pause' curdoc().add_periodic_callback(self.animate, 50) else: play.label = '► Play' curdoc().remove_periodic_callback(self.animate) play = Button(label='► Play', width=60) play.on_click(toggle) def sel_node(new): self.active = new node = self.nodes[new] self.tbd = {} self.tr_src.data, self.links_src.data = self.extract_data( node, bfs((node.head,), lambda u: node.hg[u].p), 0) for u, j in tuple(self.tbd.items()): self.tr_src.data['line_alpha'][j] = 1 if node.famous.get(u) else 0 if u in node.idx: self.tr_src.data['round_color'][j] = idx_color(node.idx[u]) self.tr_src.data['idx'][j] = node.idx.get(u) if u in node.idx and u in node.famous: del self.tbd[u] print('updated') self.tr_src.trigger('data', None, self.tr_src.data) selector = RadioButtonGroup( labels=['Node %i' % i for i in range(n_nodes)], active=0, name='Node to inspect') selector.on_click(sel_node) plot = figure( plot_height=700, plot_width=900, y_range=(0, 30), tools=[PanTool(dimensions=['height']), HoverTool(tooltips=[ ('round', '@round'), ('hash', '@hash'), ('timestamp', '@time'), ('payload', '@payload'), ('number', '@idx')])]) plot.xgrid.grid_line_color = None plot.xaxis.minor_tick_line_color = None plot.ygrid.grid_line_color = None plot.yaxis.minor_tick_line_color = None self.links_src = ColumnDataSource(data={'x0': [], 'y0': [], 'x1': [], 'y1': [], 'width': []}) #self.links_rend = plot.add_layout( # Arrow(end=NormalHead(fill_color='black'), x_start='x0', y_start='y0', x_end='x1', # y_end='y1', source=self.links_src)) self.links_rend = plot.segment(color='#777777', x0='x0', y0='y0', x1='x1', y1='y1', source=self.links_src, line_width='width') self.tr_src = ColumnDataSource( data={'x': [], 'y': [], 'round_color': [], 'idx': [], 'line_alpha': [], 'round': [], 'hash': [], 'payload': [], 'time': []}) self.tr_rend = plot.circle(x='x', y='y', size=20, color='round_color', line_alpha='line_alpha', source=self.tr_src, line_width=5) sel_node(0) curdoc().add_root(row([widgetbox(play, selector, width=300), plot], sizing_mode='fixed'))
def gen_keypair() -> Tuple[bytes, bytes]: return crypto_sign_keypair()
new = () while True: payload = (yield new) # pick a random node to sync with but not me c = tuple(self.network.keys() - {self.pk})[randrange(self.n - 1)] new = self.sync(c, payload) self.divide_rounds(new) new_c = self.decide_fame() self.find_order(new_c) n_nodes = int(sys.argv[1]) kps = [crypto_sign_keypair() for _ in range(n_nodes)] network = {} stake = {kp[0]: 1 for kp in kps} nodes = [Node(kp, network, n_nodes, stake) for kp in kps] for n in nodes: network[n.pk] = n.ask_sync mains = [n.main() for n in nodes] for m in mains: next(m) def task(arg1, arg2): r = randrange(n_nodes) print('working node: %i, event number: %i' % (r, 0)) next(mains[r]) signal.signal(signal.SIGALRM, task)
def generate(cls) -> "KeyPair": """Generates a new random keypair""" public_key, secret_key = crypto_sign_keypair() return cls(PublicKey(public_key), SecretKey(secret_key))
def test_crypto_sign_open(self): pk, sk = pysodium.crypto_sign_keypair() signed = pysodium.crypto_sign(b'howdy', sk) changed = signed[:pysodium.crypto_sign_BYTES] + b'0' + signed[pysodium.crypto_sign_BYTES + 1:] pysodium.crypto_sign_open(signed, pk) self.assertRaises(ValueError, pysodium.crypto_sign_open, changed, pk)
def test_pysodium(): """ Test all the functions needed from pysodium libarary (libsodium) """ # crypto_sign signatures with Ed25519 keys # create keypair without seed verkey, sigkey = pysodium.crypto_sign_keypair() assert len(verkey) == 32 == pysodium.crypto_sign_PUBLICKEYBYTES assert len(sigkey) == 64 == pysodium.crypto_sign_SECRETKEYBYTES assert 32 == pysodium.crypto_sign_SEEDBYTES sigseed = pysodium.randombytes(pysodium.crypto_sign_SEEDBYTES) assert len(sigseed) == 32 # seed = (b'J\xeb\x06\xf2BA\xd6/T\xe1\xe2\xe2\x838\x8a\x99L\xd9\xb5(\\I\xccRb\xc8\xd5\xc7Y\x1b\xb6\xf0') # Ann's seed sigseed = ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_\xf2K\x93`' ) assert len(sigseed) == 32 # try key stretching from 16 bytes using pysodium.crypto_pwhash() assert 16 == pysodium.crypto_pwhash_SALTBYTES salt = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES) assert len(salt) == 16 # salt = b'\x19?\xfa\xc7\x8f\x8b\x7f\x8b\xdbS"$\xd7[\x85\x87' # algorithm default is argon2id sigseed = pysodium.crypto_pwhash( outlen=32, passwd="", salt=salt, opslimit=pysodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, memlimit=pysodium.crypto_pwhash_MEMLIMIT_INTERACTIVE, alg=pysodium.crypto_pwhash_ALG_DEFAULT) assert len(sigseed) == 32 # seed = (b'\xa9p\x89\x7f+\x0e\xc4\x9c\xf2\x01r\xafTI\xc0\xfa\xac\xd5\x99\xf8O\x8f=\x843\xa2\xb6e\x9fO\xff\xd0') # creates signing/verification key pair from seed verkey, sigkey = pysodium.crypto_sign_seed_keypair(sigseed) assert len(verkey) == 32 assert len(sigkey) == 64 # sigkey is seed and verkey concatenated. Libsodium does this as an optimization # because the signing scheme needs both the private key (seed) and the public key so # instead of recomputing the public key each time from the secret key it requires # the public key as an input of and instead of two separate inputs, one for the # secret key and one for the public key, it uses a concatenated form. # Essentially crypto_sign_seed_keypair and crypto_sign_keypair return redundant # information in the duple (verkey, sigkey) because sigkey includes verkey # so one could just store sigkey and extract verkey or sigseed when needed # or one could just store verkey and sigseed and reconstruct sigkey when needed. # crypto_sign_detached requires sigkey (sigseed + verkey) # crypto_sign_verify_detached reqires verkey only # https://crypto.stackexchange.com/questions/54353/why-are-nacl-secret-keys-64-bytes-for-signing-but-32-bytes-for-box assert sigseed == sigkey[:32] assert verkey == sigkey[32:] assert sigkey == sigseed + verkey # vk = (b'B\xdd\xbb}8V\xa0\xd6lk\xcf\x15\xad9\x1e\xa7\xa1\xfe\xe0p<\xb6\xbex\xb0s\x8d\xd6\xf5\xa5\xe8Q') # utility function to extract seed from secret sigkey (really just extracting from front half) assert sigseed == pysodium.crypto_sign_sk_to_seed(sigkey) assert 64 == pysodium.crypto_sign_BYTES msg = "The lazy dog jumped over the river" msgb = msg.encode( "utf-8") # must convert unicode string to bytes in order to sign it assert msgb == b'The lazy dog jumped over the river' sig = pysodium.crypto_sign_detached(msgb, sigseed + verkey) # sigkey = seed + verkey assert len(sig) == 64 """ sig = (b"\x99\xd2<9$$0\x9fk\xfb\x18\xa0\x8c@r\x122.k\xb2\xc7\x1fp\x0e'm\x8f@" b'\xaa\xa5\x8c\xc8n\x85\xc8!\xf6q\x91p\xa9\xec\xcf\x92\xaf)\xde\xca' b'\xfc\x7f~\xd7o|\x17\x82\x1d\xd4<o"\x81&\t') """ #siga = pysodium.crypto_sign(msg.encode("utf-8"), sk)[:pysodium.crypto_sign_BYTES] #assert len(siga) == 64 #assert sig == siga try: # verify returns None if valid else raises ValueError result = pysodium.crypto_sign_verify_detached(sig, msgb, verkey) except Exception as ex: assert False assert not result assert result is None sigbad = sig[:-1] sigbad += b'A' try: # verify returns None if valid else raises ValueError result = pysodium.crypto_sign_verify_detached(sigbad, msgb, verkey) except Exception as ex: assert True assert isinstance(ex, ValueError) # crypto_box authentication encryption with X25519 keys apubkey, aprikey = pysodium.crypto_box_keypair() assert len(apubkey) == 32 == pysodium.crypto_box_SECRETKEYBYTES assert len(aprikey) == 32 == pysodium.crypto_box_PUBLICKEYBYTES repubkey = pysodium.crypto_scalarmult_curve25519_base(aprikey) assert repubkey == apubkey assert 32 == pysodium.crypto_box_SEEDBYTES boxseed = pysodium.randombytes(pysodium.crypto_box_SEEDBYTES) assert len(boxseed) == 32 bpubkey, bprikey = pysodium.crypto_box_seed_keypair(boxseed) assert len(bpubkey) == 32 assert len(bprikey) == 32 repubkey = pysodium.crypto_scalarmult_curve25519_base(bprikey) assert repubkey == bpubkey assert 24 == pysodium.crypto_box_NONCEBYTES nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) assert len(nonce) == 24 # nonce = b'\x11\xfbi<\xf2\xb6k\xa05\x0c\xf9\x86t\x07\x8e\xab\x8a\x97nG\xe8\x87,\x94' atob_tx = "Hi Bob I'm Alice" atob_txb = atob_tx.encode("utf-8") # Detached recomputes shared key every time. # A encrypt to B acrypt, amac = pysodium.crypto_box_detached(atob_txb, nonce, bpubkey, aprikey) amacl = pysodium.crypto_box_MACBYTES assert amacl == 16 # amac = b'\xa1]\xc6ML\xe2\xa9:\xc0\xdc\xab\xa5\xc4\xc7\xf4\xdb' # acrypt = (b'D\n\x17\xb6z\xd8+t)\xcc`y\x1d\x10\x0cTC\x02\xb5@\xe2\xf2\xc9-(\xec*O\xb8~\xe2\x1a\xebO') # when transmitting prepend amac to crypt acipher = pysodium.crypto_box(atob_txb, nonce, bpubkey, aprikey) assert acipher == amac + acrypt atob_rxb = pysodium.crypto_box_open_detached(acrypt, amac, nonce, apubkey, bprikey) atob_rx = atob_rxb.decode("utf-8") assert atob_rx == atob_tx assert atob_rxb == atob_txb atob_rxb = pysodium.crypto_box_open(acipher, nonce, apubkey, bprikey) atob_rx = atob_rxb.decode("utf-8") assert atob_rx == atob_tx assert atob_rxb == atob_txb btoa_tx = "Hello Alice I am Bob" btoa_txb = btoa_tx.encode("utf-8") # B encrypt to A bcrypt, bmac = pysodium.crypto_box_detached(btoa_txb, nonce, apubkey, bprikey) # bmac = b'\x90\xe07=\xd22\x8fh2\xff\xdd\x84tC\x053' # bcrypt = (b'8\xb5\xba\xe7\xcc\xae B\xefx\xe6{U\xf7\xefA\x00\xc7|\xdbu\xcfc\x01$\xa9\xa2P\xa7\x84\xa5\xae\x180') # when transmitting prepend amac to crypt bcipher = pysodium.crypto_box(btoa_txb, nonce, apubkey, bprikey) assert bcipher == bmac + bcrypt btoa_rxb = pysodium.crypto_box_open_detached(bcrypt, bmac, nonce, bpubkey, aprikey) btoa_rx = btoa_rxb.decode("utf-8") assert btoa_rx == btoa_tx assert btoa_rxb == btoa_txb btoa_rxb = pysodium.crypto_box_open(bcipher, nonce, bpubkey, aprikey) btoa_rx = btoa_rxb.decode("utf-8") assert btoa_rx == btoa_tx assert btoa_rxb == btoa_txb # compute shared key asymkey = pysodium.crypto_box_beforenm(bpubkey, aprikey) bsymkey = pysodium.crypto_box_beforenm(apubkey, bprikey) assert asymkey == bsymkey acipher = pysodium.crypto_box_afternm(atob_txb, nonce, asymkey) atob_rxb = pysodium.crypto_box_open_afternm(acipher, nonce, bsymkey) assert atob_rxb == atob_txb bcipher = pysodium.crypto_box_afternm(btoa_txb, nonce, bsymkey) btoa_rxb = pysodium.crypto_box_open_afternm(bcipher, nonce, asymkey) assert btoa_rxb == btoa_txb # crypto_box_seal public key encryption with X25519 keys # uses same X25519 type of keys as crypto_box authenticated encryption # so when converting sign key Ed25519 to X25519 can use for both types of encryption pubkey, prikey = pysodium.crypto_box_keypair() assert len(pubkey) == 32 == pysodium.crypto_box_PUBLICKEYBYTES assert len(prikey) == 32 == pysodium.crypto_box_SECRETKEYBYTES assert 48 == pysodium.crypto_box_SEALBYTES msg_txb = "Catch me if you can.".encode("utf-8") assert msg_txb == b'Catch me if you can.' cipher = pysodium.crypto_box_seal(msg_txb, pubkey) assert len(cipher) == 48 + len(msg_txb) msg_rxb = pysodium.crypto_box_seal_open(cipher, pubkey, prikey) assert msg_rxb == msg_txb # convert Ed25519 key pair to X25519 key pair # https://blog.filippo.io/using-ed25519-keys-for-encryption/ # https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519 # crypto_sign_ed25519_pk_to_curve25519 # crypto_sign_ed25519_sk_to_curve25519 pubkey = pysodium.crypto_sign_pk_to_box_pk(verkey) assert len(pubkey) == pysodium.crypto_box_PUBLICKEYBYTES prikey = pysodium.crypto_sign_sk_to_box_sk(sigkey) assert len(prikey) == pysodium.crypto_box_SECRETKEYBYTES repubkey = pysodium.crypto_scalarmult_curve25519_base(prikey) assert repubkey == pubkey msg_txb = "Encoded using X25519 key converted from Ed25519 key".encode( "utf-8") cipher = pysodium.crypto_box_seal(msg_txb, pubkey) assert len(cipher) == 48 + len(msg_txb) msg_rxb = pysodium.crypto_box_seal_open(cipher, pubkey, prikey) assert msg_rxb == msg_txb """
print( 'No escrow key for initial shared secret. If you lose connectivity for an extended period of time, you may lose access to data unless you store the following value in a secure location:' ) print(nodeID + ':', hexlify(rb), " (key index", idx, ")") # Second, generate identify keypair and chain, and write cryptokey config file if path.exists(nodeID + ".crypto"): with open(nodeID + ".crypto", "rb+") as f: sk, rb = msgpack.unpackb(f.read(), raw=True) pk = pysodium.crypto_sign_sk_to_pk(sk) f.seek(0, 0) f.write(msgpack.packb([sk, rb], use_bin_type=True)) f.flush() f.truncate() else: pk, sk = pysodium.crypto_sign_keypair() with open(nodeID + ".crypto", "wb") as f: f.write( msgpack.packb( [sk, pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES)], use_bin_type=True)) poison = [['usages', _usages[key]]] if len(topics) > 0: poison.append(['topics', topics]) if pathlen != -1: poison.append(['pathlen', pathlen]) poison = msgpack.packb(poison, use_bin_type=True) msg = [time() + _lifetime, poison, pk] if choice < 5:
#!/usr/bin/env python # vim: set sw=4 sts=4 et tw=80 : # -*- coding: utf-8 -*- import binascii import sys import pysodium as s if __name__ == '__main__': if len(sys.argv) < 2: sys.exit(1) if sys.argv[1] == 'gen': (public, secret) = s.crypto_sign_keypair() print "Secret: %s" % binascii.hexlify(secret) print "Public: %s" % binascii.hexlify(public) sys.exit(0) if sys.argv[1] == 'sign': if len(sys.argv) < 4: sys.exit(1) secret = sys.argv[2] token = sys.argv[3] print "Signing using '%s': '%s'" % (secret, token) print "Token: %s" % binascii.hexlify(s.crypto_sign(token, binascii.unhexlify(secret))) sys.exit(0)