Skip to content

Commit

Permalink
crypto_box_easy support
Browse files Browse the repository at this point in the history
  • Loading branch information
gon committed Aug 16, 2024
1 parent 56523d2 commit 1c49a13
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 2 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/nacl/bindings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
crypto_box_keypair,
crypto_box_open,
crypto_box_open_afternm,
crypto_box_easy,
crypto_box_open_easy,
crypto_box_easy_afternm,
crypto_box_open_easy_afternm,
crypto_box_seal,
crypto_box_seal_open,
crypto_box_seed_keypair,
Expand Down Expand Up @@ -279,6 +283,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
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
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

0 comments on commit 1c49a13

Please sign in to comment.