Skip to content

Commit

Permalink
crypto_box_easy and crypto_secretbox_easy support (#835)
Browse files Browse the repository at this point in the history
Co-authored-by: gon <[email protected]>
  • Loading branch information
gonatienza and gon authored Sep 1, 2024
1 parent a35b9fc commit e47e41e
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 4 deletions.
17 changes: 17 additions & 0 deletions src/bindings/crypto_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ size_t crypto_box_boxzerobytes();
size_t crypto_box_noncebytes();
size_t crypto_box_beforenmbytes();
size_t crypto_box_sealbytes();
size_t crypto_box_macbytes();


int crypto_box_keypair(unsigned char *pk, unsigned char *sk);
Expand Down Expand Up @@ -53,3 +54,19 @@ int crypto_box_seal(unsigned char *c, const unsigned char *m,
int crypto_box_seal_open(unsigned char *m, const unsigned char *c,
unsigned long long clen,
const unsigned char *pk, const unsigned char *sk);

int crypto_box_easy_afternm(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
const unsigned char *k);

int crypto_box_easy(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
const unsigned char *pk, const unsigned char *sk);

int crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c,
unsigned long long clen, const unsigned char *n,
const unsigned char *k);

int crypto_box_open_easy(unsigned char *m, const unsigned char *c,
unsigned long long clen, const unsigned char *n,
const unsigned char *pk, const unsigned char *sk);
8 changes: 8 additions & 0 deletions src/bindings/crypto_secretbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,11 @@ int crypto_secretbox(unsigned char *c, const unsigned char *m,
int crypto_secretbox_open(unsigned char *m, const unsigned char *c,
unsigned long long clen, const unsigned char *n,
const unsigned char *k);

int crypto_secretbox_easy(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
const unsigned char *k);

int crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c,
unsigned long long clen, const unsigned char *n,
const unsigned char *k);
12 changes: 12 additions & 0 deletions src/nacl/bindings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@
crypto_box_ZEROBYTES,
crypto_box_afternm,
crypto_box_beforenm,
crypto_box_easy,
crypto_box_easy_afternm,
crypto_box_keypair,
crypto_box_open,
crypto_box_open_afternm,
crypto_box_open_easy,
crypto_box_open_easy_afternm,
crypto_box_seal,
crypto_box_seal_open,
crypto_box_seed_keypair,
Expand Down Expand Up @@ -182,7 +186,9 @@
crypto_secretbox_MESSAGEBYTES_MAX,
crypto_secretbox_NONCEBYTES,
crypto_secretbox_ZEROBYTES,
crypto_secretbox_easy,
crypto_secretbox_open,
crypto_secretbox_open_easy,
)
from nacl.bindings.crypto_secretstream import (
crypto_secretstream_xchacha20poly1305_ABYTES,
Expand Down Expand Up @@ -279,6 +285,10 @@
"crypto_box_beforenm",
"crypto_box_afternm",
"crypto_box_open_afternm",
"crypto_box_easy",
"crypto_box_easy_afternm",
"crypto_box_open_easy",
"crypto_box_open_easy_afternm",
"crypto_box_seal",
"crypto_box_seal_open",
"crypto_box_seed_keypair",
Expand Down Expand Up @@ -343,7 +353,9 @@
"crypto_secretbox_MACBYTES",
"crypto_secretbox_MESSAGEBYTES_MAX",
"crypto_secretbox",
"crypto_secretbox_easy",
"crypto_secretbox_open",
"crypto_secretbox_open_easy",
"crypto_secretstream_xchacha20poly1305_ABYTES",
"crypto_secretstream_xchacha20poly1305_HEADERBYTES",
"crypto_secretstream_xchacha20poly1305_KEYBYTES",
Expand Down
151 changes: 151 additions & 0 deletions src/nacl/bindings/crypto_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
crypto_box_BOXZEROBYTES: int = lib.crypto_box_boxzerobytes()
crypto_box_BEFORENMBYTES: int = lib.crypto_box_beforenmbytes()
crypto_box_SEALBYTES: int = lib.crypto_box_sealbytes()
crypto_box_MACBYTES: int = lib.crypto_box_macbytes()


def crypto_box_keypair() -> Tuple[bytes, bytes]:
Expand Down Expand Up @@ -227,6 +228,156 @@ def crypto_box_open_afternm(
return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]


def crypto_box_easy(
message: bytes, nonce: bytes, pk: bytes, sk: bytes
) -> bytes:
"""
Encrypts and returns a message ``message`` using the secret key ``sk``,
public key ``pk``, and the nonce ``nonce``.
:param message: bytes
:param nonce: bytes
:param pk: bytes
:param sk: bytes
:rtype: bytes
"""
if len(nonce) != crypto_box_NONCEBYTES:
raise exc.ValueError("Invalid nonce size")

if len(pk) != crypto_box_PUBLICKEYBYTES:
raise exc.ValueError("Invalid public key")

if len(sk) != crypto_box_SECRETKEYBYTES:
raise exc.ValueError("Invalid secret key")

_mlen = len(message)
_clen = crypto_box_MACBYTES + _mlen

ciphertext = ffi.new("unsigned char[]", _clen)

rc = lib.crypto_box_easy(ciphertext, message, _mlen, nonce, pk, sk)
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)

return ffi.buffer(ciphertext, _clen)[:]


def crypto_box_open_easy(
ciphertext: bytes, nonce: bytes, pk: bytes, sk: bytes
) -> bytes:
"""
Decrypts and returns an encrypted message ``ciphertext``, using the secret
key ``sk``, public key ``pk``, and the nonce ``nonce``.
:param ciphertext: bytes
:param nonce: bytes
:param pk: bytes
:param sk: bytes
:rtype: bytes
"""
if len(nonce) != crypto_box_NONCEBYTES:
raise exc.ValueError("Invalid nonce size")

if len(pk) != crypto_box_PUBLICKEYBYTES:
raise exc.ValueError("Invalid public key")

if len(sk) != crypto_box_SECRETKEYBYTES:
raise exc.ValueError("Invalid secret key")

_clen = len(ciphertext)

ensure(
_clen >= crypto_box_MACBYTES,
"Input ciphertext must be at least {} long".format(
crypto_box_MACBYTES
),
raising=exc.TypeError,
)

_mlen = _clen - crypto_box_MACBYTES

plaintext = ffi.new("unsigned char[]", max(1, _mlen))

res = lib.crypto_box_open_easy(plaintext, ciphertext, _clen, nonce, pk, sk)
ensure(
res == 0,
"An error occurred trying to decrypt the message",
raising=exc.CryptoError,
)

return ffi.buffer(plaintext, _mlen)[:]


def crypto_box_easy_afternm(message: bytes, nonce: bytes, k: bytes) -> bytes:
"""
Encrypts and returns the message ``message`` using the shared key ``k`` and
the nonce ``nonce``.
:param message: bytes
:param nonce: bytes
:param k: bytes
:rtype: bytes
"""
if len(nonce) != crypto_box_NONCEBYTES:
raise exc.ValueError("Invalid nonce")

if len(k) != crypto_box_BEFORENMBYTES:
raise exc.ValueError("Invalid shared key")

_mlen = len(message)
_clen = crypto_box_MACBYTES + _mlen

ciphertext = ffi.new("unsigned char[]", _clen)

rc = lib.crypto_box_easy_afternm(ciphertext, message, _mlen, nonce, k)
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)

return ffi.buffer(ciphertext, _clen)[:]


def crypto_box_open_easy_afternm(
ciphertext: bytes, nonce: bytes, k: bytes
) -> bytes:
"""
Decrypts and returns the encrypted message ``ciphertext``, using the shared
key ``k`` and the nonce ``nonce``.
:param ciphertext: bytes
:param nonce: bytes
:param k: bytes
:rtype: bytes
"""
if len(nonce) != crypto_box_NONCEBYTES:
raise exc.ValueError("Invalid nonce")

if len(k) != crypto_box_BEFORENMBYTES:
raise exc.ValueError("Invalid shared key")

_clen = len(ciphertext)

ensure(
_clen >= crypto_box_MACBYTES,
"Input ciphertext must be at least {} long".format(
crypto_box_MACBYTES
),
raising=exc.TypeError,
)

_mlen = _clen - crypto_box_MACBYTES

plaintext = ffi.new("unsigned char[]", max(1, _mlen))

res = lib.crypto_box_open_easy_afternm(
plaintext, ciphertext, _clen, nonce, k
)
ensure(
res == 0,
"An error occurred trying to decrypt the message",
raising=exc.CryptoError,
)

return ffi.buffer(plaintext, _mlen)[:]


def crypto_box_seal(message: bytes, pk: bytes) -> bytes:
"""
Encrypts and returns a message ``message`` using an ephemeral secret key
Expand Down
73 changes: 73 additions & 0 deletions src/nacl/bindings/crypto_secretbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,76 @@ def crypto_secretbox_open(

plaintext = ffi.buffer(plaintext, len(padded))
return plaintext[crypto_secretbox_ZEROBYTES:]


def crypto_secretbox_easy(message: bytes, nonce: bytes, key: bytes) -> bytes:
"""
Encrypts and returns the message ``message`` with the secret ``key`` and
the nonce ``nonce``.
:param message: bytes
:param nonce: bytes
:param key: bytes
:rtype: bytes
"""
if len(key) != crypto_secretbox_KEYBYTES:
raise exc.ValueError("Invalid key")

if len(nonce) != crypto_secretbox_NONCEBYTES:
raise exc.ValueError("Invalid nonce")

_mlen = len(message)
_clen = crypto_secretbox_MACBYTES + _mlen

ciphertext = ffi.new("unsigned char[]", _clen)

res = lib.crypto_secretbox_easy(ciphertext, message, _mlen, nonce, key)
ensure(res == 0, "Encryption failed", raising=exc.CryptoError)

ciphertext = ffi.buffer(ciphertext, _clen)
return ciphertext[:]


def crypto_secretbox_open_easy(
ciphertext: bytes, nonce: bytes, key: bytes
) -> bytes:
"""
Decrypt and returns the encrypted message ``ciphertext`` with the secret
``key`` and the nonce ``nonce``.
:param ciphertext: bytes
:param nonce: bytes
:param key: bytes
:rtype: bytes
"""
if len(key) != crypto_secretbox_KEYBYTES:
raise exc.ValueError("Invalid key")

if len(nonce) != crypto_secretbox_NONCEBYTES:
raise exc.ValueError("Invalid nonce")

_clen = len(ciphertext)

ensure(
_clen >= crypto_secretbox_MACBYTES,
"Input ciphertext must be at least {} long".format(
crypto_secretbox_MACBYTES
),
raising=exc.TypeError,
)

_mlen = _clen - crypto_secretbox_MACBYTES

plaintext = ffi.new("unsigned char[]", max(1, _mlen))

res = lib.crypto_secretbox_open_easy(
plaintext, ciphertext, _clen, nonce, key
)
ensure(
res == 0,
"Decryption failed. Ciphertext failed verification",
raising=exc.CryptoError,
)

plaintext = ffi.buffer(plaintext, _mlen)
return plaintext[:]
4 changes: 2 additions & 2 deletions src/nacl/public.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def encrypt(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE
)

ciphertext = nacl.bindings.crypto_box_afternm(
ciphertext = nacl.bindings.crypto_box_easy_afternm(
plaintext,
nonce,
self._shared_key,
Expand Down Expand Up @@ -296,7 +296,7 @@ def decrypt(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE
)

plaintext = nacl.bindings.crypto_box_open_afternm(
plaintext = nacl.bindings.crypto_box_open_easy_afternm(
ciphertext,
nonce,
self._shared_key,
Expand Down
4 changes: 2 additions & 2 deletions src/nacl/secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def encrypt(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
)

ciphertext = nacl.bindings.crypto_secretbox(
ciphertext = nacl.bindings.crypto_secretbox_easy(
plaintext, nonce, self._key
)

Expand Down Expand Up @@ -146,7 +146,7 @@ def decrypt(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
)

plaintext = nacl.bindings.crypto_secretbox_open(
plaintext = nacl.bindings.crypto_secretbox_open_easy(
ciphertext, nonce, self._key
)

Expand Down
Loading

0 comments on commit e47e41e

Please sign in to comment.