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