Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: opt-in V2-only records, IPIP-428 verification #234

Merged
merged 14 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 26 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipns.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipns)
[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipns/js-test-and-release.yml?branch=master\&style=flat-square)](https://github.com/ipfs/js-ipns/actions/workflows/js-test-and-release.yml?query=branch%3Amaster)

> ipns record definitions
> IPNS Record definitions

## Table of contents <!-- omit in toc -->

Expand Down Expand Up @@ -54,15 +54,15 @@ This module contains all the necessary code for creating, understanding and vali
```js
import * as ipns from 'ipns'

const entryData = await ipns.create(privateKey, value, sequenceNumber, lifetime)
const ipnsRecord = await ipns.create(privateKey, value, sequenceNumber, lifetime)
```

### Validate record

```js
import * as ipns from 'ipns'

await ipns.validate(publicKey, ipnsEntry)
await ipns.validate(publicKey, marshalledData)
// if no error thrown, the record is valid
```

Expand All @@ -71,15 +71,15 @@ await ipns.validate(publicKey, ipnsEntry)
```js
import * as ipns from 'ipns'

const ipnsEntryWithEmbedPublicKey = await ipns.embedPublicKey(publicKey, ipnsEntry)
const ipnsRecordWithEmbeddedPublicKey = await ipns.embedPublicKey(publicKey, ipnsRecord)
```

### Extract public key from record

```js
import * as ipns from 'ipns'

const publicKey = await ipns.extractPublicKey(peerId, ipnsEntry)
const publicKey = await ipns.extractPublicKey(peerId, ipnsRecord)
```

### Datastore key
Expand All @@ -90,7 +90,7 @@ import * as ipns from 'ipns'
ipns.getLocalKey(peerId)
```

Returns a key to be used for storing the ipns entry locally, that is:
Returns a key to be used for storing the IPNS record locally, that is:

```
/ipns/${base32(<HASH>)}
Expand All @@ -101,23 +101,23 @@ Returns a key to be used for storing the ipns entry locally, that is:
```js
import * as ipns from 'ipns'

const entryData = await ipns.create(privateKey, value, sequenceNumber, lifetime)
const ipnsRecord = await ipns.create(privateKey, value, sequenceNumber, lifetime)
// ...
const marshalledData = ipns.marshal(entryData)
const marshalledData = ipns.marshal(ipnsRecord)
// ...
```

Returns the entry data serialized.
Returns the record data serialized.

### Unmarshal data from proto buffer

```js
import * as ipns from 'ipns'

const data = ipns.unmarshal(storedData)
const ipnsRecord = ipns.unmarshal(storedData)
```

Returns the entry data structure after being serialized.
Returns the `IPNSRecord` after being deserialized.

### Validator

Expand All @@ -131,81 +131,70 @@ Contains an object with `validate (marshalledData, key)` and `select (dataA, dat

The `validate` async function aims to verify if an IPNS record is valid. First the record is unmarshalled, then the public key is obtained and finally the record is validated (`signatureV2` of CBOR `data` is verified).

The `select` function is responsible for deciding which ipns record is the best (newer) between two records. Both records are unmarshalled and their sequence numbers are compared. If the first record provided is the newer, the operation result will be `0`, otherwise the operation result will be `1`.
The `select` function is responsible for deciding which IPNS record is the best (newer) between two records. Both records are unmarshalled and their sequence numbers are compared. If the first record provided is the newer, the operation result will be `0`, otherwise the operation result will be `1`.

## API

### Create record

```js

ipns.create(privateKey, value, sequenceNumber, lifetime)
ipns.create(privateKey, value, sequenceNumber, lifetime, options)
```

Create an IPNS record for being stored in a protocol buffer.

- `privateKey` (`PrivKey` [RSA Instance](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/rsa-class.js)): key to be used for cryptographic operations.
- `value` (Uint8Array): ipfs path of the object to be published.
- `value` (string): IPFS path of the object to be published.
- `sequenceNumber` (Number): number representing the current version of the record.
- `lifetime` (Number): lifetime of the record (in milliseconds).
- `options` (CreateOptions): additional creation options.

Returns a `Promise` that resolves to an object with the entry's properties eg:

```js
{
value: Uint8Array,
signature: Uint8Array, // V1 (legacy, ignored)
validityType: 0,
validity: Uint8Array,
sequence: 2,
signatureV2: Uint8Array, // V2 signature of data field
data: Uint8Array // DAG-CBOR that was signed
}
```
Returns a `Promise` that resolves to an object with a `IPNSRecord`.

### Validate record

```js
ipns.validate(publicKey, ipnsEntry)
ipns.validate(publicKey, ipnsRecord)
```

Validate an IPNS record previously stored in a protocol buffer.

- `publicKey` (`PubKey` [RSA Instance](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/rsa-class.js)): key to be used for cryptographic operations.
- `ipnsEntry` (Object): ipns entry record (obtained using the create function).
- `ipnsRecord` (`IPNSRecord`): IPNS record (obtained using the create function).

Returns a `Promise`, which may be rejected if the validation was not successful.

### Marshal data with proto buffer

```js
const marshalledData = ipns.marshal(entryData)
const marshalledData = ipns.marshal(ipnsRecord)
```

Returns the entry data serialized.
Returns the serialized IPNS record.

- `entryData` (Object): ipns entry record (obtained using the create function).
- `ipnsRecord` (`IPNSRecord`): ipns record (obtained using the create function).

### Unmarshal data from proto buffer

```js
const data = ipns.unmarshal(storedData)
```

Returns the entry data structure after being serialized.
Returns a `IPNSRecord` after being serialized.

- `storedData` (Uint8Array): ipns entry record serialized.
- `storedData` (Uint8Array): ipns record serialized.

### Extract public key from record

```js
const publicKey = await ipns.extractPublicKey(peerId, ipnsEntry)
const publicKey = await ipns.extractPublicKey(peerId, ipnsRecord)
```

Extract a public key from an IPNS entry.
Extract a public key from an IPNS record.

- `peerId` (`PeerId` [Instance](https://github.com/libp2p/js-libp2p-peer-id/tree/master/packages/libp2p-peer-id)): peer identifier object.
- `ipnsEntry` (Object): ipns entry record (obtained using the create function).
- `ipnsRecord` (`IPNSRecord`): ipns record (obtained using the create function).

Returns a `Promise` which resolves to public key ([`PublicKey`](https://github.com/libp2p/js-libp2p-interfaces/blob/master/packages/interface-keys/src/index.ts) ): may be used for cryptographic operations.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ipns",
"version": "6.0.7",
"description": "ipns record definitions",
"description": "IPNS record definitions",
"author": "Vasco Santos <[email protected]>",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/js-ipns#readme",
Expand Down
1 change: 1 addition & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const ERR_PEER_ID_FROM_PUBLIC_KEY = 'ERR_PEER_ID_FROM_PUBLIC_KEY'
export const ERR_PUBLIC_KEY_FROM_ID = 'ERR_PUBLIC_KEY_FROM_ID'
export const ERR_UNDEFINED_PARAMETER = 'ERR_UNDEFINED_PARAMETER'
export const ERR_INVALID_RECORD_DATA = 'ERR_INVALID_RECORD_DATA'
export const ERR_INVALID_VALUE = 'ERR_INVALID_VALUE'
export const ERR_INVALID_EMBEDDED_KEY = 'ERR_INVALID_EMBEDDED_KEY'
export const ERR_MISSING_PRIVATE_KEY = 'ERR_MISSING_PRIVATE_KEY'
export const ERR_RECORD_TOO_LARGE = 'ERR_RECORD_TOO_LARGE'
Loading