def test_get_chat_event(): try: with LogCapture() as log_cap: private_key = secrets.token_bytes(32) signing_key = SigningKey(private_key) public_key_feed_id = signing_key.verify_key.encode() content0 = Content('chat/whateveraction', { 'messagekey': 'hallo zusammen', 'chat_id': '1', 'timestampkey': 10 }) hash_of_content = hashlib.sha256( content0.get_as_cbor()).hexdigest() hash_of_prev = None meta = Meta(public_key_feed_id, 0, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content0).get_as_cbor() connector = EventHandler() connector.add_event(event) meta = Meta(public_key_feed_id, 1, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) content1 = Content('chat/whateveraction', { 'messagekey': 'wie gehts?', 'chat_id': '1', 'timestampkey': 20 }) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content1).get_as_cbor() connector.add_event(event) content2 = Content( 'chat/whateveraction', { 'messagekey': 'schönes Wetter heute', 'chat_id': '1', 'timestampkey': 30 }) meta = Meta(public_key_feed_id, 2, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content2).get_as_cbor() connector.add_event(event) print(log_cap) print('\n#######################################') # TODO: there seem to be some errors concerning the chat_id, I would watch out in what form it is (binary or string?) q = EventHandler().get_event_since('chat', 15, '1') print(q) print('\n#######################################') t = EventHandler().get_all_events(application='chat', chat_id='1') print(t) assert True finally: try: if os.path.exists('eventDatabase.sqlite'): os.remove('eventDatabase.sqlite') else: assert False except PermissionError: print('Database is still in use')
def create_block(signing_key, previous_block, body, difficulty=1, difficulty_mode=0): signing_key = SigningKey(signing_key) if type(signing_key) == type( 's') or type(signing_key) == type(b's') else signing_key nonce = nacl.utils.random(16) signature = signing_key.sign(previous_block['hash'] + nonce + body) # mild PoW while not BasicBlockChain.meets_difficulty( signature.signature, difficulty, difficulty_mode): nonce = nacl.utils.random(16) signature = signing_key.sign(previous_block['hash'] + nonce + body) hash = sha256(signature.signature, encoder=RawEncoder) # return the block return { 'block_height': previous_block['block_height'] + 1, 'hash': hash, 'signature': signature.signature, 'address': signing_key.verify_key._key, 'previous_block': previous_block['hash'], 'nonce': nonce, 'body': body }
def test_get_event(): try: with LogCapture() as log_cap: private_key = secrets.token_bytes(32) signing_key = SigningKey(private_key) public_key_feed_id = signing_key.verify_key.encode() content0 = Content('whateverapp/whateveraction', { 'firstkey': 'somevalue', 'someotherkey': 3 }) hash_of_content = hashlib.sha256( content0.get_as_cbor()).hexdigest() hash_of_prev = None meta = Meta(public_key_feed_id, 0, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content0).get_as_cbor() connector = DatabaseConnector() connector.add_event(event) meta = Meta(public_key_feed_id, 1, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) content1 = Content('whateverapp/whateveraction', { 'secondkey': 'somevalue', 'someotherkey': 4 }) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content1).get_as_cbor() connector.add_event(event) content2 = Content('whateverapp/whateveraction', { 'thirdkey': 'somevalue', 'someotherkey': 5 }) meta = Meta(public_key_feed_id, 2, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content2).get_as_cbor() connector.add_event(event) res0 = connector.get_event(public_key_feed_id, 0) res1 = connector.get_event(public_key_feed_id, 1) res2 = connector.get_event(public_key_feed_id, 2) result0 = Event.from_cbor(res0) result1 = Event.from_cbor(res1) result2 = Event.from_cbor(res2) assert result0.content.content == content0.content assert result1.content.content == content1.content assert result2.content.content == content2.content print(log_cap) finally: try: if os.path.exists('cborDatabase.sqlite'): os.remove('cborDatabase.sqlite') if os.path.exists('eventDatabase.sqlite'): os.remove('eventDatabase.sqlite') else: assert False except PermissionError: print('Database is still in use')
def test_get_event(): with session_scope(): with LogCapture() as log_cap: private_key = secrets.token_bytes(32) signing_key = SigningKey(private_key) public_key_feed_id = signing_key.verify_key.encode() content0 = Content('whateverapp/whateveraction', { 'firstkey': 'somevalue', 'someotherkey': 3 }) hash_of_content = hashlib.sha256( content0.get_as_cbor()).hexdigest() hash_of_prev = None meta = Meta(public_key_feed_id, 0, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content0).get_as_cbor() connector = DatabaseConnector() connector.add_event(event) meta = Meta(public_key_feed_id, 1, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) content1 = Content('whateverapp/whateveraction', { 'secondkey': 'somevalue', 'someotherkey': 4 }) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content1).get_as_cbor() connector.add_event(event) content2 = Content('whateverapp/whateveraction', { 'thirdkey': 'somevalue', 'someotherkey': 5 }) meta = Meta(public_key_feed_id, 2, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content2).get_as_cbor() connector.add_event(event) res0 = connector.get_event(public_key_feed_id, 0) res1 = connector.get_event(public_key_feed_id, 1) res2 = connector.get_event(public_key_feed_id, 2) result0 = Event.from_cbor(res0) result1 = Event.from_cbor(res1) result2 = Event.from_cbor(res2) assert result0.content.content == content0.content assert result1.content.content == content1.content assert result2.content.content == content2.content print(log_cap)
def test_get_chat_event(): try: with LogCapture() as log_cap: private_key = secrets.token_bytes(32) signing_key = SigningKey(private_key) public_key_feed_id = signing_key.verify_key.encode() content0 = Content('chat/whateveraction', {'messagekey': 'hallo zusammen', 'chat_id': '1', 'timestampkey': 10}) hash_of_content = hashlib.sha256(content0.get_as_cbor()).hexdigest() hash_of_prev = None meta = Meta(public_key_feed_id, 0, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content0).get_as_cbor() connector = ChatFunction() connector.insert_chat_msg(event) meta = Meta(public_key_feed_id, 1, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) content1 = Content('chat/whateveraction', {'messagekey': 'wie gehts?', 'chat_id': '1', 'timestampkey': 20}) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content1).get_as_cbor() connector.insert_chat_msg(event) content2 = Content('chat/whateveraction', {'messagekey': 'schönes Wetter heute', 'chat_id': '1', 'timestampkey': 30}) meta = Meta(public_key_feed_id, 2, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content2).get_as_cbor() connector.insert_chat_msg(event) print(log_cap) q = connector.get_chat_since(15, '1') assert q[0][0] == 'wie gehts?' assert q[1][0] == 'schönes Wetter heute' t = connector.get_full_chat('1') assert t[0][0] == 'hallo zusammen' assert t[1][0] == 'wie gehts?' assert t[2][0] == 'schönes Wetter heute' assert True finally: try: if os.path.exists('cborDatabase.sqlite'): os.remove('cborDatabase.sqlite') if os.path.exists('eventDatabase.sqlite'): os.remove('eventDatabase.sqlite') else: assert False except PermissionError: print('Database is still in use')
def verify_pair(filename): """ Function to verify a public/private key pair previously generated by this tool. Parameters ---------- filename: str Name of the files to write the public and private key to. """ with open(filename, 'r') as f: hex_read = f.read().encode() sk_read = SigningKey(hex_read, encoder=HexEncoder) pub_filename = filename + '.pub' with open(pub_filename, 'r') as f: hex_read = f.read().encode() vk_read = VerifyKey(hex_read, encoder=HexEncoder) phrase_to_sign = b'phrase to sign' try: signed_phrase = sk_read.sign(phrase_to_sign) vk_read.verify(signed_phrase) except BadSignatureError as be: print(f"Private key in {filename} does not match public key in {pub_filename}.") return False print(f"Private key in {filename} matches public key in {pub_filename}.") return True
class Account: def __init__(self, private_key, sequence_number=0): self._signing_key = SigningKey(private_key) self._verify_key = self._signing_key.verify_key shazer = new_sha3_256() shazer.update(self._verify_key.encode()) self.address = shazer.digest() self.sequence_number = sequence_number self.status = AccountStatus.Local def sign(self, message): return self._signing_key.sign(message) @property def address_hex(self): return self.address.hex() @property def public_key(self): return self._verify_key.encode() @property def private_key(self): return self._signing_key.encode() @property def public_key_hex(self): return self.public_key.hex() @property def private_key_hex(self): return self.private_key.hex()
def test_worker_key_pair_tool(): key_file = "gen_pair_test" private_key, public_key = gen_pair(key_file) test_phrase = b"Test phrase" try: public_key.verify(private_key.sign(test_phrase)) except BadSignatureError as bse: assert False # load the generated keys from the file with open(key_file, 'r') as f: loaded_private_key = SigningKey(f.read().encode(), encoder=HexEncoder) with open(key_file + '.pub', 'r') as f: loaded_public_key = VerifyKey(f.read().encode(), encoder=HexEncoder) # test the try: loaded_public_key.verify(loaded_private_key.sign(test_phrase)) except BadSignatureError as bse: assert False assert verify_pair(key_file) # test that a bad signature is detected with open(key_file, 'w') as f: f.write( SigningKey.generate().encode(encoder=HexEncoder).decode('utf-8')) assert not verify_pair(key_file) # clean up os.remove(key_file) os.remove(key_file + '.pub')
def prepare_hsc_transfer_transaction(): from stablecoin.TransferTransactionData_pb2 import TransferTransactionData from stablecoin.TransactionBody_pb2 import TransactionBody from stablecoin.Transaction_pb2 import Transaction key_from = SigningKey( bytes.fromhex( "1aaced2d7b85ca122adfb5e6d15926eddbdfa8f270e40109fa01e3607446c48b") ) address_from = bytes(key_from.verify_key) address_to = bytes.fromhex( "c9fef56cee613e390d728399bef53619603b9f0559daab6ba68bf1c24715fb23") value = int_to_bytes(100) # $1.00 transfer = TransferTransactionData(to=address_to, value=value) valid_start = generate_valid_start_nanos() body = TransactionBody(caller=address_from, operatorAccountNum=9523, validStartNanos=valid_start, transfer=transfer) body_bytes = body.SerializeToString() body_signature = key_from.sign(body_bytes).signature tx = Transaction(body=body_bytes, signature=body_signature) tx_bytes = tx.SerializeToString() return tx_bytes, 9523, valid_start
def create_transaction( private_key: str, public_key: str, receiver: str, amount: int ) -> dict: """ Creates a transaction from a sender's public key to a receiver's public key :param private_key: The Sender's private key :param public_key: The Sender's public key :param receiver: The Receiver's public key :param amount: The amount in cents :return: <dict> The transaction dict """ tx = { "sender": public_key, "receiver": receiver, "amount": amount, "timestamp": int(time()), } tx_bytes = json.dumps(tx, sort_keys=True).encode("ascii") # Generate a signing key from the private key signing_key = SigningKey(private_key, encoder=HexEncoder) # Now add the signature to the original transaction signature = signing_key.sign(tx_bytes).signature tx["signature"] = HexEncoder.encode(signature).decode("ascii") return tx
def test_get_current_event(): try: with LogCapture(): private_key = secrets.token_bytes(32) signing_key = SigningKey(private_key) public_key_feed_id = signing_key.verify_key.encode() content = Content('whateverapp/whateveraction', { 'oneKey': 'somevalue', 'someotherkey': 1 }) hash_of_content = hashlib.sha256(content.get_as_cbor()).hexdigest() hash_of_prev = None meta = Meta(public_key_feed_id, 0, hash_of_prev, 'ed25519', ('sha256', hash_of_content)) signature = signing_key.sign(meta.get_as_cbor())._signature event = Event(meta, signature, content).get_as_cbor() connector = DatabaseConnector() connector.add_event(event) result = connector.get_current_event(public_key_feed_id) result = Event.from_cbor(result) assert result.meta.hash_of_content[1] == meta.hash_of_content[1] finally: try: if os.path.exists('cborDatabase.sqlite'): os.remove('cborDatabase.sqlite') if os.path.exists('eventDatabase.sqlite'): os.remove('eventDatabase.sqlite') else: assert False except PermissionError: print('Database is still in use')
def serialise(self, signing_key: SigningKey): # Create buffer buffer = BytesIO() # Write magic number buffer.write(Frame.MAGIC_NUMBER) # Write the destination key buffer.write(self.destination.serialise().read()) # Write the origin key buffer.write(self.origin.serialise().read()) # Write the via field buffer.write(self.via.serialise().read()) # Create a box to send the signed data in box = SealedBox(self.destination.public_key) # Sign the payload signed = signing_key.sign(self.payload.read()) # Encrypt and write the data to the buffer buffer.write(box.encrypt(signed)) # Rewind the buffer buffer.seek(0, 0) # Return the buffer return buffer
def decrypt_message(encrypted_message, keying_material, private_key): encrypted_key = keying_material['encrypted_key'] message_signature = keying_material['message_signature'] temp_public_key = PublicKey( keying_material['temp_public_key'], Base64Encoder) box = PublicBox(private_key, temp_public_key) message_key = box.decrypt( encrypted_key, encoder=Base64Encoder) # We got the key, so let's get the message. message_box = nacl.secret.SecretBox(message_key) message = message_box.decrypt( encrypted_message, encoder=Base64Encoder) # Check the signature. mac_key = sha256(box._shared_key, RawEncoder) signing_key = SigningKey(mac_key) if signing_key.sign(message, Base64Encoder) != message_signature: raise SignatureError("The signature is not valid") return message
def test_message_signing(self, seed, message, signature, expected): signing_key = SigningKey(seed, encoder=HexEncoder) signed = signing_key.sign(binascii.unhexlify(message), encoder=HexEncoder) assert signed == expected assert signed.message == message assert signed.signature == signature
def sign(self, signing_key: SigningKey) -> SignedMessageT: """ It's important for all messages to be able to prove who they were sent from. This method endows every message with the ability for someone to "sign" (with a hash of the message) as the sender of the message so that someone else, at a later date, can verify the sender. Args: signing_key: The key to use to sign the SyftMessage. Returns: A :class:`SignedMessage` """ debug( f"> Signing with {self.address.key_emoji(key=signing_key.verify_key)}" ) signed_message = signing_key.sign(serialize(self, to_bytes=True)) # signed_type will be the final subclass callee's closest parent signed_type # for example ReprMessage -> ImmediateSyftMessageWithoutReply.signed_type # == SignedImmediateSyftMessageWithoutReply return self.signed_type( msg_id=self.id, address=self.address, obj_type=get_fully_qualified_name(obj=self), signature=signed_message.signature, verify_key=signing_key.verify_key, message=signed_message.message, )
class Account: def __init__(self, private_key, address=None, sequence_number=0): self._signing_key = SigningKey(private_key) self._verify_key = self._signing_key.verify_key shazer = new_sha3_256() shazer.update(self._verify_key.encode()) if address is None: self.address = shazer.digest() else: self.address = Address.normalize_to_bytes(address) self.sequence_number = sequence_number self.status = AccountStatus.Local def json_print_fields(self): return ["address", "private_key", "public_key"] @classmethod def faucet_account(cls, private_key): return cls(private_key, AccountConfig.association_address()) @classmethod def gen_faucet_account(cls, faucet_account_file): if faucet_account_file is None: faucet_account_file = cls.faucet_file_path() with open(faucet_account_file, 'rb') as f: data = f.read() assert len(data) == 80 assert b' \x00\x00\x00\x00\x00\x00\x00' == data[0:8] assert b' \x00\x00\x00\x00\x00\x00\x00' == data[40:48] private_key = data[8:40] public_key = data[48:] return cls.faucet_account(private_key) @classmethod def faucet_file_path(cls): curdir = os.path.dirname(libra.__file__) return os.path.abspath((os.path.join(curdir, "faucet_key_for_test"))) def sign(self, message): return self._signing_key.sign(message) @property def address_hex(self): return self.address.hex() @property def public_key(self): return self._verify_key.encode() @property def private_key(self): return self._signing_key.encode() @property def public_key_hex(self): return self.public_key.hex() @property def private_key_hex(self): return self.private_key.hex()
def sign_message(signing_key, message): if isinstance(signing_key, str): signing_key = binascii.unhexlify(signing_key) if isinstance(signing_key, bytes): signing_key = SigningKey(signing_key) if isinstance(message, str): message = message.encode() return signing_key.sign(message, encoder=HexEncoder)
def test_message_signing(self, seed, message, signature, expected): signing_key = SigningKey( seed, encoder=HexEncoder, ) signed = signing_key.sign( binascii.unhexlify(message), encoder=HexEncoder, ) assert signed == expected assert signed.message == message assert signed.signature == signature
def get_credentials(): if not current_user.is_authenticated: abort(403) user = "******".format(current_user) jid = user + "@chatproto.muikkuverkko.fi" timestamp = int(round(time() * 1000)) payload = "{},{}".format(timestamp, user) signing_key = SigningKey(signing_key_hex, HexEncoder) signed = signing_key.sign(payload) password = signed.message + "," + HexEncoder.encode(signed.signature) sys.stderr.write("Outgoing password: {} \n".format(password)) return jsonify({"jid": jid, "password": password})
def test_verify_signature(self): private = os.urandom(32) sk = SigningKey(private) previous = os.urandom(64) counter = os.urandom(16) timestamp = os.urandom(16) public = bytes(sk.verify_key) msg = os.urandom(64) # Valid sig, correct pub key in signing header: signing_form = b''.join([previous, counter, timestamp, public, msg]) sm = sk.sign(signing_form) c = verify.verify_signature(bytes(sm), public) self.assertEqual(type(c), verify.Child) self.assertEqual(c.signature, sm.signature) self.assertEqual(c.previous, previous) self.assertEqual(c.counter.to_bytes(16, 'little'), counter) self.assertEqual(c.timestamp.to_bytes(16, 'little'), timestamp) self.assertEqual(c.public, public) self.assertEqual(c.message, msg) # Signed message has been modified with different public key: bad_public = os.urandom(32) signed = b''.join( [sm.signature, previous, counter, timestamp, bad_public, msg]) with self.assertRaises(nacl.exceptions.BadSignatureError): verify.verify_signature(signed, public) # Signature is valid, but wrong public key was used in signing header: signing_form = b''.join( [previous, counter, timestamp, bad_public, msg]) signed = bytes(sk.sign(signing_form)) with self.assertRaises(ValueError) as cm: verify.verify_signature(signed, public) self.assertEqual( str(cm.exception), 'embebbed pubkey mismatch: {!r} != {!r}'.format( bad_public, public))
def raw_sign(self, private_key): """ Sign the transaction. Args: private_key (str): the private key of the signing account Returns: bytes: signature """ private_key = base64.b64decode(private_key) txn = encoding.msgpack_encode(self) to_sign = constants.txid_prefix + base64.b64decode(txn) signing_key = SigningKey(private_key[:constants.key_len_bytes]) signed = signing_key.sign(to_sign) sig = signed.signature return sig
def sign(self, message, private_key): """ Sign the message. This method will take the currently configured values for the message prefix and suffix and create a signature using the provided Ed25519 private key. Args: message (bytes): message to be signed private_key (bytes) Ed25519 private key """ sk = SigningKey(private_key) self.public_key = sk.verify_key.encode() self.signature = sk.sign(message).signature return self.signature
def sign_bytes(to_sign, private_key): """ Sign arbitrary bytes after prepending with "MX" for domain separation. Args: to_sign (bytes): bytes to sign Returns: str: base64 signature """ to_sign = constants.bytes_prefix + to_sign private_key = base64.b64decode(private_key) signing_key = SigningKey(private_key[:constants.key_len_bytes]) signed = signing_key.sign(to_sign) signature = base64.b64encode(signed.signature).decode() return signature
def sign(self, path: str, json_payload: str = '') -> {str, str}: if self.__public_key is None or self.__secret_key is None: raise CodexAPIRequestSignerException( 'Use of private API methods require public_key and secret_key to be set.' ) signing_key = SigningKey(seed=self.__secret_key[:64], encoder=HexEncoder) tonce_timestamp = str(time_ns()) message = f'{json_payload}{path}{tonce_timestamp}' signature = signing_key.sign(message=message.encode(), encoder=HexEncoder) return {'signature': signature, 'timestamp': tonce_timestamp}
class Ed25519PrivateKey(ed25519.Ed25519PrivateKey): def __init__(self, data: bytes): self._key = SigningKey(data) def __bytes__(self) -> bytes: return bytes(self._key) def __hash__(self) -> int: return hash(bytes(self)) def __eq__(self, other: object) -> bool: if not isinstance(other, self.__class__): return False return self._key == other._key def __ne__(self, other: object) -> bool: return not (self == other) @classmethod def generate(cls) -> ed25519.Ed25519PrivateKey: return cls(bytes(SigningKey.generate())) @classmethod def from_private_bytes(cls, data: bytes) -> ed25519.Ed25519PrivateKey: return cls(data) def public_key(self) -> ed25519.Ed25519PublicKey: return Ed25519PublicKey(bytes(self._key.verify_key)) def private_bytes( self, encoding: serialization.Encoding, format: serialization.PrivateFormat, encryption_algorithm: serialization.KeySerializationEncryption, ) -> bytes: if (encoding is not serialization.Encoding.Raw or format is not serialization.PrivateFormat.Raw or not isinstance(encryption_algorithm, serialization.NoEncryption)): raise ValueError("Encoding and format must be Raw and " "encryption_algorithm must be NoEncryption") return bytes(self) def sign(self, data: bytes) -> bytes: return self._key.sign(data).signature
class Account(object): def __init__(self, private_key): self._signing_key = SigningKey(bytes.fromhex(private_key)) self._verify_key = self._signing_key.verify_key shazer = sha3_256() shazer.update(self._verify_key.encode()) self.address = shazer.digest().hex() def sign(self, message): return self._signing_key.sign(message) @property def public_key(self): return self._verify_key.encode().hex() @property def private_key(self): return self._signing_key.encode().hex()
class Account: def __init__(self, private_key): self._signing_key = SigningKey(bytes.fromhex(private_key)) self._verify_key = self._signing_key.verify_key m = create_hasher() m.update(self._verify_key.encode()) self.address = m.digest().hex() def sign(self, message): return self._signing_key.sign(message) @property def public_key(self): return self._verify_key.encode().hex() @property def private_key(self): return self._signing_key.encode().hex()
def sign(self, private_key): """ Sign a bid. Args: private_key (str): private_key of the bidder Returns: SignedBid: signed bid with the signature """ temp = encoding.msgpack_encode(self) to_sign = constants.bid_prefix + base64.b64decode(bytes(temp, "utf-8")) private_key = base64.b64decode(bytes(private_key, "utf-8")) signing_key = SigningKey(private_key[:constants.signing_key_len_bytes]) signed = signing_key.sign(to_sign) sig = signed.signature signed = SignedBid(self, base64.b64encode(sig).decode()) return signed
def teal_sign(private_key, data, contract_addr): """ Return the signature suitable for ed25519verify TEAL opcode Args: private_key (str): private key to sign with data (bytes): data to sign contract_addr (str): program hash (contract address) to sign for Return: bytes: signature """ private_key = base64.b64decode(private_key) signing_key = SigningKey(private_key[:constants.key_len_bytes]) to_sign = constants.logic_data_prefix + encoding.decode_address(contract_addr) + data signed = signing_key.sign(to_sign) return signed.signature
class Signer(object): """ Only supported signing algorithm is ed25519 When using ed25519 algorithm, the secret is the base64-encoded private key """ def __init__(self, secret): if isinstance(secret, str): secret = secret.encode() self._key = SigningKey(secret, encoder=Base64Encoder) @property def algorithm(self): return "ed25519" def sign(self, data): if isinstance(data, str): data = data.encode(encode) signed = self._key.sign(data).signature return base64.b64encode(signed).decode()
def _add_sig(self, split_version): # Adding new signature to version file # Raw private key will need to be converted into # a signing key object private_key_raw = self._load_private_keys() if private_key_raw is None: log.error("Private Key not found. Please " "import a keypack & try again") return # Load update manifest update_data = self._load_update_data() # We don't want to verify the signature if "signature" in update_data: log.debug("Removing signatures from version file") del update_data["signature"] # We create a signature from the string update_data_str = json.dumps(update_data, sort_keys=True) # Creating signing key object private_key = SigningKey(private_key_raw, self.key_encoder) log.debug("Signing update data") # Signs update data with private key signature = private_key.sign(bytes(update_data_str, "latin-1")) signature = self.key_encoder.encode(signature[:64]).decode() log.debug("Sig: %s", signature) # Create new dict from json string update_data = json.loads(update_data_str) # Add signatures to update data update_data["signature"] = signature log.debug("Adding signature to update data") # Write updated version file to .pyupdater/config.pyu self._write_update_data(update_data, split_version) # Write gzipped key file self._write_key_file()
def encrypt_message(message, identifier): """Encrypts a message so that it can be read by all the devices of the given identifier. :param message: the message itself, in clear text. :param identifier: the identifier of the message recipient. """ # Cipher the message with a brand new random key. message_key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE) message_box = nacl.secret.SecretBox(message_key) message_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted_message = message_box.encrypt(message, message_nonce, Base64Encoder) returned = [] # Encrypt the message key with each recipient's public key. for recipient_device_pub_key in get_public_keys(identifier): # Generate a new keypair & cipher the key with it. temp_private_key, temp_public_key = generate_keypair() box = PublicBox(temp_private_key, recipient_device_pub_key) nonce = nacl.utils.random(PublicBox.NONCE_SIZE) encrypted_key = box.encrypt(message_key, nonce, Base64Encoder) # Sign the message. mac_key = sha256(box._shared_key, RawEncoder) signing_key = SigningKey(mac_key) message_sig = signing_key.sign(message, Base64Encoder) # Return the public key used to cipher the message key. returned.append({ 'encrypted_key': encrypted_key, 'temp_public_key': temp_public_key.encode(Base64Encoder), 'message_signature': message_sig }) return { 'encrypted_message': encrypted_message, 'recipients': returned }
def init(server, username, keydir, action, message, recipients): """ SHSM CLI client. """ global serverurl serverurl = server if action == "register": master_signing_key = SigningKey.generate() device_signing_key = SigningKey.generate() device_private_key = PrivateKey.generate() enc_master_verify_key = master_signing_key.verify_key.encode(encoder=HexEncoder) register(username, enc_master_verify_key) # TODO: make sure keydir exists save_key(master_signing_key.encode(encoder=HexEncoder), keydir + "/master_signing_key") save_key(device_signing_key.encode(encoder=HexEncoder), keydir + "/device_signing_key") save_key(device_private_key.encode(encoder=HexEncoder), keydir + "/device_private_key") else: try: master_signing_key = SigningKey(load_key(keydir + "/master_signing_key"), encoder=HexEncoder) device_signing_key = SigningKey(load_key(keydir + "/device_signing_key"), encoder=HexEncoder) device_private_key = PrivateKey(load_key(keydir + "/device_private_key"), encoder=HexEncoder) except TypeError: print "bad key, exiting." exit() if action == "add-device": enc_device_verify_key = device_signing_key.verify_key.encode(encoder=HexEncoder) enc_signed_device_verify_key = b64encode(master_signing_key.sign(enc_device_verify_key)) enc_device_public_key = device_private_key.public_key.encode(encoder=HexEncoder) enc_signed_device_public_key = b64encode(master_signing_key.sign(enc_device_public_key)) add_device(username, enc_signed_device_verify_key, enc_signed_device_public_key) if action == "send-message": ephemeral_key = PrivateKey.generate() enc_ephemeral_public_key = b64encode( device_signing_key.sign(ephemeral_key.public_key.encode(encoder=HexEncoder)) ) # TODO:: should sign binary text, no? b"bob" destination_usernames = recipients.split(",") enc_dest_usernames = b64encode( device_signing_key.sign(json.dumps({"destination_usernames": destination_usernames})) ) symmetric_key = random(SecretBox.KEY_SIZE) symmetric_box = SecretBox(symmetric_key) nonce = random(SecretBox.NONCE_SIZE) msg_manifest = {} msg_manifest["recipients"] = {} msg_manifest["msg"] = b64encode(symmetric_box.encrypt(str(message), nonce)) for dest_user in destination_usernames: msg_manifest["recipients"][dest_user] = {} for recipient_key in get_recipient_keys( device_signing_key.verify_key.encode(encoder=HexEncoder), b64encode(device_signing_key.sign(str(dest_user))), ): # TODO:: should sign binary text, no? crypt_box = Box(ephemeral_key, recipient_key) nonce = random(Box.NONCE_SIZE) crypt_key = b64encode(crypt_box.encrypt(symmetric_key, nonce)) dest_key = recipient_key.encode(encoder=HexEncoder) msg_manifest["recipients"][dest_user][dest_key] = crypt_key enc_signed_crypt_msg = b64encode(device_signing_key.sign(json.dumps(msg_manifest))) send_message( device_signing_key.verify_key.encode(encoder=HexEncoder), enc_dest_usernames, enc_signed_crypt_msg, enc_ephemeral_public_key, ) if action == "get-messages": enc_device_verify_key = device_signing_key.verify_key.encode(encoder=HexEncoder) enc_signed_device_verify_key = b64encode(device_signing_key.sign(enc_device_verify_key)) messages = get_messages(enc_device_verify_key, enc_signed_device_verify_key) for message_public_key in messages["messages"].keys(): try: crypto_box = Box(device_private_key, PublicKey(b64decode(message_public_key), encoder=HexEncoder)) except TypeError: print "not a valid public key" exit() packed_msg = json.loads(messages["messages"][message_public_key]) msg_manifest = json.loads(b64decode(packed_msg["message_manifest"])) dest_pub_key = device_private_key.public_key.encode(encoder=HexEncoder) symmetric_key = crypto_box.decrypt(b64decode(msg_manifest["recipients"][username][dest_pub_key])) symmetric_box = SecretBox(symmetric_key) print ("From: %s\nMessage: %s") % ( packed_msg["reply_to"], symmetric_box.decrypt(b64decode(msg_manifest["msg"])), )
class Invitation: # This has a brief lifetime: one is created in response to the rendezvous # client discovering new messages for us, used for one reactor tick, then # dereferenced. It holds onto a few values during that tick (which may # process multiple messages for a single invitation, e.g. A's second poll # will receive both B-m1 and B-m2 together). But all persistent state # beyond that one tick is stored in the database. def __init__(self, iid, db, manager): self.iid = iid self.db = db self.manager = manager c = self.db.execute("SELECT petname, inviteID, inviteKey," # 0,1,2 " theirTempPubkey," # 3 " nextExpectedMessage," # 4 " myMessages," # 5 " theirMessages" # 6 " FROM invitations WHERE id = ?", (iid,)) res = c.fetchone() if not res: raise KeyError("no pending Invitation for '%d'" % iid) self.petname = res[0] self.inviteID = res[1] self.inviteKey = SigningKey(res[2].decode("hex")) self.theirTempPubkey = None if res[3]: self.theirTempPubkey = PublicKey(res[3].decode("hex")) self.nextExpectedMessage = int(res[4]) self.myMessages = splitMessages(res[5]) self.theirMessages = splitMessages(res[6]) def getAddressbookID(self): c = self.db.execute("SELECT addressbook_id FROM invitations" " WHERE id = ?", (self.iid,)) return c.fetchone()[0] def getMyTempPrivkey(self): c = self.db.execute("SELECT myTempPrivkey FROM invitations" " WHERE id = ?", (self.iid,)) return PrivateKey(c.fetchone()[0].decode("hex")) def getMySigningKey(self): c = self.db.execute("SELECT mySigningKey FROM invitations" " WHERE id = ?", (self.iid,)) return SigningKey(c.fetchone()[0].decode("hex")) def getMyPublicChannelRecord(self): c = self.db.execute("SELECT my_channel_record FROM invitations" " WHERE id = ?", (self.iid,)) return c.fetchone()[0] def getMyPrivateChannelData(self): c = self.db.execute("SELECT my_private_channel_data FROM invitations" " WHERE id = ?", (self.iid,)) return json.loads(c.fetchone()[0]) def sendFirstMessage(self): pub = self.getMyTempPrivkey().public_key.encode() self.send("i0:m1:"+pub) self.db.update("UPDATE invitations SET myMessages=? WHERE id=?", (",".join(self.myMessages), self.iid), "invitations", self.iid) # that will be commited by our caller def processMessages(self, messages): # These messages are neither version-checked nor signature-checked. # Also, we may have already processed some of them. #print "processMessages", messages #print " my", self.myMessages #print " theirs", self.theirMessages assert isinstance(messages, set), type(messages) assert None not in messages, messages assert None not in self.myMessages, self.myMessages assert None not in self.theirMessages, self.theirMessages # Send anything that didn't make it to the server. This covers the # case where we commit our outbound message in send() but crash # before finishing delivery. for m in self.myMessages - messages: #print "resending", m self.manager.sendToAll(self.inviteID, m) newMessages = messages - self.myMessages - self.theirMessages #print " %d new messages" % len(newMessages) if not newMessages: print " huh, no new messages, stupid rendezvous client" # check signatures, extract bodies. invalid messages kill the channel # and the invitation. MAYBE TODO: lose the one channel, keep using # the others. bodies = set() for m in newMessages: #print " new inbound message", m try: if not m.startswith("r0:"): print "unrecognized rendezvous message prefix" if not VALID_MESSAGE.search(m): raise CorruptChannelError() m = m[len("r0:"):].decode("hex") bodies.add(self.inviteKey.verify_key.verify(m)) except (BadSignatureError, CorruptChannelError) as e: print "channel %s is corrupt" % self.inviteID if isinstance(e, BadSignatureError): print " (bad sig)" self.unsubscribe(self.inviteID) # TODO: mark invitation as failed, destroy it return #print " new inbound bodies:", ", ".join([repr(b[:10])+" ..." for b in bodies]) # these handlers will update self.myMessages with sent messages, and # will increment self.nextExpectedMessage. We can handle multiple # (sequential) messages in a single pass. if self.nextExpectedMessage == 1: self.findPrefixAndCall("i0:m1:", bodies, self.processM1) # no elif here: self.nextExpectedMessage may have incremented if self.nextExpectedMessage == 2: self.findPrefixAndCall("i0:m2:", bodies, self.processM2) if self.nextExpectedMessage == 3: self.findPrefixAndCall("i0:m3:", bodies, self.processM3) self.db.update("UPDATE invitations SET" " myMessages=?," " theirMessages=?," " nextExpectedMessage=?" " WHERE id=?", (",".join(self.myMessages), ",".join(self.theirMessages | newMessages), self.nextExpectedMessage, self.iid), "invitations", self.iid) #print " db.commit" self.db.commit() def findPrefixAndCall(self, prefix, bodies, handler): for msg in bodies: if msg.startswith(prefix): return handler(msg[len(prefix):]) return None def send(self, msg, persist=True): #print "send", repr(msg[:10]), "..." signed = "r0:%s" % self.inviteKey.sign(msg).encode("hex") if persist: # m4-destroy is not persistent self.myMessages.add(signed) # will be persisted by caller # This will be added to the DB, and committed, by our caller, to # get it into the same transaction as the update to which inbound # messages we've processed. assert VALID_MESSAGE.search(signed), signed self.manager.sendToAll(self.inviteID, signed) def processM1(self, msg): #print "processM1", self.petname self.theirTempPubkey = PublicKey(msg) self.db.update("UPDATE invitations SET theirTempPubkey=?" " WHERE id=?", (self.theirTempPubkey.encode(Hex), self.iid), "invitations", self.iid) # theirTempPubkey will committed by our caller, in the same txn as # the message send my_privkey = self.getMyTempPrivkey() my_channel_record = self.getMyPublicChannelRecord() b = Box(my_privkey, self.theirTempPubkey) signedBody = b"".join([self.theirTempPubkey.encode(), my_privkey.public_key.encode(), my_channel_record.encode("utf-8")]) my_sign = self.getMySigningKey() body = b"".join([b"i0:m2a:", my_sign.verify_key.encode(), my_sign.sign(signedBody) ]) nonce = os.urandom(Box.NONCE_SIZE) nonce_and_ciphertext = b.encrypt(body, nonce) #print "ENCRYPTED n+c", len(nonce_and_ciphertext), nonce_and_ciphertext.encode("hex") #print " nonce", nonce.encode("hex") msg2 = "i0:m2:"+nonce_and_ciphertext self.send(msg2) self.nextExpectedMessage = 2 def processM2(self, msg): #print "processM2", repr(msg[:10]), "...", self.petname assert self.theirTempPubkey nonce_and_ciphertext = msg my_privkey = self.getMyTempPrivkey() b = Box(my_privkey, self.theirTempPubkey) #nonce = msg[:Box.NONCE_SIZE] #ciphertext = msg[Box.NONCE_SIZE:] #print "DECRYPTING n+ct", len(msg), msg.encode("hex") body = b.decrypt(nonce_and_ciphertext) if not body.startswith("i0:m2a:"): raise ValueError("expected i0:m2a:, got '%r'" % body[:20]) verfkey_and_signedBody = body[len("i0:m2a:"):] theirVerfkey = VerifyKey(verfkey_and_signedBody[:32]) signedBody = verfkey_and_signedBody[32:] body = theirVerfkey.verify(signedBody) check_myTempPubkey = body[:32] check_theirTempPubkey = body[32:64] their_channel_record_json = body[64:].decode("utf-8") #print " binding checks:" #print " check_myTempPubkey", check_myTempPubkey.encode("hex") #print " my real tempPubkey", my_privkey.public_key.encode(Hex) #print " check_theirTempPubkey", check_theirTempPubkey.encode("hex") #print " first theirTempPubkey", self.theirTempPubkey.encode(Hex) if check_myTempPubkey != my_privkey.public_key.encode(): raise ValueError("binding failure myTempPubkey") if check_theirTempPubkey != self.theirTempPubkey.encode(): raise ValueError("binding failure theirTempPubkey") them = json.loads(their_channel_record_json) me = self.getMyPrivateChannelData() addressbook_id = self.db.insert( "INSERT INTO addressbook" " (petname, acked," " next_outbound_seqnum, my_signkey," " their_channel_record_json," " my_CID_key, next_CID_token," " highest_inbound_seqnum," " my_old_channel_privkey, my_new_channel_privkey," " they_used_new_channel_key, their_verfkey)" " VALUES (?,?, " " ?,?," " ?," " ?,?," # my_CID_key, next_CID_token " ?," # highest_inbound_seqnum " ?,?," " ?,?)", (self.petname, 0, 1, me["my_signkey"], json.dumps(them), me["my_CID_key"], None, 0, me["my_old_channel_privkey"], me["my_new_channel_privkey"], 0, theirVerfkey.encode(Hex) ), "addressbook") self.db.update("UPDATE invitations SET addressbook_id=?" " WHERE id=?", (addressbook_id, self.iid), "invitations", self.iid) msg3 = "i0:m3:ACK-"+os.urandom(16) self.send(msg3) self.nextExpectedMessage = 3 def processM3(self, msg): #print "processM3", repr(msg[:10]), "..." if not msg.startswith("ACK-"): raise ValueError("bad ACK") cid = self.getAddressbookID() self.db.update("UPDATE addressbook SET acked=1 WHERE id=?", (cid,), "addressbook", cid ) self.db.delete("DELETE FROM invitations WHERE id=?", (self.iid,), "invitations", self.iid) # we no longer care about the channel msg4 = "i0:destroy:"+os.urandom(16) self.send(msg4, persist=False) self.manager.unsubscribe(self.inviteID)