OverviewFilesCommitsIssuesDocsReleasesPeers

anproto commits / 7b51f8e

README: the repo had none
Written from the source, not from memory: exports and method names come from index.js and lib/, the usage example mirrors examples/cli.js, and the test count is one I ran. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7b51f8e7faedd6db811cfe91d1fb60d6258a60d0
by plankatron <fleeky@gmail.com> · 2026-09-10T15:40:19.000Z

Changed files (1) +84 -0

README.md +84 -0
……@@ -0,0 +1,84 @@
1# anproto
2
3Wire-compatible implementation of [evbogue](https://github.com/evbogue)'s **ANProto** —
4Authenticated Non-networked Protocol. Ed25519 signatures over hashed, timestamped messages,
5with no transport of its own.
6
7Non-networked is the point: ANProto says how a message is signed and opened, and nothing about
8how it travels. Carry it over Hypercore, HTTP, a QR code or a piece of paper.
9
10## Install
11
12```sh
13npm install anproto
14```
15
16## Usage
17
18```js
19import { an } from 'anproto'
20
21const keypair = await an.gen() // a new Ed25519 keypair
22const hash = await an.hash('hello world') // hash the payload
23const signed = await an.sign(hash, keypair) // sign it
24const opened = await an.open(signed) // verify + unwrap
25const { author, timestamp, data } = an.parse(opened)
26```
27
28`an.open()` throws on a bad signature rather than returning false — an unopenable message is
29not a value you should be able to carry around by accident.
30
31## API
32
33#### `await an.gen() -> keypair`
34
35A new Ed25519 keypair, as a 132-character string.
36
37#### `await an.hash(data) -> hash`
38
39Hash a payload.
40
41#### `await an.sign(hash, keypair) -> message`
42
43Sign a hash with a keypair. Returns the ANProto envelope.
44
45#### `await an.open(message) -> opened`
46
47Verify the signature and unwrap. **Throws** on an invalid signature, a wrong pubkey length,
48or a malformed envelope.
49
50#### `an.parse(opened) -> { author, timestamp, data }`
51
52Split an opened message into its fields. Synchronous.
53
54### Challenges
55
56A replay guard: issue a nonce, accept it exactly once.
57
58```js
59import { Challenges } from 'anproto'
60
61const challenges = new Challenges()
62const c = challenges.generate() // issue a nonce
63challenges.has(c) // true
64challenges.consume(c) // true, once
65challenges.consume(c) // false — already spent
66challenges.destroy() // stop the expiry timer
67```
68
69`destroy()` matters: `Challenges` runs a cleanup timer, and a process will not exit while it
70is alive.
71
72## Test
73
74```sh
75npm test # 14/14
76```
77
78## Used by
79
80`wirecore`, for content-by-hash feeds.
81
82## License
83
84Not yet declared.