Generate a new Ed25519 keypair for an agent. Returns: Tuple of (private_key_pem, public_key_base64url). The private key MUST be stored securely by the agent — never sent to the server.
()
| 75 | |
| 76 | |
| 77 | def generate_agent_keypair() -> tuple[str, str]: |
| 78 | """ |
| 79 | Generate a new Ed25519 keypair for an agent. |
| 80 | |
| 81 | Returns: |
| 82 | Tuple of (private_key_pem, public_key_base64url). |
| 83 | The private key MUST be stored securely by the agent — never sent to the server. |
| 84 | """ |
| 85 | private_key = ed25519.Ed25519PrivateKey.generate() |
| 86 | public_key = private_key.public_key() |
| 87 | |
| 88 | private_bytes = private_key.private_bytes( |
| 89 | encoding=serialization.Encoding.PEM, |
| 90 | format=serialization.PrivateFormat.PKCS8, |
| 91 | encryption_algorithm=serialization.NoEncryption(), |
| 92 | ) |
| 93 | public_bytes = public_key.public_bytes( |
| 94 | encoding=serialization.Encoding.Raw, |
| 95 | format=serialization.PublicFormat.Raw, |
| 96 | ) |
| 97 | # 32 bytes -> base64url encode (no padding) |
| 98 | public_key_b64url = base64.urlsafe_b64encode(public_bytes).decode().rstrip("=") |
| 99 | return private_bytes.decode("utf-8"), public_key_b64url |
| 100 | |
| 101 | |
| 102 | # ── Signing & Verification ───────────────────────────────────────────────────── |