def test_box_wrong_lengths(): A_pubkey, A_secretkey = c.crypto_box_keypair() with pytest.raises(ValueError): c.crypto_box(b"abc", "\x00", A_pubkey, A_secretkey) with pytest.raises(ValueError): c.crypto_box(b"abc", "\x00" * c.crypto_box_NONCEBYTES, b"", A_secretkey) with pytest.raises(ValueError): c.crypto_box(b"abc", "\x00" * c.crypto_box_NONCEBYTES, A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_open(b"", b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_open(b"", "\x00" * c.crypto_box_NONCEBYTES, b"", b"") with pytest.raises(ValueError): c.crypto_box_open(b"", "\x00" * c.crypto_box_NONCEBYTES, A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_beforenm(b"", b"") with pytest.raises(ValueError): c.crypto_box_beforenm(A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_afternm(b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_afternm(b"", b"\x00" * c.crypto_box_NONCEBYTES, b"") with pytest.raises(ValueError): c.crypto_box_open_afternm(b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_open_afternm(b"", b"\x00" * c.crypto_box_NONCEBYTES, b"")
def test_box_wrong_lengths(): A_pubkey, A_secretkey = c.crypto_box_keypair() with pytest.raises(ValueError): c.crypto_box(b"abc", "\x00", A_pubkey, A_secretkey) with pytest.raises(ValueError): c.crypto_box( b"abc", "\x00" * c.crypto_box_NONCEBYTES, b"", A_secretkey) with pytest.raises(ValueError): c.crypto_box( b"abc", "\x00" * c.crypto_box_NONCEBYTES, A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_open(b"", b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_open(b"", "\x00" * c.crypto_box_NONCEBYTES, b"", b"") with pytest.raises(ValueError): c.crypto_box_open(b"", "\x00" * c.crypto_box_NONCEBYTES, A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_beforenm(b"", b"") with pytest.raises(ValueError): c.crypto_box_beforenm(A_pubkey, b"") with pytest.raises(ValueError): c.crypto_box_afternm(b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_afternm(b"", b"\x00" * c.crypto_box_NONCEBYTES, b"") with pytest.raises(ValueError): c.crypto_box_open_afternm(b"", b"", b"") with pytest.raises(ValueError): c.crypto_box_open_afternm(b"", b"\x00" * c.crypto_box_NONCEBYTES, b"")
def test_box(): A_pubkey, A_secretkey = c.crypto_box_keypair() assert len(A_secretkey) == c.crypto_box_SECRETKEYBYTES assert len(A_pubkey) == c.crypto_box_PUBLICKEYBYTES B_pubkey, B_secretkey = c.crypto_box_keypair() k1 = c.crypto_box_beforenm(B_pubkey, A_secretkey) assert len(k1) == c.crypto_box_BEFORENMBYTES k2 = c.crypto_box_beforenm(A_pubkey, B_secretkey) assert tohex(k1) == tohex(k2) message = b"message" nonce = b"\x01" * c.crypto_box_NONCEBYTES ct1 = c.crypto_box_afternm(message, nonce, k1) assert len(ct1) == len(message) + c.crypto_box_BOXZEROBYTES ct2 = c.crypto_box(message, nonce, B_pubkey, A_secretkey) assert tohex(ct2) == tohex(ct1) m1 = c.crypto_box_open(ct1, nonce, A_pubkey, B_secretkey) assert m1 == message m2 = c.crypto_box_open_afternm(ct1, nonce, k1) assert m2 == message with pytest.raises(CryptoError): c.crypto_box_open(message + b"!", nonce, A_pubkey, A_secretkey)
def test_box(): A_pubkey, A_secretkey = c.crypto_box_keypair() assert len(A_secretkey) == c.crypto_box_SECRETKEYBYTES assert len(A_pubkey) == c.crypto_box_PUBLICKEYBYTES B_pubkey, B_secretkey = c.crypto_box_keypair() k1 = c.crypto_box_beforenm(B_pubkey, A_secretkey) assert len(k1) == c.crypto_box_BEFORENMBYTES k2 = c.crypto_box_beforenm(A_pubkey, B_secretkey) assert tohex(k1) == tohex(k2) message = b"message" nonce = b"\x01" * c.crypto_box_NONCEBYTES ct1 = c.crypto_box_afternm(message, nonce, k1) assert len(ct1) == len(message) + c.crypto_box_BOXZEROBYTES ct2 = c.crypto_box(message, nonce, B_pubkey, A_secretkey) assert tohex(ct2) == tohex(ct1) m1 = c.crypto_box_open(ct1, nonce, A_pubkey, B_secretkey) assert m1 == message m2 = c.crypto_box_open_afternm(ct1, nonce, k1) assert m2 == message with pytest.raises(CryptoError): c.crypto_box_open( message + b"!", nonce, A_pubkey, A_secretkey)
def verify_client_auth(self, client_auth): """ verify the client auth crypto envelope. this operation is performed by the server when it receives a client auth message. """ scalar = crypto_scalarmult(bytes(self.local_ephemeral_key.private_key), bytes(self._remote_ephemeral_pub_key)) scalar_remote_longterm = crypto_scalarmult( bytes(self.local_signing_key.private_key.to_curve25519_private_key( )), bytes(self._remote_ephemeral_pub_key)) hasher = hashlib.sha256() hasher.update(self.application_key + scalar + scalar_remote_longterm) box_secret = hasher.digest() nonce = b"\x00" * 24 message = crypto_box_open_afternm(client_auth, nonce, box_secret) self._client_vouch = message self.remote_longterm_pub_key = VerifyKey(message[:32]) signature = message[32:] hasher = hashlib.sha256() scalar = crypto_scalarmult(bytes(self.local_ephemeral_key.private_key), bytes(self._remote_ephemeral_pub_key)) hasher.update(scalar) hashed_value = hasher.digest() signed_message = self.application_key + bytes( self.local_signing_key.public_key) + hashed_value self.remote_longterm_pub_key.verify(signed_message, signature=signature)
def verify_server_accept(self, data): """Verify that the server's accept message is sane""" curve_lkey = self.local_key.to_curve25519_private_key() # b_alice is (A * b) b_alice = crypto_scalarmult(bytes(curve_lkey), self.remote_ephemeral_key) self.b_alice = b_alice # this is hash(K | a * b | a * B | A * b) self.box_secret = hashlib.sha256(self.application_key + self.shared_secret + self.a_bob + b_alice).digest() nonce = b"\x00" * 24 try: # let's use the box secret to unbox our encrypted message signature = crypto_box_open_afternm(data, nonce, self.box_secret) except CryptoError: raise SHSError('Error decrypting server acceptance message') # we should have received sign(B)[K | H | hash(a * b)] # let's see if that signature can verify the reconstructed data on our side self.remote_pub_key.verify( self.application_key + self.hello + self.shared_hash, signature) return True
def verify_client_auth(self, data): assert len(data) == 112 a_bob = crypto_scalarmult(bytes(self.local_key.to_curve25519_private_key()), self.remote_ephemeral_key) box_secret = hashlib.sha256(self.application_key + self.shared_secret + a_bob).digest() self.hello = crypto_box_open_afternm(data, b'\x00' * 24, box_secret) signature, public_key = self.hello[:64], self.hello[64:] signed = self.application_key + bytes(self.local_key.verify_key) + self.shared_hash pkey = VerifyKey(public_key) # will raise an exception if verification fails pkey.verify(signed, signature) self.remote_pub_key = pkey b_alice = crypto_scalarmult(bytes(self.local_ephemeral_key), bytes(self.remote_pub_key.to_curve25519_public_key())) self.box_secret = hashlib.sha256(self.application_key + self.shared_secret + a_bob + b_alice).digest()[:32] return True
def verify_server_accept(self, server_accept_envelope): """ this is used by the client to verify the server accept envelope """ remote_longterm_sharedsecret = crypto_scalarmult( bytes(self.local_ephemeral_key.private_key), bytes(self.remote_longterm_pub_key.to_curve25519_public_key())) local_longterm_sharedsecret = crypto_scalarmult( bytes(self.local_signing_key.private_key.to_curve25519_private_key( )), bytes(self._remote_ephemeral_pub_key)) to_hash = self.application_key + self._secret + remote_longterm_sharedsecret + local_longterm_sharedsecret hasher = hashlib.sha256() hasher.update(to_hash) box_secret = hasher.digest() self._shared_secret = box_secret nonce = b"\x00" * 24 signature = crypto_box_open_afternm(server_accept_envelope, nonce, box_secret) message = self.application_key + self._client_auth + self._hashed_secret self.remote_longterm_pub_key.verify(message, signature)
def crypto_box_open_afternm(self, c, n, k): try: return bindings.crypto_box_open_afternm(c, n, k) except Exception as e: raise BadEncryptedDataException(e)