Code Monkey home page Code Monkey logo

js-did-ipid's Introduction

did-ipid

NPM version Downloads Build Status Coverage Status Dependency status Dev Dependency status

The IPID DID method implementation in JavaScript.

Installation

$ npm install did-ipid

This library is written in modern JavaScript and is published in both CommonJS and ES module transpiled variants. If you target older browsers please make sure to transpile accordingly.

Usage

import createIpid, { getDid } from 'did-ipid';

const did = await getDid(pem);
//=> Returns the DID associated to a private key in PEM format.

const ipid = await createIpid(ipfs);

const didDocument = await ipid.resolve('did:ipid:QmUTE4cxTxihntPEFqTprgbqyyS9YRaRcC8FXp6PACEjFG');
//=> Resolves a DID and returns the respective DID Document.

const didDocument = await ipid.create(pem, (document) => {
    const publicKey = document.addPublicKey({
    	type: 'RsaVerificationKey2018',
        publicKeyHex: '02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71',
    });

    const authentication = document.addAuthentication(publicKey.id);

    const service = document.addService({
    	id: 'hub',
    	type: 'HubService',
    	serviceEndpoint: 'https://hub.example.com/',
    });
});
//=> Creates a new DID and the corresponding DID Document based on the provided private key pem.
//=> The DID Document is published with the added publicKey, authentication and service.

const didDocument = await ipid.update(pem, (document) => {
    document.removeService('hub');

    document.addService({
    	id: 'messages',
    	type: 'MessagingService',
    	serviceEndpoint: 'https://example.com/messages/8377464',
    });
});
//=> Updates a DID Document based on the DID associated to the provided private key pem.
//=> The DID Document is published without the `hub` service and with a new one called `messages`. 

API

getDid(pem)

Returns the DID associated to a private key in PEM format.

pem

Type: string

A private key in PEM format.

Supported formats: pkcs1-pem or pkcs8-pem.

Example:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDCQZyRCPMcBPL2J2SuI2TduR7sy28wmcRzfj8fXQTbj1zJURku
...
-----END RSA PRIVATE KEY-----

IPID

An IPFS node is required to create an IPID instance. Please be sure to check js-ipfs, the JavaScript implementation of the IPFS protocol, to learn how to create one.

There is currently only one option available during the creation of an IPID instance. The lifetime option defines the duration of the DID document availability.

Example:

import createIpid from 'did-ipid';

const ipid = await createIpid(ipfs, { lifetime: '24h' });

Notes:

  • Please make sure that the IPFS node is ready to use.
  • This package uses the Key Management provided by IPFS. So during the creation of the node a password must be defined, as an option, to encrypt/decrypt your keys.

resolve(did)

Resolves a DID and provides the respective DID Document.

Returns a Promise that resolves to the DID Document.

did

Type: string

The DID to resolve.

Example:

did:ipid:QmUTE4cxTxihntPEFqTprgbqyyS9YRaRcC8FXp6PACEjFG

create(privateKeyPem, operations)

Creates a new DID and respective DID Document by applying all the specified operations.

Returns a Promise that resolves to the DID Document.

privateKeyPem

Type: string

A private key in PEM format.

Example:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDCQZyRCPMcBPL2J2SuI2TduR7sy28wmcRzfj8fXQTbj1zJURku
...
-----END RSA PRIVATE KEY-----
operations

Type: Function

A function that receives a Document instance that provides methods to modify its content.

update(privateKeyPem, operations)

Updates an existing DID Document by applying all the specified operations.

Returns a Promise that resolves to the DID Document.

privateKeyPem

Type: string

A private key in PEM format.

Example:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDCQZyRCPMcBPL2J2SuI2TduR7sy28wmcRzfj8fXQTbj1zJURku
...
-----END RSA PRIVATE KEY-----
operations

Type: Function

A function that receives a Document instance that provides methods to modify its content.

Document

getContent()

Returns the current state of the documents content.

addPublicKey(publicKey, [options])

Adds a new Public Key to the document.

Returns the added public key.

publicKey

Type: Object

An object with all the Public Key required properties as defined in the DID Public Keys spec.

  • id should be provided without a prefixed did.
  • If no id is provided, one will be generated.
  • If no controller is provided, it is assumed that it is its own DID.
options

Type: Object

Options to be used while adding a public key.

idPrefix

Type: string

A prefix to be added to the public key id.

revokePublicKey(id)

Revokes a Public Key from the document.

Also revokes an authentication that references this public key.

id

Type: string

The id of the public key.

addAuthentication(authentication)

Adds a new Authentication to the document.

Returns the added authentication.

authentication

Type: string

The id of the public key that is being referenced.

removeAuthentication(id)

Revokes an Authentication from the document.

id

Type: string

The id authentication.

addService(service, [options])

Adds a new Service Endpoint to the document.

Returns the added service.

service

Type: Object

An object with all the Service Endpoint required properties as defined in the DID Service Endpoints spec.

  • id should be provided without a prefixed did.
  • If no id is provided, one will be generated.
options

Type: Object

Options to be used while adding a service.

idPrefix

Type: string

A prefix to be added to the service id.

removeService(id)

Revokes a Service Endpoint from the document.

id

Type: string

The id of the service endpoint.

Tests

$ npm test
$ npm test -- --watch # during development

License

Released under the MIT License.

js-did-ipid's People

Contributors

paulobmarcos avatar satazor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-did-ipid's Issues

Add proof

Proof

proof is an optional document property that represents the cryptographic proof of the integrity of the DID Document.

The rules for a proof are:

  1. A DID Document MAY have exactly one property representing a proof.
  2. The key for this property MUST be proof.
  3. The value of this key MUST be a valid JSON-LD proof as defined by Linked Data Proofs.

Unable to create did document in my local IPFS instance

Hi, i would like create an DID document in my local IPFS instance.
here is my code to achieve this

    const ipfsClient = require('ipfs-http-client');
    const ipfs = ipfsClient({ host: 'localhost', port: '5001', protocol: 'http' });
    const ipid = require('did-ipid');
    const createIpid = ipid.default;
    const _ipid = await createIpid(ipfs);
    const didDocument = await _ipid.create(< privateKey_in_pem_format >, (document) => {
            document.addPublicKey({
                id: 'idm-master',
                type: 'RsaVerificationKey2018',
                publicKeyPem: <public_key>
            });
      });

while doing so, getting below error:

{ HTTPError: 404 page not found
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  name: 'HTTPError',
  response:
   Response {
     size: 0,
     timeout: 0,
     [Symbol(Body internals)]: { body: [PassThrough], disturbed: true, error: null },
     [Symbol(Response internals)]:
      { url:
         'http://localhost:5001/api/v0/key/import?arg=js-ipid-vnor04wt66n&pem=-----BEGIN+PRIVATE+KEY-----%0A<private_key_in_pem>%0A-----END+PRIVATE+KEY-----%0A',
        status: 404,
        statusText: 'Not Found',
        headers: [Headers],
        counter: undefined } } }

for some reason %0A characters have been added.

Please help me out in fixing this by telling what went wrong

Issue adding/resolving DID Docs

Hey,

I'm trying to create and add a DID Doc but it seems like it's not being added to the network. Maybe you can help me find the issue.

I got a node.js express server setup with the following code to create a did

var did = require('did-ipid');
...
ipid = did.default(ipfsNode, {lifetime: '24h'}); //IPFS.create({repo: "ipfs-server", pass: "}{.&PWPWPWPWPWPWPW000000"})
...
router.get('/register', function (req, res) { 
    let rsaKeyPair = generateRsaKeyPair(); //generates rsa keys with crypto 
    ipid.create(rsaKeyPair.privateKey, (document) => {
        const publicKey = document.addPublicKey({
            type: 'RsaVerificationKey2018',
            publicKeyHex: rsaKeyPair.publicKey
        }); 

        const authentication = document.addAuthentication(publicKey.id);

        const service = document.addService({
            id: 'hub',
            type: 'HubService',
            serviceEndpoint: 'https://hub.example.com/',
        });
    })
        .then(didDocument => res.send(didDocument))
        .catch(reason => res.status(500).send(reason));
});

This creates and responds the didDoc but when trying to resolve it I don't get anything.

router.get('/resolve', function (req, res) {
    let did = req.query["did"]
    if (did !== undefined && did.length > 0) {
        ipid.resolve(did)
            .then(r => res.send(r))
            .catch(reason => res.status(404).send(reason));
    } else {
        res.status(400).send("Missing did");
    }
});

Register response: {

    "publicKey": [
        {
            "type": "RsaVerificationKey2018",
            "publicKeyHex": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2wSSx0XuixPRjE9bVjj\nBotpLmgQ4j6QTXjkgEO8db8woXTLXKyv7k0Qlg3/o+/BaCFoqq7eCgYPzuLQtsV4\nmKmUWGs8i783wtx9ChdsvNUJtQDYLvY60tdEredCxzr4+IocQEeAp6oqHiuuQ3mX\nAtEh1909vsootLcNinK74ysOiTKhNeUWGYCKIMtMqUSqSIGP617os+IJVcGbZ1fk\nf9ofrVcQMTW+9LAohs1KYuFuNACRUP2EoQTkM890Mv0hp0kTKfexsKd7bjxfazo0\nDebrtYCwnFJyHaA+AB6+n1eskCGIgmM6KECLKZoLq1CPXn+AHDWc5MHJNKNN2kqt\nuQIDAQAB\n-----END PUBLIC KEY-----\n",
            "id": "did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb#5y3dyogt2to",
            "controller": "did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb"
        }
    ],
    "authentication": [
        "did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb#5y3dyogt2to"
    ],
    "service": [
        {
            "id": "did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb;hub",
            "type": "HubService",
            "serviceEndpoint": "https://hub.example.com/"
        }
    ],
    "@context": "https://w3id.org/did/v1",
    "id": "did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb",
    "created": "2020-06-17T12:19:38.247Z",
    "updated": "2020-06-17T12:19:38.247Z"
}

Response to localhost:3000/did/resolve?did=did:ipid:QmWDmXuHmm2RDhFDrVpL7487MB26NpVMWvS8jv59pARMMb
Code 404

{
    "originalError": "Cannot read property 'replace' of undefined",
    "code": "INVALID_DID",
    "name": "InvalidDid"
}

It's the replace on path in line 97 of the ipid index.js

const {
        path
      } = await _classPrivateFieldGet(this, _ipfs).name.resolve(identifier);
      const cidStr = path.replace(/^\/ipfs\//, '');

So it looks like it can't resolve the identifier

Manually resolving the did ipfs.name.resolve returns /ipfs/bafyreihnyf7hwzeo7gzfpxdys5kyz6v3o7pvh7dd3riird3krpfqyxx2lm but ipfs.cat returns Error: this dag node has no content. and the cloudflare gateway unknown node type

So I guess I'm doing something wrong but I can't figure it out. Maybe you can help.

Thanks,
Lukas

Using a secp256k1 private key to generate the DID document

Hi,

so I've been exploring using a secp256k1 private for architectural reasons.
I managed to get as far as generating the DID with a couple of tweaks in the code.

However I am struggling with the publishing. I am curious what is the purpose of this method: https://github.com/ipfs-shipyard/js-did-ipid/blob/master/src/index.js#L96, and how I can adapt things to work with secp256k1 as it expects RSA only (from libp2p-crypto).

I did go to the extent of converting the private key to pem with key-encoder-js, but that still fails since it's not RSA, but EC.

Here is the stacktrace, more for reference than anything:

Error: Invalid PEM formatted message.
    at Object.pem.decode (/Users/julien/work/did-blockcerts-poc/node_modules/libp2p/node_modules/node-forge/lib/pem.js:188:11)
    at Object.pki.decryptRsaPrivateKey (/Users/julien/work/did-blockcerts-poc/node_modules/libp2p/node_modules/node-forge/lib/pbe.js:540:23)
    at Object.importKey [as import] (/Users/julien/work/did-blockcerts-poc/node_modules/libp2p/node_modules/libp2p-crypto/src/keys/index.js:119:25)
    at Keychain.importKey (/Users/julien/work/did-blockcerts-poc/node_modules/libp2p/src/keychain/index.js:423:20)
    at Ipid.value (/Users/julien/work/js-did-ipid/lib/index.js:78:9)
    at Ipid.value (/Users/julien/work/js-did-ipid/lib/index.js:40:9)
(node:66147) UnhandledPromiseRejectionWarning: Error: Cannot read the key, most likely the password is wrong
    at Keychain.importKey (/Users/julien/work/did-blockcerts-poc/node_modules/libp2p/src/keychain/index.js:426:35)
    at Ipid.value (/Users/julien/work/js-did-ipid/lib/index.js:78:9)
    at Ipid.value (/Users/julien/work/js-did-ipid/lib/index.js:40:9)

And my pem key (which is actually a EC PRIVATE KEY - but I am replacing EC to nothing to avoid an early failure):

 -----BEGIN PRIVATE KEY-----
MHQCAQEEIOcqsPHevRXRga8fCRTu87mDb0mIV1wGoWLy98+9IRhIoAcGBSuBBAAK
oUQDQgAEwfIKzOidXUlhpq7E9Htu5cgj4b5Gu94UqHKkyLwOO6Ew36elS0dnrbDl
sBPNQbG1vPGYNTFibKCSAcBGI7Tv6A==
-----END PRIVATE KEY-----

I understand that I am trying to open a square with a circle and that's why it does not work. I believe I would also need to modify the #importKey method to work with secp256k1 natively (maybe just unmarshal my key from there)?
IPFS to allows existing keys to be passed: https://docs.ipfs.io/how-to/use-existing-private-key/#javascript, and in the options when creating one can also set the algorithm to be secp256k1. That does not help when importing the key.

Any guidance is welcome,

thanks a lot

Compatibility with ipfs-http-client

Im trying to use did-ipid with an instance of ipfs-http-client, but get the following error:

Uncaught (in promise) HTTPError: file argument 'key' is required

My code looks like this (similar to the example on the README.md):

const ipid = await createIpid(ipfs);
const didDocument = await ipid.create(pem, (document) => {
    const publicKey = document.addPublicKey({
    	type: 'RsaVerificationKey2018',
        publicKeyHex: '02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71',
    });

    const authentication = document.addAuthentication(publicKey.id);

    const service = document.addService({
    	id: 'hub',
    	type: 'HubService',
    	serviceEndpoint: 'https://hub.example.com/',
    });
});

Everything works as expected, when I hand over an instance of ipfs-core. The error only appears when attempting the exact same thing with an instance of ipfs-http-client. POST requests are allowed on my node and CORS is also not the problem. This might also be an issue with ipfs-http-client though. Maybe someone here could give me some directions.

[email protected]
[email protected]
[email protected]
go-ipfs v0.8.0

Thanks in advance!

Add new contexts

Contexts

DID method specifications, like IPID, may define their own JSON-LD contexts.

Although, as per the DID spec, this is possible:

it is NOT RECOMMENDED to define a new context unless necessary to properly implement the method

Also:

Method-specific contexts MUST NOT override the terms defined in the generic DID context.

state of this package

Hi,

I am curious to know what is the state of this package as it seems no active development was made in the past 2 years?

I saw in the spec that support for secp256k1 is considered, but it seems not available in this package. I looked at #20 and from what I understood partial support of secp256k1 has been developed into libp2p-crypto, at least for the use cases I am interested in.

I was wondering if subsequent work would happen in js-did-ipid to add support or if we could consider this package as stale?

Thanks

Pin dag nodes

Currently, we are not calling ipfs.pin.add after creating de DID document, but we should. We aren’t experiencing any issues because JS IPFS doesn’t GC files yet, but it will eventually.

Moreover, we will need a method to do the opposite, maybe dispose or unpin, which should be called when we remove an identity from the IDM wallet.

Cross link to other implementations

on the w3c ccg call today, it was mentioned that there are 3 implementations of dagCBOR / IPID... I would love to see those centralized under an IPID spec / document that is separate from a specific implementation.

Add embeded authentications

Authentication

An Authentication method can be embedded or referenced.

The DID spec, at the time of this issue, does not fully cover what and how an authentication method should be verified.

An example of a verification method is a public key.

This raised some questions during the first implementation of the module:

  • Can they only reference/embed public keys? If not, what more can they reference/embed?
  • Are this public keys from the same document?
  • If a public key is referenced from another document, should we manage a way to resolve it?
  • What are the use cases for embedded public keys? Are they available to avoid resolving a public key?

After some thought, me and @satazor decided that, during the first implementation, we would only support referenced authentication methods based on public keys from the same document.

We hope the DID spec to mature in following months and better cover the questions above.

Public Keys revoked list

Public Keys

At the time of this issue, the DID spec mentions that:

If a public key does not exist in the DID Document, it MUST be assumed the key has been revoked or is invalid. The DID Document MAY contain revoked keys. A DID Document that contains a revoked key MUST also contain or refer to the revocation information for the key (e.g., a revocation list). Each DID Method specification is expected to detail how revocation is performed and tracked.

Currently, the IPID method doesn't have any specification on how the revocation should be performed and tracked.

There is an open issue and we hope to see further developments.

Assert public key value integrity based on encoding

Public Keys

The value of the public key must be encoded in only one of the following:
Pem, Jwk, Hex, Base64, Base58, Multibase

Where, depending on the encoding, the corresponding property name should be used to match its value:
Pem - publicKeyPem
Jwk - publicKeyJwk
Base64 - publicKeyBase64
Base58 - publicKeyBase58
Multibase - publicKeyMultibase

This raised question of whether we should verify the integrity of the value based on its encoding before adding it to the document.
When reading a document, an entity might have parsing methods for each encoding and it the value doesn't match, the public key might be considered "invalid".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.