# `KeyPair` — Ed25519 Signing Keys

`pollyweb.keypair` provides the Ed25519 key material used by [`Domain`](domain.md) and [`Msg`](msg.md): a private signing key plus its derived public verification key.

**See also:** [`DNS`](dns.md), [`Domain`](domain.md), [`Msg`](msg.md)

---

## Quick start

```python
import pollyweb as pw

pair = pw.KeyPair()  # generates a fresh Ed25519 private key

msg = pw.Msg(To="receiver.dom", Subject="Hello@Host", Body={"text": "hi"})
domain = pw.Domain(Name="sender.dom", KeyPair=pair, Selector="pw1")
dns_record = domain.dns()
signed = domain.sign(msg)

signed.verify(pair.PublicKey)  # True
```

To export PEM files:

```python
private_pem = pair.private_pem_bytes()
public_pem = pair.public_pem_bytes()
```

You can also wrap an existing Ed25519 private key:

```python
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
import pollyweb as pw

existing = Ed25519PrivateKey.generate()
pair = pw.KeyPair(PrivateKey=existing)
```

---

## `KeyPair` fields

`KeyPair` is a dataclass with one stored field and one derived property.

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `PrivateKey` | `Ed25519PrivateKey` | — | auto-generated | The Ed25519 private key used for signing. If omitted, a fresh key is generated on construction. |

Each `KeyPair()` instance generates a new private key by default, so separate instances do not share key material.

---

## Properties

### `pair.PublicKey → Ed25519PublicKey`

Returns the public key derived from `PrivateKey`.

This is a computed property, not a constructor argument. It is typically used to validate signed messages without DNS lookup:

```python
signed.verify(pair.PublicKey)
```

The returned public key is equivalent to:

```python
pair.PrivateKey.public_key()
```

---

## Methods

- [`pair.dkim(v="DKIM1") → str`](keypair/dkim.md) — returns the DKIM TXT payload for the current public key.
- [`pair.private_pem_bytes() → bytes`](keypair/private_pem_bytes.md) — exports the private key as unencrypted PKCS#8 PEM.
- [`pair.public_pem_bytes() → bytes`](keypair/public_pem_bytes.md) — exports the public key as SubjectPublicKeyInfo PEM.

---

## Design notes

**Generated by default** — `KeyPair()` creates a fresh Ed25519 private key automatically, which makes it convenient for tests and initial setup.

**Public key is derived, not stored separately** — `PublicKey` is computed from `PrivateKey`, so the pair cannot drift out of sync.

**DNS export is raw-key based** — `dkim()` serialises the Ed25519 public key in raw form and base64-encodes it for the `p=` tag, matching the format expected by `Msg.verify()` when resolving keys from DNS.

**PEM export is part of the keypair API** — use `private_pem_bytes()` and `public_pem_bytes()` instead of re-implementing `cryptography` serialization at call sites.
