Metadata-Version: 2.4
Name: minizign
Version: 0.0.2
Summary: a native cpython extension for minisign using zig
Author-email: Tobias Simetsreiter <dasimmet@gmail.com>
Maintainer-email: Tobias Simetsreiter <dasimmet@gmail.com>
License-Expression: MIT
Keywords: zig,ziglang,cpython,native,sdist,minisign,minisign-zig
Requires-Python: >=3.9
Project-URL: Homepage, https://codeberg.org/dasimmet/minizign
Project-URL: Issues, https://codeberg.org/dasimmet/minizign/issues
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Zig
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Description-Content-Type: text/markdown

# minizign

Fast, lightweight Python bindings for the Zig [minisign](https://jedisct1.github.io/minisign/) implementation.

`minizign` provides high-performance cryptographic signing and verification using Ed25519 and Blake2b-512 with full Minisign format compatibility.

---

## Features

- **Standard Minisign Compatibility**: Interoperable with official `minisign` files, keys, and signatures.
- **Multiple Input Types**: Sign and verify `str`, `bytes`, `bytearray`, `memoryview`, integer file descriptors (`int`), and file-like objects.
- **Streaming Hashing**: Fast chunked hashing (Blake2b-512) for large files and file descriptors without loading entire files into memory.
- **Direct Output Writing**: Write signatures and keys directly to integer file descriptors or file-like streams.
- **Full Comment Support**: Custom trusted comments and untrusted comments on signatures, public keys, and secret keys.
- **Type Annotations**: Fully typed with PEP 561 `.pyi` stubs.

---

## Installation

```bash
pip install minizign
```

---

## Quickstart

### Keypair Generation

```python
import minizign

# Generate a new random secret key
sk = minizign.SecretKey(untrusted_comment="my secret key")

# Derive the corresponding public key
pk = sk.getPublicKey(untrusted_comment="my public key")

# Export keys as Minisign formatted strings
sk_str = sk.toString()
pk_str = pk.toString()

print("Public Key:")
print(pk_str)
```

### Signing and Verifying Data

```python
import minizign

sk = minizign.SecretKey()
pk = sk.getPublicKey()

# Sign a string or bytes
message = "Hello, world!"
sig = sk.sign(
    message,
    trusted_comment="trusted timestamp",
    untrusted_comment="signature from minizign"
)

# Verify with PublicKey or Signature object
is_valid = pk.verify(message, sig)
print("Valid:", is_valid)  # True

# Verify using top-level helper
print("Valid:", minizign.verify(message, sig, pk))  # True
```

### Signing Files and File Descriptors (Streaming)

```python
import os
import minizign

sk = minizign.SecretKey()
pk = sk.getPublicKey()

# Sign a file stream directly
with open("large_dataset.tar.gz", "rb") as f:
    sig = sk.sign(f, trusted_comment="release archive")

# Verify with file object
with open("large_dataset.tar.gz", "rb") as f:
    assert pk.verify(f, sig)

# Sign using an OS file descriptor and write signature directly to another fd
fd_in = os.open("document.pdf", os.O_RDONLY)
fd_out = os.open("document.pdf.minisig", os.O_WRONLY | os.O_CREAT | os.O_TRUNC)

sig = sk.sign(fd_in, out=fd_out, trusted_comment="approved")

os.close(fd_in)
os.close(fd_out)
```

### Loading Keys and Signatures

```python
import minizign

# Load from serialized strings
pk = minizign.PublicKey("untrusted comment: minisign public key\nRWR...\n")
sig = minizign.Signature("untrusted comment: ...\n...\ntrusted comment: ...\n...\n")

# Load from file or file descriptor
with open("minisign.pub", "r") as f:
    pk_from_file = minizign.PublicKey(f)

# Inspect properties
print(sig.trusted_comment)
print(sig.untrusted_comment)
print(sig.signature)        # 64 bytes
print(sig.global_signature) # 64 bytes
print(sig.key_id)           # 8 bytes
```

---

## API Reference

### Module Functions

- **`minizign.sign(secret_key, message, trusted_comment=None, untrusted_comment=None, out=None, timestamp=None) -> Signature`**  
  Sign a message with a `SecretKey`. Output can optionally be written to a file descriptor or file object. A custom `timestamp` (`int`, `float`, or `str`) can be supplied.

- **`minizign.verify(message, signature, public_key) -> bool`**  
  Verify a signature against a message and a `PublicKey`.

### `SecretKey`
- **`SecretKey(str=None, *, untrusted_comment=None, comment=None)`**: Generate a new random key or load from input (`str`, `bytes`, `int` fd, or file object).
- **`sk.getPublicKey(untrusted_comment=None, *, comment=None) -> PublicKey`**: Extract the corresponding public key.
- **`sk.sign(message, trusted_comment=None, untrusted_comment=None, out=None, timestamp=None) -> Signature`**: Sign `message` (`str`, `bytes`, `bytearray`, `memoryview`, `int` fd, or file).
- **`sk.signBytes(data, ...)`** / **`sk.signString(message, ...)`**: Aliases for `sign`.
- **`sk.toString(out=None, *, untrusted_comment=None, comment=None) -> Optional[str]`**: Format as serialized Minisign secret key string or write to `out`.
- **`sk.write(out, *, untrusted_comment=None, comment=None) -> None`**: Write secret key to an output destination.
- **Properties**: `untrusted_comment`, `comment`, `key_id`, `secret_key`.

### `PublicKey`
- **`PublicKey(str=None, *, untrusted_comment=None, comment=None)`**: Load a public key from string, bytes, file descriptor, or file.
- **`pk.verify(message, signature) -> bool`**: Verify a signature against a message (`str`, `bytes`, `bytearray`, `memoryview`, `int` fd, or file).
- **`pk.verifyString(message, signature) -> bool`**: Alias for `verify`.
- **`pk.toString(out=None, *, untrusted_comment=None, comment=None) -> Optional[str]`**: Format as Minisign public key string or write to `out`.
- **`pk.write(out, *, untrusted_comment=None, comment=None) -> None`**: Write public key to an output destination.
- **Properties**: `untrusted_comment`, `comment`, `key_id`, `key`, `public_key`.

### `Signature`
- **`Signature(str=None, *, untrusted_comment=None, comment=None)`**: Parse a signature from string, bytes, file descriptor, or file.
- **`sig.verify(message, public_key) -> bool`**: Verify this signature against a message and public key.
- **`sig.toString(out=None) -> Optional[str]`**: Format as Minisign signature string or write to `out`.
- **`sig.write(out) -> None`**: Write signature to an output destination.
- **Properties**: `trusted_comment`, `untrusted_comment`, `comment`, `signature`, `global_signature`, `key_id`.

---

## License

MIT / Apache-2.0
