Example #1
0
    def test_symmetric_one_pass(self):
        encrypt, decrypt = 1, 0

        iv = ec.Cipher.gen_IV(self.ciphername)
        enc_cipher = ec.Cipher(self.secret_key,
                               iv,
                               encrypt,
                               ciphername=self.ciphername)

        plaintext_part1 = "Test plaintext part 1"
        plaintext_part2 = "Test plaintext part 2"
        plaintext = plaintext_part1 + plaintext_part2

        ciphertext_part1 = enc_cipher.update(plaintext_part1)
        ciphertext_part2 = enc_cipher.update(plaintext_part2)
        ciphertext_final = enc_cipher.final()
        ciphertext = "".join(
            (ciphertext_part1, ciphertext_part2, ciphertext_final))

        dec_cipher = ec.Cipher(self.secret_key,
                               iv,
                               decrypt,
                               ciphername=self.ciphername)

        self.assertEqual(plaintext, dec_cipher.ciphering(ciphertext))
Example #2
0
    def setup_cipher(self):
        # https://github.com/ethereum/cpp-ethereum/blob/develop/libp2p/RLPxFrameIO.cpp#L34
        assert self.responder_nonce
        assert self.initiator_nonce
        assert self.auth_init
        assert self.auth_ack
        assert self.remote_ephemeral_pubkey
        if not self.ecc.is_valid_key(self.remote_ephemeral_pubkey):
            raise InvalidKeyError('invalid remote ephemeral pubkey')

        # derive base secrets from ephemeral key agreement
        # ecdhe-shared-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
        ecdhe_shared_secret = self.ephemeral_ecc.get_ecdh_key(
            self.remote_ephemeral_pubkey)

        # shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
        shared_secret = sha3(ecdhe_shared_secret +
                             sha3(self.responder_nonce + self.initiator_nonce))

        self.ecdhe_shared_secret = ecdhe_shared_secret  # FIXME DEBUG
        self.shared_secret = shared_secret  # FIXME DEBUG

        # token = sha3(shared-secret)
        self.token = sha3(shared_secret)
        self.token_by_pubkey[self.remote_pubkey] = self.token

        # aes-secret = sha3(ecdhe-shared-secret || shared-secret)
        self.aes_secret = sha3(ecdhe_shared_secret + shared_secret)

        # mac-secret = sha3(ecdhe-shared-secret || aes-secret)
        self.mac_secret = sha3(ecdhe_shared_secret + self.aes_secret)

        # setup sha3 instances for the MACs
        # egress-mac = sha3.update(mac-secret ^ recipient-nonce || auth-sent-init)
        mac1 = sha3_256(
            sxor(self.mac_secret, self.responder_nonce) + self.auth_init)
        # ingress-mac = sha3.update(mac-secret ^ initiator-nonce || auth-recvd-ack)
        mac2 = sha3_256(
            sxor(self.mac_secret, self.initiator_nonce) + self.auth_ack)

        if self.is_initiator:
            self.egress_mac, self.ingress_mac = mac1, mac2
        else:
            self.egress_mac, self.ingress_mac = mac2, mac1

        ciphername = 'aes-256-ctr'
        iv = "\x00" * 16
        assert len(iv) == 16
        self.aes_enc = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         1,
                                         ciphername=ciphername)
        self.aes_dec = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         0,
                                         ciphername=ciphername)
        self.mac_enc = AES.AESCipher(self.mac_secret, AES.MODE_ECB).encrypt

        self.is_ready = True
Example #3
0
    def encrypt(self,
                data: bytes,
                raw_pubkey: bytes,
                shared_mac_data: bytes = b'') -> bytes:
        """
        ECIES Encrypt, where P = recipient public key is:
        1) generate r = random value
        2) generate shared-secret = kdf( ecdhAgree(r, P) )
        3) generate R = rG [same op as generating a public key]
        4) send 0x04 || R || AES(shared-secret, plaintext) || tag
        """
        enc_key, mac_key, ephem_pubkey = \
            self.key_manager.get_ephem_key(raw_pubkey)

        iv = pyelliptic.Cipher.gen_IV(self.CIPHERNAME)
        assert len(iv) == 16

        cipher = pyelliptic.Cipher(enc_key, iv, 1, self.CIPHERNAME)
        ciphertext = cipher.ciphering(data)
        assert len(ciphertext) == len(data)

        msg = ephem_pubkey + iv + ciphertext

        tag = pyelliptic.hmac_sha256(mac_key, msg[1 + 64:] + shared_mac_data)
        assert len(tag) == 32

        msg += tag
        assert len(msg) == self.OVERHEAD + len(data)

        return msg
Example #4
0
 def encrypt(self, raw):
     raw = self.pad(raw)
     iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
     ctx = pyelliptic.Cipher(self.key, iv, 1, ciphername='aes-256-cfb')
     ciphertext = ctx.update(raw)
     ciphertext += ctx.final()
     return (iv + ciphertext).encode("hex")
Example #5
0
    def ecies_encrypt(cls, data, raw_pubkey, shared_mac_data=''):
        """
        ECIES Encrypt, where P = recipient public key is:
        1) generate r = random value
        2) generate shared-secret = kdf( ecdhAgree(r, P) )
        3) generate R = rG [same op as generating a public key]
        4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag


        currently used by go:
        ECIES_AES128_SHA256 = &ECIESParams{
            Hash: sha256.New,
            hashAlgo: crypto.SHA256,
            Cipher: aes.NewCipher,
            BlockSize: aes.BlockSize,
            KeyLen: 16,
            }

        """
        # 1) generate r = random value
        ephem = cls(None)

        # 2) generate shared-secret = kdf( ecdhAgree(r, P) )
        key_material = ephem.raw_get_ecdh_key(pubkey_x=raw_pubkey[:32],
                                              pubkey_y=raw_pubkey[32:])
        assert len(key_material) == 32
        key = eciesKDF(key_material, 32)
        assert len(key) == 32
        key_enc, key_mac = key[:16], key[16:]

        key_mac = hashlib.sha256(key_mac).digest()  # !!!
        assert len(key_mac) == 32
        # 3) generate R = rG [same op as generating a public key]
        ephem_pubkey = ephem.raw_pubkey

        # encrypt
        iv = pyelliptic.Cipher.gen_IV(cls.ecies_ciphername)
        assert len(iv) == 16
        ctx = pyelliptic.Cipher(key_enc, iv, 1, cls.ecies_ciphername)
        ciphertext = ctx.ciphering(data)
        assert len(ciphertext) == len(data)

        # 4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext)
        #    || tag
        msg = rlp_utils.ascii_chr(0x04) + ephem_pubkey + iv + ciphertext

        # the MAC of a message (called the tag) as per SEC 1, 3.5.
        tag = pyelliptic.hmac_sha256(
            key_mac, msg[1 + 64:] + rlp_utils.str_to_bytes(shared_mac_data))
        assert len(tag) == 32
        msg += tag

        assert len(msg) == 1 + 64 + 16 + 32 + len(data) == 113 + len(data)
        assert len(msg) - cls.ecies_encrypt_overhead_length == len(data)
        return msg
Example #6
0
    def something():
        ##################

        # send authentication if not yet
        if not self._authentication_sent:
            remote_node = RemoteNode(remote_pubkey)  # FIXME LOOKUP
            self.send_authentication(remote_node)

            # - success -> AcknowledgeAuthentication
            self.acknowledge_authentication(other, remote_pubkey,
                                            remote_ecdhe_pubkey)

        # ecdhe_shared_secret = ecdh.agree(ecdhe-random, ecdhe-random-public)
        # Compute public key with the local private key and return a 512bits shared key
        ecdhe_shared_secret = self.ephemeral_ecc.get_ecdh_key(remote_pubkey)
        ecdhe_pubkey = self.ephemeral_ecc.get_pubkey()
        # shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || remote-nonce))
        shared_secret = sha3(ecdhe_shared_secret +
                             sha3(ienc(self.nonce) + ienc(remote_nonce)))

        self.aes_secret = sha3(ecdhe_shared_secret + shared_secret)
        self.mac_secret = sha3(ecdhe_shared_secret + self.aes_secret)
        # egress-mac = sha3(mac-secret^nonce || auth)
        self.egress_mac = sha3(sxor(self.mac_secret, self.nonce) + ciphertext)
        # ingress-mac = sha3(mac-secret^remote-nonce || auth)
        self.ingress_mac = sha3(
            sxor(self.mac_secret, remote_nonce) + ciphertext)
        self.token = sha3(shared_secret)

        iv = pyelliptic.Cipher.gen_IV('aes-256-ctr')
        self.aes_enc = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         1,
                                         ciphername='aes-256-ctr')
        self.aes_dec = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         0,
                                         ciphername='aes-256-ctr')

        self.is_ready = True
Example #7
0
    def ecies_decrypt(self, data, shared_mac_data=b''):
        """
        Decrypt data with ECIES method using the local private key

        ECIES Decrypt (performed by recipient):
        1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
        2) verify tag
        3) decrypt

        ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
        [where R = r*G, and recipientPublic = recipientPrivate*G]

        """
        if data[:1] != b'\x04':
            raise exceptions.DecryptionError("wrong ecies header")

        #  1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
        _shared = data[1:1 + 64]
        # FIXME, check that _shared_pub is a valid one (on curve)

        key_material = self.raw_get_ecdh_key(pubkey_x=_shared[:32],
                                             pubkey_y=_shared[32:])
        assert len(key_material) == 32
        key = eciesKDF(key_material, 32)
        assert len(key) == 32
        key_enc, key_mac = key[:16], key[16:]

        key_mac = hashlib.sha256(key_mac).digest()
        assert len(key_mac) == 32

        tag = data[-32:]
        assert len(tag) == 32

        # 2) verify tag
        hmaced_data = pyelliptic.hmac_sha256(
            key_mac, data[1 + 64:-32] + shared_mac_data)
        if not pyelliptic.equals(hmaced_data, tag):
            raise exceptions.DecryptionError("Fail to verify data")

        # 3) decrypt
        blocksize = pyelliptic.OpenSSL.get_cipher(
            self.ecies_ciphername).get_blocksize()  # noqa
        iv = data[1 + 64:1 + 64 + blocksize]
        assert len(iv) == 16
        ciphertext = data[1 + 64 + blocksize:-32]
        assert 1 + len(_shared) + len(iv) + len(ciphertext) + len(tag) == len(
            data)  # noqa
        ctx = pyelliptic.Cipher(key_enc, iv, 0, self.ecies_ciphername)
        return ctx.ciphering(ciphertext)
Example #8
0
    def decrypt(self, data, raw_privkey, shared_mac_data=b''):
        """
        Decrypt data with ECIES method using the local private key

        ECIES Decrypt (performed by recipient):
        1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
        2) verify tag
        3) decrypt

        ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
        [where R = r*G, and recipientPublic = recipientPrivate*G]

        """
        if data[:1] != b'\x04':
            raise exceptions.DecryptionError("Wrong ECIES header")

        # 1) generate shared-secret
        ephem_pubkey = data[:1 + 64]
        key_material = self.key_manager.ecdh(HashablePrivateKey(raw_privkey),
                                             ephem_pubkey)
        assert len(key_material) == 32

        enc_key, mac_key = self.key_manager.get_derived_keys(key_material)

        tag = data[-32:]
        assert len(tag) == 32

        # 2) verify tag
        hmaced_data = pyelliptic.hmac_sha256(
            mac_key, data[1 + 64:-32] + shared_mac_data)
        if not pyelliptic.equals(hmaced_data, tag):
            raise exceptions.DecryptionError("Tag verification failed")

        # 3) decrypt
        iv = data[1 + 64:1 + 64 + self.BLOCK_SIZE]
        assert len(iv) == 16

        ciphertext = data[1 + 64 + self.BLOCK_SIZE:-32]
        assert len(ephem_pubkey) + len(iv) + len(ciphertext) + len(tag) \
            == len(data)

        cipher = pyelliptic.Cipher(enc_key, iv, 0, self.CIPHERNAME)
        msg = cipher.ciphering(ciphertext)
        assert len(msg) == len(ciphertext)
        return msg
Example #9
0
    def decrypt(self, data, shared_mac_data=b""):
        """
        Decrypt data with ECIES method using the local private key

        ECIES Decrypt (performed by recipient):
        1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
        2) verify tag
        3) decrypt

        ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
        [where R = r*G, and recipientPublic = recipientPrivate*G]

        :param data: data to decrypt
        :param shared_mac_data: shared mac
        :return: decrypted data
        """

        if not data:
            raise ValueError("Data is required")

        if data[:eth_common_constants.
                ECIES_HEADER_LEN] != eth_common_constants.ECIES_HEADER_BYTE:
            raise DecryptionError("Wrong ECIES header")

        #  1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
        shared = data[eth_common_constants.
                      ECIES_HEADER_LEN:eth_common_constants.ECIES_HEADER_LEN +
                      eth_common_constants.PUBLIC_KEY_LEN]

        shared_pubkey_x = shared[:eth_common_constants.PUBLIC_KEY_X_Y_LEN]
        shared_pubkey_y = shared[eth_common_constants.PUBLIC_KEY_X_Y_LEN:]

        key_material = self.raw_get_ecdh_key(pubkey_x=shared_pubkey_x,
                                             pubkey_y=shared_pubkey_y)
        assert len(key_material) == eth_common_constants.KEY_MATERIAL_LEN
        key = crypto_utils.ecies_kdf(key_material,
                                     eth_common_constants.SHARED_KEY_LEN)
        assert len(key) == eth_common_constants.SHARED_KEY_LEN
        key_enc, key_mac = key[:eth_common_constants.ENC_KEY_LEN], key[
            eth_common_constants.ENC_KEY_LEN:]

        key_mac = hashlib.sha256(key_mac).digest()
        assert len(key_mac) == eth_common_constants.MAC_LEN

        tag = data[-eth_common_constants.MAC_LEN:]
        assert len(tag) == eth_common_constants.MAC_LEN

        # 2) verify tag
        header_len = eth_common_constants.ECIES_HEADER_LEN + eth_common_constants.PUBLIC_KEY_LEN

        mac_data = data[header_len:- eth_common_constants.MAC_LEN] + \
                   shared_mac_data
        if not pyelliptic.equals(pyelliptic.hmac_sha256(key_mac, mac_data),
                                 tag):
            raise DecryptionError("Fail to verify data")

        # 3) decrypt
        block_size = pyelliptic.OpenSSL.get_cipher(
            eth_common_constants.ECIES_CIPHER_NAME).get_blocksize()

        iv = data[header_len:header_len + block_size]
        cipher_text = data[header_len +
                           block_size:-eth_common_constants.MAC_LEN]
        assert eth_common_constants.ECIES_HEADER_LEN + len(shared) + len(
            iv) + len(cipher_text) + len(tag) == len(data)
        ctx = pyelliptic.Cipher(key_enc, iv,
                                eth_common_constants.CIPHER_DECRYPT_DO,
                                eth_common_constants.ECIES_CIPHER_NAME)
        return ctx.ciphering(cipher_text)
Example #10
0
    def receive_authentication(self, other, ciphertext):
        """
        Verification (function, upon receive of PresetAuthentication):
        3. remote generates ecdhe-random and nonce and creates auth
        4. remote receives auth and decrypts (ECIES performs authentication before
        decryption)
            - If address is known, lookup token and public key to be authenticated
            - derive signature-message = sha3(token || addr^addrRemote)
            - success -> AcknowledgeAuthentication
        5. remote sends auth
        6. remote derives shared-secret, aes-secret, mac-secret, ingress-mac, egress-mac
"""

        # eciesEncrypt(remote-pubk, sign(privkey, token^nonce) || 0x80 || ecdhe-random || nonce )

        data = self.node.decrypt(ciphertext)
        assert len(data) == 64 + 1 + 64 + 32
        signature = data[:65]
        assert data[65] == '0x80'
        remote_ecdhe_pubkey = data[65:65 + 64]
        token_or_nonce = idec(data[-32:])

        # verify signature
        if not self.node.verify(signature, token_or_nonce):
            return self.disconnect()

        # recover remote pubkey
        remote_pubkey = ecdsa_recover(token_or_nonce, signature)

        # lookup pubkey and related token
        token_database = dict()  # FIXME
        token = token_database.get(remote_pubkey, None)
        if token and token != token_or_nonce:
            # something fishy
            # FIXME reset node reputation
            pass

        remote_nonce = token_or_nonce

        # send authentication if not yet
        if not self._authentication_sent:
            remote_node = RemoteNode(remote_pubkey)  # FIXME LOOKUP
            self.send_authentication(remote_node)

            # - success -> AcknowledgeAuthentication
            self.acknowledge_authentication(other, remote_pubkey,
                                            remote_ecdhe_pubkey)

        # ecdhe_shared_secret = ecdh.agree(ecdhe-random, ecdhe-random-public)
        # Compute public key with the local private key and return a 512bits shared key
        ecdhe_shared_secret = self.ephemeral_ecc.get_ecdh_key(remote_pubkey)
        ecdhe_pubkey = ephemeral_ecc.get_pubkey()
        # shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || remote-nonce))
        shared_secret = sha3(ecdhe_shared_secret +
                             sha3(ienc(self.nonce) + ienc(remote_nonce)))

        self.aes_secret = sha3_256(ecdhe_shared_secret + shared_secret)
        self.mac_secret = sha3_256(ecdhe_shared_secret + self.aes_secret)
        # egress-mac = sha3(mac-secret^nonce || auth)
        self.egress_mac = sha3_256(
            sxor(self.mac_secret, self.nonce) + ciphertext)
        # ingress-mac = sha3(mac-secret^remote-nonce || auth)
        self.ingress_mac = sha3_256(
            sxor(self.mac_secret, remote_nonce) + ciphertext)
        self.token = sha3(shared_secret)

        iv = pyelliptic.Cipher.gen_IV('aes-256-ctr')
        self.aes_enc = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         1,
                                         ciphername='aes-256-ctr')
        self.aes_dec = pyelliptic.Cipher(self.aes_secret,
                                         iv,
                                         0,
                                         ciphername='aes-256-ctr')

        self.is_ready = True
Example #11
0
import pyelliptic

# Symmetric encryption
iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
ctx = pyelliptic.Cipher("secretkey", iv, 1, ciphername='aes-256-cfb')

ciphertext = ctx.update('test1')
ciphertext += ctx.update('test2')
ciphertext += ctx.final()

ctx2 = pyelliptic.Cipher("secretkey", iv, 0, ciphername='aes-256-cfb')
print ctx2.ciphering(ciphertext)

# Asymmetric encryption
alice = pyelliptic.ECC(curve='secp256k1')
bob = pyelliptic.ECC(curve='secp256k1')

ciphertext = alice.encrypt("Hello bbBob", bob.get_pubkey())
print bob.decrypt(ciphertext)

signature = bob.sign("Hello Alice")
# alice's job :
print pyelliptic.ECC(pubkey=bob.get_pubkey()).verify(signature, "Hello Alice")

# ERROR !!!
try:
    key = alice.get_ecdh_key(bob.get_pubkey())
except:
    print(
        "For ECDH key agreement, the keys must be defined on the same curve !")
Example #12
0
def decrypt_aes(encrypted_data, key, iv, ciphername=DEFAUL_CIPHERNAME):
    ctx = pyelliptic.Cipher(key, iv, 0, ciphername=ciphername)
    return ctx.ciphering(encrypted_data)
Example #13
0
def encrypt_aes(data, key, ciphername=DEFAUL_CIPHERNAME):
    iv = pyelliptic.Cipher.gen_IV(ciphername)
    ctx = pyelliptic.Cipher(key, iv, 1, ciphername=ciphername)
    ciphertext = ctx.update(data)
    ciphertext += ctx.final()
    return hexlify(ciphertext), hexlify(iv)
Example #14
0
    def encrypt(cls, data, raw_public_key, shared_mac_data=""):
        """
        ECIES Encrypt, where P = recipient public key is:
        1) generate r = random value
        2) generate shared-secret = kdf( ecdhAgree(r, P) )
        3) generate R = rG [same op as generating a public key]
        4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag


        currently used by go:
        ECIES_AES128_SHA256 = &ECIESParams{
            Hash: sha256.New,
            hashAlgo: crypto.SHA256,
            Cipher: aes.NewCipher,
            BlockSize: aes.BlockSize,
            KeyLen: 16,
            }

        :param data: data to encrypt
        :param raw_public_key: public key used of encryption
        :param shared_mac_data: shared mac
        :return: encrypted data
        """

        if not data:
            raise ValueError("Data is required")

        if len(raw_public_key) != eth_common_constants.PUBLIC_KEY_LEN:
            raise ValueError(
                "Public key of len {0} is expected but was {1}".format(
                    eth_common_constants.PUBLIC_KEY_LEN, len(raw_public_key)))

        # 1) generate r = random value
        ephem = ECCx()

        # 2) generate shared-secret = kdf( ecdhAgree(r, P) )
        pubkey_x = raw_public_key[:eth_common_constants.PUBLIC_KEY_X_Y_LEN]
        pubkey_y = raw_public_key[eth_common_constants.PUBLIC_KEY_X_Y_LEN:]
        key_material = ephem.raw_get_ecdh_key(pubkey_x=pubkey_x,
                                              pubkey_y=pubkey_y)

        key = crypto_utils.ecies_kdf(key_material,
                                     eth_common_constants.SHARED_KEY_LEN)
        assert len(key) == eth_common_constants.SHARED_KEY_LEN
        key_enc, key_mac = key[:eth_common_constants.ENC_KEY_LEN], key[
            eth_common_constants.ENC_KEY_LEN:]

        key_mac = hashlib.sha256(key_mac).digest()

        # 3) generate R = rG [same op as generating a public key]
        ephem_pubkey = ephem.get_raw_public_key()

        # encrypt
        iv = pyelliptic.Cipher.gen_IV(eth_common_constants.ECIES_CIPHER_NAME)
        assert len(iv) == eth_common_constants.IV_LEN

        ctx = pyelliptic.Cipher(key_enc, iv,
                                eth_common_constants.CIPHER_ENCRYPT_DO,
                                eth_common_constants.ECIES_CIPHER_NAME)
        cipher_text = ctx.ciphering(data)
        assert len(cipher_text) == len(data)

        # 4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag
        msg = rlp_utils.ascii_chr(eth_common_constants.ECIES_HEADER
                                  ) + ephem_pubkey + iv + cipher_text

        # the MAC of a message (called the tag) as per SEC 1, 3.5.
        tag = pyelliptic.hmac_sha256(
            key_mac, msg[eth_common_constants.ECIES_HEADER_LEN +
                         eth_common_constants.PUBLIC_KEY_LEN:] +
            rlp_utils.str_to_bytes(shared_mac_data))
        assert len(tag) == eth_common_constants.MAC_LEN
        msg += tag

        assert len(
            msg) - eth_common_constants.ECIES_ENCRYPT_OVERHEAD_LENGTH == len(
                data)
        return msg
Example #15
0
 def decrypt(self, enc):
     enc = enc.decode("hex")
     (iv, enc) = enc[:16], enc[16:]
     ctx = pyelliptic.Cipher(self.key, iv, 0, ciphername='aes-256-cfb')
     return self.unpad(ctx.ciphering(enc))
Example #16
0
ecc = pyelliptic.ECC(privkey=myPrivkey, pubkey=myPubkey, curve='secp521r1')

#Get Receiver public key

r = requests.get(url + "/values/pubkey.json")
receiverPubkey = unhexlify(r.json()["pubkey"])

#Generate Shared key
sharedKey = ecc.get_ecdh_key(receiverPubkey)

#Sign Message
signature = ecc.sign(message)

#Encrypt Message
# Symmetric encryption
iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
ctx = pyelliptic.Cipher(sharedKey, iv, 1, ciphername='aes-256-cfb')
ciphertext = ctx.update(message)
ciphertext += ctx.final()

print "Shared Key: ", hexlify(sharedKey)

#Send Signature, Ciphertext and Public Key
payload = {
    "ciphertext": ciphertext,
    "signature": signature,
    "pubkey": hexlify(ecc.get_pubkey())
}
r = requests.post(url + "/receive", data=payload)
print r.text
Example #17
0
    def setup_cipher(self):
        """
        Sets up cipher parameters.
        Needs to be called after initial authentication handshake
        """

        assert self._responder_nonce
        assert self._initiator_nonce
        assert self._auth_init
        assert self._auth_ack
        assert self._remote_ephemeral_pubkey
        if not self._ecc.is_valid_key(self._remote_ephemeral_pubkey):
            raise InvalidKeyError("Invalid remote ephemeral pubkey")

        # derive base secrets from ephemeral key agreement
        # ecdhe-shared-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
        ecdhe_shared_secret = self._ephemeral_ecc.get_ecdh_key(
            self._remote_ephemeral_pubkey)

        # shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
        shared_secret = eth_common_utils.keccak_hash(
            ecdhe_shared_secret +
            eth_common_utils.keccak_hash(self._responder_nonce +
                                         self._initiator_nonce))

        self.ecdhe_shared_secret = ecdhe_shared_secret  # used in tests
        self.shared_secret = shared_secret  # used in tests

        # token = sha3(shared-secret)
        self._token = eth_common_utils.keccak_hash(shared_secret)

        # aes-secret = sha3(ecdhe-shared-secret || shared-secret)
        self._aes_secret = eth_common_utils.keccak_hash(ecdhe_shared_secret +
                                                        shared_secret)

        # mac-secret = sha3(ecdhe-shared-secret || aes-secret)
        self.mac_secret = eth_common_utils.keccak_hash(ecdhe_shared_secret +
                                                       self._aes_secret)

        # setup sha3 instances for the MACs
        # egress-mac = sha3.update(mac-secret ^ recipient-nonce || auth-sent-init)
        mac1 = crypto_utils.get_sha3_calculator(
            crypto_utils.string_xor(self.mac_secret, self._responder_nonce) +
            self._auth_init)
        # ingress-mac = sha3.update(mac-secret ^ initiator-nonce || auth-recvd-ack)
        mac2 = crypto_utils.get_sha3_calculator(
            crypto_utils.string_xor(self.mac_secret, self._initiator_nonce) +
            self._auth_ack)

        if self._is_initiator:
            self._egress_mac, self._ingress_mac = mac1, mac2
        else:
            self._egress_mac, self._ingress_mac = mac2, mac1

        iv = "\x00" * eth_common_constants.IV_LEN
        self._aes_enc = pyelliptic.Cipher(
            self._aes_secret,
            iv,
            eth_common_constants.CIPHER_ENCRYPT_DO,
            ciphername=eth_common_constants.RLPX_CIPHER_NAME)
        self._aes_dec = pyelliptic.Cipher(
            self._aes_secret,
            iv,
            eth_common_constants.CIPHER_DECRYPT_DO,
            ciphername=eth_common_constants.RLPX_CIPHER_NAME)
        self._mac_enc = AES.new(self.mac_secret, AES.MODE_ECB).encrypt

        self._is_ready = True