Skip to content

Commit

Permalink
Mypy bindings part 2 (#717)
Browse files Browse the repository at this point in the history
* Annotations for `nacl.bindings.crypto_secretstream`

Mypy couldn't see that `state.tagbuf is not None` in
`crypto_secretstream_xchacha20poly1305_pull`, so I used a cast. I
_think_ it's correct to treat this as an `Optional[bytes]`, because the
docstrings mark many cffi `unsigned char[]` types as `bytes`. I'd
appreciate a sanity check though!

* Annotations for `nacl.bindings.crypto_shorthash`

* Annotations for `nacl.bindings.crypto_sign`

* Annotations for `nacl.bindings.randombytes`

* Annotations for `nacl.bindings.sodium_core`

* Annotations for `nacl.bindings.utils`

* The `bindings` module is done
  • Loading branch information
DMRobertson committed Dec 6, 2021
1 parent 5629937 commit 910e1bb
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 66 deletions.
10 changes: 1 addition & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,7 @@ ignore_missing_imports = true
# Most options can be applied across the entire project.
[[tool.mypy.overrides]]
module = [
"nacl.bindings.crypto_aead",
"nacl.bindings.crypto_box",
"nacl.bindings.crypto_core",
"nacl.bindings.crypto_hash",
"nacl.bindings.crypto_generichash",
"nacl.bindings.crypto_kx",
"nacl.bindings.crypto_pwhash",
"nacl.bindings.crypto_scalarmult",
"nacl.bindings.crypto_secretbox",
"nacl.bindings",
"nacl.encoding",
"nacl.exceptions",
"nacl.utils",
Expand Down
64 changes: 40 additions & 24 deletions src/nacl/bindings/crypto_secretstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,45 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional, Tuple, cast

from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure


crypto_secretstream_xchacha20poly1305_ABYTES = (
crypto_secretstream_xchacha20poly1305_ABYTES: int = (
lib.crypto_secretstream_xchacha20poly1305_abytes()
)
crypto_secretstream_xchacha20poly1305_HEADERBYTES = (
crypto_secretstream_xchacha20poly1305_HEADERBYTES: int = (
lib.crypto_secretstream_xchacha20poly1305_headerbytes()
)
crypto_secretstream_xchacha20poly1305_KEYBYTES = (
crypto_secretstream_xchacha20poly1305_KEYBYTES: int = (
lib.crypto_secretstream_xchacha20poly1305_keybytes()
)
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = (
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX: int = (
lib.crypto_secretstream_xchacha20poly1305_messagebytes_max()
)
crypto_secretstream_xchacha20poly1305_STATEBYTES = (
crypto_secretstream_xchacha20poly1305_STATEBYTES: int = (
lib.crypto_secretstream_xchacha20poly1305_statebytes()
)


crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = (
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE: int = (
lib.crypto_secretstream_xchacha20poly1305_tag_message()
)
crypto_secretstream_xchacha20poly1305_TAG_PUSH = (
crypto_secretstream_xchacha20poly1305_TAG_PUSH: int = (
lib.crypto_secretstream_xchacha20poly1305_tag_push()
)
crypto_secretstream_xchacha20poly1305_TAG_REKEY = (
crypto_secretstream_xchacha20poly1305_TAG_REKEY: int = (
lib.crypto_secretstream_xchacha20poly1305_tag_rekey()
)
crypto_secretstream_xchacha20poly1305_TAG_FINAL = (
crypto_secretstream_xchacha20poly1305_TAG_FINAL: int = (
lib.crypto_secretstream_xchacha20poly1305_tag_final()
)


def crypto_secretstream_xchacha20poly1305_keygen():
def crypto_secretstream_xchacha20poly1305_keygen() -> bytes:
"""
Generate a key for use with
:func:`.crypto_secretstream_xchacha20poly1305_init_push`.
Expand All @@ -71,18 +71,20 @@ class crypto_secretstream_xchacha20poly1305_state:

__slots__ = ["statebuf", "rawbuf", "tagbuf"]

def __init__(self):
def __init__(self) -> None:
"""Initialize a clean state object."""
self.statebuf = ffi.new(
"unsigned char[]",
crypto_secretstream_xchacha20poly1305_STATEBYTES,
)

self.rawbuf = None
self.tagbuf = None
self.rawbuf: Optional[bytes] = None
self.tagbuf: Optional[bytes] = None


def crypto_secretstream_xchacha20poly1305_init_push(state, key):
def crypto_secretstream_xchacha20poly1305_init_push(
state: crypto_secretstream_xchacha20poly1305_state, key: bytes
) -> bytes:
"""
Initialize a crypto_secretstream_xchacha20poly1305 encryption buffer.
Expand Down Expand Up @@ -125,11 +127,11 @@ def crypto_secretstream_xchacha20poly1305_init_push(state, key):


def crypto_secretstream_xchacha20poly1305_push(
state,
m,
ad=None,
tag=crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
):
state: crypto_secretstream_xchacha20poly1305_state,
m: bytes,
ad: Optional[bytes] = None,
tag: int = crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
) -> bytes:
"""
Add an encrypted message to the secret stream.
Expand Down Expand Up @@ -191,7 +193,11 @@ def crypto_secretstream_xchacha20poly1305_push(
return ffi.buffer(state.rawbuf, clen)[:]


def crypto_secretstream_xchacha20poly1305_init_pull(state, header, key):
def crypto_secretstream_xchacha20poly1305_init_pull(
state: crypto_secretstream_xchacha20poly1305_state,
header: bytes,
key: bytes,
) -> None:
"""
Initialize a crypto_secretstream_xchacha20poly1305 decryption buffer.
Expand Down Expand Up @@ -240,7 +246,11 @@ def crypto_secretstream_xchacha20poly1305_init_pull(state, header, key):
ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)


def crypto_secretstream_xchacha20poly1305_pull(state, c, ad=None):
def crypto_secretstream_xchacha20poly1305_pull(
state: crypto_secretstream_xchacha20poly1305_state,
c: bytes,
ad: Optional[bytes] = None,
) -> Tuple[bytes, int]:
"""
Read a decrypted message from the secret stream.
Expand Down Expand Up @@ -317,10 +327,16 @@ def crypto_secretstream_xchacha20poly1305_pull(state, c, ad=None):
)
ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)

return (ffi.buffer(state.rawbuf, mlen)[:], int(state.tagbuf[0]))
# Cast safety: we `ensure` above that `state.tagbuf is not None`.
return (
ffi.buffer(state.rawbuf, mlen)[:],
int(cast(bytes, state.tagbuf)[0]),
)


def crypto_secretstream_xchacha20poly1305_rekey(state):
def crypto_secretstream_xchacha20poly1305_rekey(
state: crypto_secretstream_xchacha20poly1305_state,
) -> None:
"""
Explicitly change the encryption key in the stream.
Expand Down
8 changes: 4 additions & 4 deletions src/nacl/bindings/crypto_shorthash.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
lib.PYNACL_HAS_CRYPTO_SHORTHASH_SIPHASHX24
)

BYTES = lib.crypto_shorthash_siphash24_bytes()
KEYBYTES = lib.crypto_shorthash_siphash24_keybytes()
BYTES: int = lib.crypto_shorthash_siphash24_bytes()
KEYBYTES: int = lib.crypto_shorthash_siphash24_keybytes()

XBYTES = 0
XKEYBYTES = 0
Expand All @@ -33,7 +33,7 @@
XKEYBYTES = lib.crypto_shorthash_siphashx24_keybytes()


def crypto_shorthash_siphash24(data, key):
def crypto_shorthash_siphash24(data: bytes, key: bytes) -> bytes:
"""Compute a fast, cryptographic quality, keyed hash of the input data
:param data:
Expand All @@ -53,7 +53,7 @@ def crypto_shorthash_siphash24(data, key):
return ffi.buffer(digest, BYTES)[:]


def crypto_shorthash_siphashx24(data, key):
def crypto_shorthash_siphashx24(data: bytes, key: bytes) -> bytes:
"""Compute a fast, cryptographic quality, keyed hash of the input data
:param data:
Expand Down
46 changes: 26 additions & 20 deletions src/nacl/bindings/crypto_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,25 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Tuple

from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure


crypto_sign_BYTES = lib.crypto_sign_bytes()
crypto_sign_BYTES: int = lib.crypto_sign_bytes()
# crypto_sign_SEEDBYTES = lib.crypto_sign_seedbytes()
crypto_sign_SEEDBYTES = lib.crypto_sign_secretkeybytes() // 2
crypto_sign_PUBLICKEYBYTES = lib.crypto_sign_publickeybytes()
crypto_sign_SECRETKEYBYTES = lib.crypto_sign_secretkeybytes()
crypto_sign_SEEDBYTES: int = lib.crypto_sign_secretkeybytes() // 2
crypto_sign_PUBLICKEYBYTES: int = lib.crypto_sign_publickeybytes()
crypto_sign_SECRETKEYBYTES: int = lib.crypto_sign_secretkeybytes()

crypto_sign_curve25519_BYTES = lib.crypto_box_secretkeybytes()
crypto_sign_curve25519_BYTES: int = lib.crypto_box_secretkeybytes()

crypto_sign_ed25519ph_STATEBYTES = lib.crypto_sign_ed25519ph_statebytes()
crypto_sign_ed25519ph_STATEBYTES: int = lib.crypto_sign_ed25519ph_statebytes()


def crypto_sign_keypair():
def crypto_sign_keypair() -> Tuple[bytes, bytes]:
"""
Returns a randomly generated public key and secret key.
Expand All @@ -47,7 +47,7 @@ def crypto_sign_keypair():
)


def crypto_sign_seed_keypair(seed):
def crypto_sign_seed_keypair(seed: bytes) -> Tuple[bytes, bytes]:
"""
Computes and returns the public key and secret key using the seed ``seed``.
Expand All @@ -69,7 +69,7 @@ def crypto_sign_seed_keypair(seed):
)


def crypto_sign(message, sk):
def crypto_sign(message: bytes, sk: bytes) -> bytes:
"""
Signs the message ``message`` using the secret key ``sk`` and returns the
signed message.
Expand All @@ -87,7 +87,7 @@ def crypto_sign(message, sk):
return ffi.buffer(signed, signed_len[0])[:]


def crypto_sign_open(signed, pk):
def crypto_sign_open(signed: bytes, pk: bytes) -> bytes:
"""
Verifies the signature of the signed message ``signed`` using the public
key ``pk`` and returns the unsigned message.
Expand All @@ -108,7 +108,7 @@ def crypto_sign_open(signed, pk):
return ffi.buffer(message, message_len[0])[:]


def crypto_sign_ed25519_pk_to_curve25519(public_key_bytes):
def crypto_sign_ed25519_pk_to_curve25519(public_key_bytes: bytes) -> bytes:
"""
Converts a public Ed25519 key (encoded as bytes ``public_key_bytes``) to
a public Curve25519 key as bytes.
Expand All @@ -133,7 +133,7 @@ def crypto_sign_ed25519_pk_to_curve25519(public_key_bytes):
return ffi.buffer(curve_public_key, curve_public_key_len)[:]


def crypto_sign_ed25519_sk_to_curve25519(secret_key_bytes):
def crypto_sign_ed25519_sk_to_curve25519(secret_key_bytes: bytes) -> bytes:
"""
Converts a secret Ed25519 key (encoded as bytes ``secret_key_bytes``) to
a secret Curve25519 key as bytes.
Expand All @@ -158,7 +158,7 @@ def crypto_sign_ed25519_sk_to_curve25519(secret_key_bytes):
return ffi.buffer(curve_secret_key, curve_secret_key_len)[:]


def crypto_sign_ed25519_sk_to_pk(secret_key_bytes):
def crypto_sign_ed25519_sk_to_pk(secret_key_bytes: bytes) -> bytes:
"""
Extract the public Ed25519 key from a secret Ed25519 key (encoded
as bytes ``secret_key_bytes``).
Expand All @@ -175,7 +175,7 @@ def crypto_sign_ed25519_sk_to_pk(secret_key_bytes):
return secret_key_bytes[crypto_sign_SEEDBYTES:]


def crypto_sign_ed25519_sk_to_seed(secret_key_bytes):
def crypto_sign_ed25519_sk_to_seed(secret_key_bytes: bytes) -> bytes:
"""
Extract the seed from a secret Ed25519 key (encoded
as bytes ``secret_key_bytes``).
Expand All @@ -199,8 +199,8 @@ class crypto_sign_ed25519ph_state:

__slots__ = ["state"]

def __init__(self):
self.state = ffi.new(
def __init__(self) -> None:
self.state: bytes = ffi.new(
"unsigned char[]", crypto_sign_ed25519ph_STATEBYTES
)

Expand All @@ -209,7 +209,9 @@ def __init__(self):
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)


def crypto_sign_ed25519ph_update(edph, pmsg):
def crypto_sign_ed25519ph_update(
edph: crypto_sign_ed25519ph_state, pmsg: bytes
) -> None:
"""
Update the hash state wrapped in edph
Expand All @@ -233,7 +235,9 @@ def crypto_sign_ed25519ph_update(edph, pmsg):
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)


def crypto_sign_ed25519ph_final_create(edph, sk):
def crypto_sign_ed25519ph_final_create(
edph: crypto_sign_ed25519ph_state, sk: bytes
) -> bytes:
"""
Create a signature for the data hashed in edph
using the secret key sk
Expand Down Expand Up @@ -272,7 +276,9 @@ def crypto_sign_ed25519ph_final_create(edph, sk):
return ffi.buffer(signature, crypto_sign_BYTES)[:]


def crypto_sign_ed25519ph_final_verify(edph, signature, pk):
def crypto_sign_ed25519ph_final_verify(
edph: crypto_sign_ed25519ph_state, signature: bytes, pk: bytes
) -> bool:
"""
Verify a prehashed signature using the public key pk
Expand Down
4 changes: 2 additions & 2 deletions src/nacl/bindings/randombytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
from nacl import exceptions as exc
from nacl._sodium import ffi, lib

randombytes_SEEDBYTES = lib.randombytes_seedbytes()
randombytes_SEEDBYTES: int = lib.randombytes_seedbytes()


def randombytes(size):
def randombytes(size: int) -> bytes:
"""
Returns ``size`` number of random bytes from a cryptographically secure
random source.
Expand Down
4 changes: 2 additions & 2 deletions src/nacl/bindings/sodium_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
from nacl.exceptions import ensure


def _sodium_init():
def _sodium_init() -> None:
ensure(
lib.sodium_init() != -1,
"Could not initialize sodium",
raising=exc.RuntimeError,
)


def sodium_init():
def sodium_init() -> None:
"""
Initializes sodium, picking the best implementations available for this
machine.
Expand Down

0 comments on commit 910e1bb

Please sign in to comment.