objective categorical abstract machine language personal data server
1# kleidos
2
3is an atproto-valid interface for secp256k1 and secp256r1 (P-256) key management, signing, verification, and encoding.
4
5The library provides a unified interface for working with both elliptic curves used in atproto, with support for multikey encoding and did:key generation.
6
7## installation
8
9Add to your `dune-project`:
10
11```lisp
12(depends
13 kleidos)
14```
15
16## usage
17
18Both K-256 and P-256 share the same interface through the `CURVE` module type.
19
20### generating keys
21
22```ocaml
23open Kleidos
24
25(* Generate a K-256 keypair *)
26let (privkey, pubkey) = K256.generate_keypair ()
27
28(* Generate a P-256 keypair *)
29let (privkey, pubkey) = P256.generate_keypair ()
30```
31
32### signing and verifying
33
34```ocaml
35(* Sign a message *)
36let msg = Bytes.of_string "Hello, atproto!" in
37let signature = K256.sign ~privkey ~msg
38
39(* Verify a signature *)
40let is_valid = K256.verify ~pubkey ~msg ~signature
41(* => true *)
42```
43
44### key encoding
45
46```ocaml
47(* Convert keys to multikey format *)
48let privkey_multikey = K256.privkey_to_multikey privkey
49(* => "z2MkApQ..." *)
50
51let pubkey_multikey = K256.pubkey_to_multikey pubkey
52(* => "zQ3sh..." *)
53
54(* Generate a DID key *)
55let did_key = K256.pubkey_to_did_key pubkey
56(* => "did:key:zQ3sh..." *)
57```
58
59### deriving public keys
60
61```ocaml
62(* Derive public key from private key *)
63let pubkey = K256.derive_pubkey ~privkey
64```
65
66### key validation
67
68```ocaml
69(* Check if a private key is valid *)
70let is_valid = K256.is_valid_privkey privkey
71```
72
73## implementation details
74
75- Implements [RFC 6979](https://datatracker.ietf.org/doc/html/rfc6979) for deterministic signature generation
76- Implements low-S normalization to prevent signature malleability
77- All signatures are deterministic given the same private key and message