Skip to content

Commit

Permalink
Merge branch 'jedisct1-up'
Browse files Browse the repository at this point in the history
  • Loading branch information
stef committed Nov 29, 2023
2 parents a99ea4f + 6effe68 commit 73a34d5
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 11 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ This wrapper requires a pre-installed libsodium from:
then it provides access to the following functions:

```
crypto_aead_aegis128l_decrypt(ciphertext, ad, nonce, key)
crypto_aead_aegis128l_encrypt(message, ad, nonce, key)
crypto_aead_aegis128l_decrypt_detached(ciphertext, mac, ad, nonce, key)
crypto_aead_aegis128l_encrypt_detached(message, ad, nonce, key)
crypto_aead_aegis256_decrypt(ciphertext, ad, nonce, key)
crypto_aead_aegis256_encrypt(message, ad, nonce, key)
crypto_aead_aegis256_decrypt_detached(ciphertext, mac, ad, nonce, key)
crypto_aead_aegis256_encrypt_detached(message, ad, nonce, key)
crypto_aead_chacha20poly1305_decrypt(ciphertext, ad, nonce, key)
crypto_aead_chacha20poly1305_encrypt(message, ad, nonce, key)
crypto_aead_chacha20poly1305_decrypt_detached(ciphertext, mac, ad, nonce, key)
Expand Down Expand Up @@ -118,6 +126,12 @@ crypto_kdf_hkdf_sha256_extract_final(state)
crypto_kdf_hkdf_sha256_extract(salt=b'', ikm=b'')
crypto_kdf_hkdf_sha256_keygen()
crypto_kdf_hkdf_sha256_expand(outlen, prk, ctx=b'')
crypto_kdf_hkdf_sha512_extract_init(salt=b'')
crypto_kdf_hkdf_sha512_extract_update(state, ikm=b'')
crypto_kdf_hkdf_sha512_extract_final(state)
crypto_kdf_hkdf_sha512_extract(salt=b'', ikm=b'')
crypto_kdf_hkdf_sha512_keygen()
crypto_kdf_hkdf_sha512_expand(outlen, prk, ctx=b'')
```

Constants:
Expand Down
211 changes: 200 additions & 11 deletions pysodium/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs):
crypto_secretstream_xchacha20poly1305_ABYTES = sodium.crypto_secretstream_xchacha20poly1305_abytes()
crypto_secretstream_xchacha20poly1305_HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_headerbytes()
crypto_secretstream_xchacha20poly1305_KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_keybytes()
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = sodium.crypto_secretstream_xchacha20poly1305_messagebytes_max()
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = ctypes.c_size_t(sodium.crypto_secretstream_xchacha20poly1305_messagebytes_max())
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_tag_message()
crypto_secretstream_xchacha20poly1305_TAG_PUSH = sodium.crypto_secretstream_xchacha20poly1305_tag_push()
crypto_secretstream_xchacha20poly1305_TAG_REKEY = sodium.crypto_secretstream_xchacha20poly1305_tag_rekey()
Expand All @@ -270,6 +270,22 @@ def wrapper(*args, **kwargs):
crypto_kdf_hkdf_sha256_BYTES_MIN = sodium.crypto_kdf_hkdf_sha256_bytes_min()
crypto_kdf_hkdf_sha256_BYTES_MAX = sodium.crypto_kdf_hkdf_sha256_bytes_max()
crypto_kdf_hkdf_sha256_STATEBYTES = sodium.crypto_kdf_hkdf_sha256_statebytes()
crypto_kdf_hkdf_sha512_KEYBYTES = sodium.crypto_kdf_hkdf_sha512_keybytes()
crypto_kdf_hkdf_sha512_BYTES_MIN = sodium.crypto_kdf_hkdf_sha512_bytes_min()
crypto_kdf_hkdf_sha512_BYTES_MAX = sodium.crypto_kdf_hkdf_sha512_bytes_max()
crypto_aead_aegis128l_KEYBYTES = sodium.crypto_aead_aegis128l_keybytes()
crypto_aead_aegis128l_NPUBBYTES = sodium.crypto_aead_aegis128l_npubbytes()
crypto_aead_aegis128l_NONCEBYTES = crypto_aead_aegis128l_NPUBBYTES
crypto_aead_aegis128l_ABYTES = sodium.crypto_aead_aegis128l_abytes()
crypto_aead_aegis128l_MESSAGEBYTES_MAX = ctypes.c_size_t(sodium.crypto_aead_aegis128l_messagebytes_max())
crypto_aead_aegis256_KEYBYTES = sodium.crypto_aead_aegis256_keybytes()
crypto_aead_aegis256_NPUBBYTES = sodium.crypto_aead_aegis256_npubbytes()
crypto_aead_aegis256_NONCEBYTES = crypto_aead_aegis256_NPUBBYTES
crypto_aead_aegis256_ABYTES = sodium.crypto_aead_aegis256_abytes()
crypto_aead_aegis256_MESSAGEBYTES_MAX = ctypes.c_size_t(sodium.crypto_aead_aegis256_messagebytes_max())

if sodium_version_check(1, 0, 20):
crypto_kdf_hkdf_sha512_STATEBYTES = sodium.crypto_kdf_hkdf_sha512_statebytes()

sodium_init = sodium.sodium_init

Expand Down Expand Up @@ -413,7 +429,7 @@ def crypto_aead_chacha20poly1305_encrypt(message, ad, nonce, key):
mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)

c = ctypes.create_string_buffer(mlen.value + 16)
c = ctypes.create_string_buffer(mlen.value + crypto_aead_chacha20poly1305_ABYTES)
clen = ctypes.c_ulonglong(0)

__check(sodium.crypto_aead_chacha20poly1305_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
Expand All @@ -425,7 +441,7 @@ def crypto_aead_chacha20poly1305_decrypt(ciphertext, ad, nonce, key):
if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key")

m = ctypes.create_string_buffer(len(ciphertext) - 16)
m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_chacha20poly1305_ABYTES)
mlen = ctypes.c_ulonglong(0)
clen = ctypes.c_ulonglong(len(ciphertext))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
Expand Down Expand Up @@ -463,6 +479,126 @@ def crypto_aead_chacha20poly1305_decrypt_detached(ciphertext, mac, ad, nonce, ke
__check(sodium.crypto_aead_chacha20poly1305_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key))
return m.raw

# crypto_aead_aegis128l_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k);
@sodium_version(1, 0, 19)
def crypto_aead_aegis128l_encrypt(message, ad, nonce, key):
if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key")

mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)

c = ctypes.create_string_buffer(mlen.value + crypto_aead_aegis128l_ABYTES)
clen = ctypes.c_ulonglong(0)

__check(sodium.crypto_aead_aegis128l_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
return c.raw


# crypto_aead_aegis128l_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis128l_decrypt(ciphertext, ad, nonce, key):
if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key")

m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_aegis128l_ABYTES)
mlen = ctypes.c_ulonglong(0)
clen = ctypes.c_ulonglong(len(ciphertext))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
__check(sodium.crypto_aead_aegis128l_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key))
return m.raw

# crypto_aead_aegis128l_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis128l_encrypt_detached(message, ad, nonce, key):
""" Return ciphertext, mac tag """
if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key")

mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
c = ctypes.create_string_buffer(mlen.value)
maclen_p = ctypes.c_ulonglong(crypto_aead_aegis128l_ABYTES)
mac = ctypes.create_string_buffer(maclen_p.value)

__check(sodium.crypto_aead_aegis128l_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key))
return c.raw, mac.raw

# crypto_aead_aegis128l_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis128l_decrypt_detached(ciphertext, mac, ad, nonce, key):
""" Return message if successful or -1 (ValueError) if not successful"""
if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key")
if len(mac) != crypto_aead_aegis128l_ABYTES:
raise ValueError("mac length != %i" % crypto_aead_aegis128l_ABYTES)

clen = ctypes.c_ulonglong(len(ciphertext))
m = ctypes.create_string_buffer(clen.value)
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
__check(sodium.crypto_aead_aegis128l_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key))
return m.raw

# crypto_aead_aegis256_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k);
@sodium_version(1, 0, 19)
def crypto_aead_aegis256_encrypt(message, ad, nonce, key):
if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key")

mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)

c = ctypes.create_string_buffer(mlen.value + crypto_aead_aegis256_ABYTES)
clen = ctypes.c_ulonglong(0)

__check(sodium.crypto_aead_aegis256_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
return c.raw


# crypto_aead_aegis256_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis256_decrypt(ciphertext, ad, nonce, key):
if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key")

m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_aegis256_ABYTES)
mlen = ctypes.c_ulonglong(0)
clen = ctypes.c_ulonglong(len(ciphertext))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
__check(sodium.crypto_aead_aegis256_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key))
return m.raw

# crypto_aead_aegis256_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis256_encrypt_detached(message, ad, nonce, key):
""" Return ciphertext, mac tag """
if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key")

mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
c = ctypes.create_string_buffer(mlen.value)
maclen_p = ctypes.c_ulonglong(crypto_aead_aegis256_ABYTES)
mac = ctypes.create_string_buffer(maclen_p.value)

__check(sodium.crypto_aead_aegis256_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key))
return c.raw, mac.raw

# crypto_aead_aegis256_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 19)
def crypto_aead_aegis256_decrypt_detached(ciphertext, mac, ad, nonce, key):
""" Return message if successful or -1 (ValueError) if not successful"""
if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key")
if len(mac) != crypto_aead_aegis256_ABYTES:
raise ValueError("mac length != %i" % crypto_aead_aegis256_ABYTES)

clen = ctypes.c_ulonglong(len(ciphertext))
m = ctypes.create_string_buffer(clen.value)
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
__check(sodium.crypto_aead_aegis256_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key))
return m.raw

# crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, unsigned long long *clen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k)
@sodium_version(1, 0, 4)
def crypto_aead_chacha20poly1305_ietf_encrypt(message, ad, nonce, key):
Expand All @@ -471,7 +607,7 @@ def crypto_aead_chacha20poly1305_ietf_encrypt(message, ad, nonce, key):

mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
c = ctypes.create_string_buffer(mlen.value + 16)
c = ctypes.create_string_buffer(mlen.value + crypto_aead_chacha20poly1305_ietf_ABYTES)
clen = ctypes.c_ulonglong(0)

__check(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
Expand All @@ -483,7 +619,7 @@ def crypto_aead_chacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key):
if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")

m = ctypes.create_string_buffer(len(ciphertext) - 16)
m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_chacha20poly1305_ietf_ABYTES)
mlen = ctypes.c_ulonglong(0)
clen = ctypes.c_ulonglong(len(ciphertext))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
Expand Down Expand Up @@ -531,7 +667,7 @@ def crypto_aead_xchacha20poly1305_ietf_encrypt(message, ad, nonce, key):
if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
mlen = ctypes.c_ulonglong(len(message))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
c = ctypes.create_string_buffer(mlen.value + 16)
c = ctypes.create_string_buffer(mlen.value + crypto_aead_xchacha20poly1305_ietf_ABYTES)
clen = ctypes.c_ulonglong(0)

__check(sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, ctypes.byref(clen),
Expand All @@ -550,7 +686,7 @@ def crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key):
if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: raise ValueError("truncated nonce")
if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")

m = ctypes.create_string_buffer(len(ciphertext) - 16)
m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_xchacha20poly1305_ietf_ABYTES)
mlen = ctypes.c_ulonglong(0)
clen = ctypes.c_ulonglong(len(ciphertext))
adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
Expand Down Expand Up @@ -888,10 +1024,10 @@ def crypto_box_seal_open(c, pk, sk):
return msg.raw

# int crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
# const unsigned char *m,
# unsigned long long mlen,
# const unsigned char *n,
# const unsigned char *k);
# const unsigned char *m,
# unsigned long long mlen,
# const unsigned char *n,
# const unsigned char *k);

def crypto_secretbox_detached(msg, nonce, k):
if None in (msg, nonce, k): raise ValueError("invalid parameters")
Expand Down Expand Up @@ -1404,6 +1540,59 @@ def crypto_kdf_hkdf_sha256_expand(outlen, prk, ctx=b''):
__check(sodium.crypto_kdf_hkdf_sha256_expand(out, ctypes.c_size_t(outlen), ctx, ctypes.c_size_t(len(ctx)), prk))
return out.raw

# int crypto_kdf_hkdf_sha512_extract_init(crypto_kdf_hkdf_sha512_state *state,
# const unsigned char *salt, size_t salt_len)
@sodium_version(1, 0, 20)
def crypto_kdf_hkdf_sha512_extract_init(salt=b''):
state = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_STATEBYTES)
__check(sodium.crypto_kdf_hkdf_sha512_extract_init(state, salt, ctypes.c_size_t(len(salt))))
return state

# int crypto_kdf_hkdf_sha512_extract_update(crypto_kdf_hkdf_sha512_state *state,
# const unsigned char *ikm, size_t ikm_len)
@sodium_version(1, 0, 20)
def crypto_kdf_hkdf_sha512_extract_update(state, ikm=b''):
if len(state) != crypto_kdf_hkdf_sha512_STATEBYTES: raise ValueError("invalid state")
__check(sodium.crypto_kdf_hkdf_sha512_extract_update(state, ikm, ctypes.c_size_t(len(ikm))))
return state

# int crypto_kdf_hkdf_sha512_extract_final(crypto_kdf_hkdf_sha512_state *state,
# unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
@sodium_version(1, 0, 20)
def crypto_kdf_hkdf_sha512_extract_final(state):
if len(state) != crypto_kdf_hkdf_sha512_STATEBYTES: raise ValueError("invalid state")
prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES)
__check(sodium.crypto_kdf_hkdf_sha512_extract_final(state, prk))
return prk.raw

# int crypto_kdf_hkdf_sha512_extract(
# unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES],
# const unsigned char *salt, size_t salt_len, const unsigned char *ikm,
# size_t ikm_len)
@sodium_version(1, 0, 19)
def crypto_kdf_hkdf_sha512_extract(salt=b'', ikm=b''):
prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES)
__check(sodium.crypto_kdf_hkdf_sha512_extract(prk, salt, ctypes.c_size_t(len(salt)), ikm, ctypes.c_size_t(len(ikm))))
return prk.raw

# void crypto_kdf_hkdf_sha512_keygen(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
@sodium_version(1, 0, 19)
def crypto_kdf_hkdf_sha512_keygen():
k = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES)
sodium.crypto_kdf_hkdf_sha512_keygen(k)
return k.raw

# int crypto_kdf_hkdf_sha512_expand(unsigned char *out, size_t out_len,
# const char *ctx, size_t ctx_len,
# const unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
@sodium_version(1, 0, 19)
def crypto_kdf_hkdf_sha512_expand(outlen, prk, ctx=b''):
if not (crypto_kdf_hkdf_sha512_BYTES_MIN <= outlen <= crypto_kdf_hkdf_sha512_BYTES_MAX): raise ValueError("invalid output len")
if len(prk) != crypto_kdf_hkdf_sha512_KEYBYTES: raise ValueError("invalid prk")
out = ctypes.create_string_buffer(outlen)
__check(sodium.crypto_kdf_hkdf_sha512_expand(out, ctypes.c_size_t(outlen), ctx, ctypes.c_size_t(len(ctx)), prk))
return out.raw

# int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
# unsigned char sk[crypto_kx_SECRETKEYBYTES]);
@sodium_version(1, 0, 12)
Expand Down
Loading

0 comments on commit 73a34d5

Please sign in to comment.