iden3js
Javascript client library of the iden3 system.
Install
npm install --save iden3
https://www.npmjs.com/package/iden3
Basic example
const iden3 = require('iden3');
let kc = new iden3.KeyContainer('localstorage');
let passphrase = 'this is a test passphrase';
kc.unlock(passphrase);
let keyId = kc.importKey('x');
let keys = kc.generateKeysMnemonic();
let keyRecover = keys.keys[0];
let keyRevoke = keys.keys[1];
let keyOp = keys.keys[2];
let seed = 'blanket kick genre rubber better helmet youth slush acid select brick setup';
let keys = kc.generateKeysMnemonic(seed);
let key0id = kc.importKey('privKHex');
let key1id = kc.generateKeyRand();
const relay = new iden3.Relay('http://127.0.0.1:5000');
let id = new iden3.Id(keyRecover, keyRevoke, keyOp, relay, '');
id.createID().then(res => {
console.log(res);
console.log(id.idaddr);
});
id.bindID(kc, 'username').then(res => {
console.log(res.data);
});
let ksign = kc.generateKey();
let unixtime = Math.round(+new Date()/1000);
id.authorizeKSignClaim(kc, key0id, ksign, 'appToAuthName', 'authz', unixtime, unixtime).then(res => {
let proofOfKSign = res.data.proofOfClaim;
});
id.genericClaim(kc, ksign, 'iden3.io', 'default', 'extraindex', 'data').then(res => {
let proofOfClaim = res.data.proofOfClaim;
});
let verified = iden3.merkleTree.checkProof(rootHex, mpHex, hiHex, htHex, numLevels);
let verified = iden3.claim.checkProofOfClaim(proofOfClaim, 140);
let qrJson = iden3.auth.parseQRhex(qrHex);
let qrKSign = iden3.utils.addrFromSig(qrJson.challenge, qrJson.signature);
id.authorizeKSignClaim(kc, id.keyOperational, qrKSign, 'appToAuthName', 'authz', unixtimeFrom, unixtimeUntil).then(res => {
let ksignProof = res.data.proofOfClaim;
iden3.auth.resolv(qrJson.url, id.keyOperational, qrJson.challenge, qrJson.signature, qrKSign, ksignProof).then(res => {
console.log('centralized auth success, the website will refresh with the jwt');
})
.catch(function (error) {
console.log(error);
});
})
.catch(function (error) {
console.log(error);
});
Usage
Import
const iden3 = require('iden3');
KeyContainer
Usage:
let passphrase = 'this is a test passphrase';
kc.unlock(passphrase);
let keys = kc.generateKeysMnemonic();
let seed = 'blanket kick genre rubber better helmet youth slush acid select brick setup';
let keys = kc.generateKeysMnemonic(seed);
let keys_id0 = kc.generateKeysMnemonic(seed, 0, 4);
let keys_id1 = kc.generateKeysMnemonic(seed, 1, 2);
let keys_id2 = kc.generateKeysMnemonic(seed, 2, 5);
let key0id = kc.importKey('privKHex');
let key1id = kc.generateKeyRandom();
let signature = kc.sign(key0id, 'test');
let keysList = kc.listKeys();
Id
let kc = new iden3.KeyContainer();
let passphrase = 'this is a test passphrase';
kc.unlock(passphrase);
let keyRecover = kc.generateKey();
let keyRevoke = kc.generateKey();
let keyOp = kc.generateKey();
const relay = new iden3.Relay('http://127.0.0.1:5000');
let id = new iden3.Id(keyRecover, keyRevoke, keyOp, relay, '');
id.createID
Creates the counterfactual contract through the Relay
, and gets the identity address.
id.createID().then(res => {
console.log(res);
});
Output:
{
idaddr : '0x46b57a3f315f99a6de39406310f5bd0db03326c1'
}
id.deployID
Deploys the counterfactual smart contract of identity to the blockchain.
id.deployID().then(res => {
console.log(res.data);
});
Output:
{
idaddr: '0x8435ebb41634c05019be1710be0007fa0d92861f',
tx: '0x403859ccc701eb358d3a25c908c33de733cbb2d0ebc1c7738eed4908cc8cf5c4'
}
id.bindID
Vinculates a name to the identity.
Internally, signs the idaddr+name, and sends it to the Relay
, that will perform an AssignNameClaim vinculating the identity address with the name.
id.bindID(kc, name).then(res => {
console.log(res.data);
});
Output:
{
ethID: '0xbc8c480e68d0895f1e410f4e4ea6e2d6b160ca9f',
name: 'username',
signature: '0xeda8b278eae69cd8c4863380f0af5cfe8360481790d8ea5c188705b552bc0d5e1384efb627db5b423d4a163ad02ca23a2f05eea5dc787ac5837789aa95f50f101b'
}
id.authorizeKSignClaim
let keyToAuth = kc.generateKey();
id.authorizeKSignClaim(kc, key0id, keyToAuth, 'appToAuthName', 'authz', 1535208350, 1535208350).then(res => {
});
id.genericClaim
id.genericClaim(kc, ksign, 'iden3.io', 'default', 'extraindex', 'data').then(res => {
});
Claims
Generic Claim
let claim = new iden3.claim.GenericClaim('iden3.io', 'default', 'extra index data', 'extra data');
claim.bytes();
claim.hi();
claim.ht();
let claimParsed = iden3.claim.parseGenericClaimBytes(claim.bytes());
authorizeKSignClaim
let authorizeKSignClaim = new iden3.claim.AuthorizeKSignClaim('0x101d2fa51f8259df207115af9eaa73f3f4e52e60',
'appToAuthName', 'authz', 1535208350, 1535208350);
authorizeKSignClaim.bytes();
authorizeKSignClaim.hi();
authorizeKSignClaim.ht();
let authorizeKSignClaimParsed = iden3.claim.parseAuthorizeKSignClaim(authorizeKSignClaim.bytes());
checkProofOfClaim
Checks the full proof
of a claim
. This means check the:
Merkle Proof
of the claim
Merkle Proof
of the non revocation claim
Merkle Proof
of the claim
that the Relay
have performed over the identity
Merkle Root
(this kind of claim is the SetRootClaim
)Merkle Proof
of the non revocation of the SetRootClaim
let proofOfClaimStr = `
{
"ClaimProof": {
"Leaf": "0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c4969403074353f867ef725411de05e3d4b0a01c37cf7ad24bcc213141a0000005400000000970e8128ab834e8eac17ab8e3812f010678cf7912077bb3f0400dd62421c97220536fd6ed2be29228e8db1315e8c6d7525f4bdf4dad9966a2e7371f0a24b1929ed765c0e7a3f2b4665a76a19d58173308bb34062000000005b816b9e000000005b816b9e",
"Proof": "0x00000000000000000000000000000000000000000000000000000000000000052d3cbe677b6e4048e0db5a3d550e5f1bb2252c099a990137ac644ddfff9553dde5d128f57df872a6ab1c768ab3da7fc08faa153d4ac40c33471d25be32b38132",
"Root": "0xb98333b2c502fc156d0ee7779d77aa9063fcbc6ed41e5c3e8b9900f379523101"
},
"SetRootClaimProof": {
"Leaf": "0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c49694030749b9a76a0132a0814192c05c9321efc30c7286f6187f18fc60000005400000003bc8c480e68d0895f1e410f4e4ea6e2d6b160ca9fb98333b2c502fc156d0ee7779d77aa9063fcbc6ed41e5c3e8b9900f379523101",
"Proof": "0x000000000000000000000000000000000000000000000000000000000000000b7d2ff8e70da77ef7559614425aa33021eb88752f63a690911c031a1fae273f9393b3f57a79800ca02cd1ac3a555d9dbb7d5869251d51d34e01d7de4ab811e9753cb6d37abb4eae8eeea11cbae9a96a021e2d157340721884763fc2ac33313ecd",
"Root": "0x33f1e9b3ed86317369938d5bb04ba23e5f5de65da07c3a9368ffe19121e7a6c6"
},
"ClaimNonRevocationProof": {
"Leaf": "0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c4969403074353f867ef725411de05e3d4b0a01c37cf7ad24bcc213141a0000005400000001970e8128ab834e8eac17ab8e3812f010678cf7912077bb3f0400dd62421c97220536fd6ed2be29228e8db1315e8c6d7525f4bdf4dad9966a2e7371f0a24b1929ed765c0e7a3f2b4665a76a19d58173308bb34062000000005b816b9e000000005b816b9e",
"Proof": "0x0000000000000000000000000000000000000000000000000000000000000003df560419165ec6b3299f04ac93510999379987ff25b0799a738ad0d078c9b9d6f912e7e2fab90f745aab5874a5e4f7657921b271378ea05ee9b0f25d69f87a3c",
"Root": "0xb98333b2c502fc156d0ee7779d77aa9063fcbc6ed41e5c3e8b9900f379523101"
},
"SetRootClaimNonRevocationProof": {
"Leaf": "0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c49694030749b9a76a0132a0814192c05c9321efc30c7286f6187f18fc60000005400000004bc8c480e68d0895f1e410f4e4ea6e2d6b160ca9fb98333b2c502fc156d0ee7779d77aa9063fcbc6ed41e5c3e8b9900f379523101",
"Proof": "0x000000000000000000000000000000000000000000000000000000000000000b615fadf56023c4ef72c3d455f0e6b6f9ace467e751e9b8e350fe0401368faf4801d4499dba57c843cd6c64fb07975d506e27b5e68166493618405a4bbf2b256eaf677f70fad9050c9d8e77b727fe6d29187c054cd47cfb3fcc10b2a4cbf08f8c",
"Root": "0x33f1e9b3ed86317369938d5bb04ba23e5f5de65da07c3a9368ffe19121e7a6c6"
},
"Date": 1539008518,
"Signature": "0x19074094d44fc77bc020d6c51c2e3f71fb45ede33b05202553d785cfce7d702411b98a4d0980d35383dfbe1d5b9779ee3b8f6295c27969bcf45156cdf6382b6201"
}
`;
let proofOfClaim = JSON.parse(proofOfClaimStr);
let verified = iden3.claim.checkProofOfClaim(proofOfClaim, 140);
Merkletree
CheckProof
Checks the Merkle Proof
of a Leaf
.
let verified = iden3.merkleTree.checkProof(rootHex, mpHex, hiHex, htHex, numLevels);
console.log(verified);
CheckProofOfClaim
This function checks the data structure of proofOfClaim
and returns true if all the proofs are correct.
Internally, it usees the iden3.merkleTree.checkProof()
function, for each one of the proofs that are contained inside proofOfClaim
data object.
let verified = iden3.merkleTree.checkProofOfClaim(proofOfClaim, 140);
console.log(verified);
Utils
let hash = iden3.utils.hashBytes(b);
let hex = iden3.utils.bytesToHex(buff);
let buff = iden3.utils.hexToBytes(hex);
let verified = iden3.utils.verifySignature(msgHashHex, signatureHex, addressHex);
Relay http
Connectors to interact with the relay API REST.
Create Relay object
const relay = new iden3.Relay('http://127.0.0.1:5000');
relay.getRelayRoot
relay.getRelayRoot()
.then(res => {
console.log('res.data', res.data);
});
Response:
{
contractRoot: '0x6e4659fedd8ff00b14e487d6d5f537646f07bde944d935d51bd9de807d6fc1c9',
root: '0x0000000000000000000000000000000000000000000000000000000000000000'
}
relay.getIDRoot
relay.getIDRoot(id.kc.addressHex())
.then(res => {
console.log('res.data', res.data);
});
Response:
{
idRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
idRootProof: '0x0000000000000000000000000000000000000000000000000000000000000000',
root: '0x0000000000000000000000000000000000000000000000000000000000000000'
}
relay.genericClaim
Creates a new AuthorizeKSignClaim, signs it, and sends it to the Relay.
relay.genericClaim(id.kc, ksign, 'iden3.io', 'default', 'data of the claim').then(res => {
expect(res.status).to.be.equal(200);
});
relay.authorizeKSignClaim
Creates a new authorizeKSignClaim, signs it, and sends it to the Relay.
relay.authorizeKSignClaim(id.kc, keyid, kSign.addressHex(), 'appToAuthName', 'authz', 1535208350, 1535208350).then(res => {
expect(res.status).to.be.equal(200);
});
relay.postClaim
Sends to the Relay a signed Claim.
relay.postClaim(idaddr, bytesSignedMsg)
.then(res => {
console.log('res.data', res.data);
});
The response is the ProofOfClaim
, same as returned in relay.getClaimByHi().
relay.getClaimByHi
relay.getClaimByHi(idaddr, hi)
.then(res => {
console.log('res.data', res.data);
});
Response, ProofOfClaim
:
{
claimProof: {
Leaf: '0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c4969403074353f867ef725411de05e3d4b0a01c37cf7ad24bcc213141a05ed7726d7932a1f00000000bc8c480e68d0895f1e410f4e4ea6e2d6b160ca9f2077bb3f0400dd62421c97220536fd6ed2be29228e8db1315e8c6d7525f4bdf4dad9966a2e7371f0a24b1929ed765c0e7a3f2b4665a76a19d58173308bb34062000000005b816b9e000000005b816b9e',
Hi: '0x438a26007910a723fedf030efd08fed2d374634eb8866ce595c139ea341daa43',
Proof: '0x0000000000000000000000000000000000000000000000000000000000000000',
Root: '0xd1d3ebd84f46ec73767a2fe89930f33eef96ddf18c35e03faf03a98c8e6bf207'
},
setRootClaimProof: {
Leaf: '0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c49694030749b9a76a0132a0814192c05c9321efc30c7286f6187f18fc6b6858214fe963e0e00000000bc8c480e68d0895f1e410f4e4ea6e2d6b160ca9fd1d3ebd84f46ec73767a2fe89930f33eef96ddf18c35e03faf03a98c8e6bf207',
Hi: '0xbadb12c663dc83678de0709619fb8c67f939b7a2c5c658a6305fa4841e62e392',
Proof: '0x0000000000000000000000000000000000000000000000000000000000000000',
Root: '0xfd89568c4dfe0b22be91c810421dcf02ac7ca42bc005461886a443fb6e0ead78'
},
claimNonRevocationProof: {
Leaf: '0x0000000000000000000000000000000000000000000000000000000000000000',
Hi: '0x1d4221032dae2392d162cf09030f5ad9fb135380a49bb1e8caf549aaea42b53f',
Proof: '0x0000000000000000000000000000000000000000000000000000000000000004ce587b2d039c876de24e8b7fbdeb4cf6b84d542a60cdef47cf0ab29c631fba26',
Root: '0xd1d3ebd84f46ec73767a2fe89930f33eef96ddf18c35e03faf03a98c8e6bf207'
},
setRootClaimNonRevocationProof: {
Leaf: '0x0000000000000000000000000000000000000000000000000000000000000000',
Hi: '0x28f5ee91e756ec1a3d1ea9ca2a68b5dde6ded3ea98effeadcefbff9a352aa434',
Proof: '0x0000000000000000000000000000000000000000000000000000000000000002b8193081f59feef7baab60cd827267371b2e6495cd2efab189370e0e2ea5819c',
Root: '0xfd89568c4dfe0b22be91c810421dcf02ac7ca42bc005461886a443fb6e0ead78'
}
}
GET relay.getID
relay.getID('0x46b57a3f315f99a6de39406310f5bd0db03326c1')
.then(res => {
console.log('res.data', res.data);
});
Output:
{
IDAddr: '0x46b57a3f315f99a6de39406310f5bd0db03326c1',
LocalDb: {
Operational: '0x970e8128ab834e8eac17ab8e3812f010678cf791',
Relayer: '0xe0fbce58cfaa72812103f003adce3f284fe5fc7c',
Recoverer: '0x970e8128ab834e8eac17ab8e3812f010678cf791',
Revokator: '0x970e8128ab834e8eac17ab8e3812f010678cf791',
Impl: '0x2623ed1533d47d56f912300ae40f83b9370cead6'
},
Onchain: null
}
relay.resolveName
relay.resolveName('username@iden3.io')
.then(res => {
console.log('res.data', res.data);
});
Output:
{
claim: '0x3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c4969403074b7ae3d3a2056c54f48763999f3ff99caffaaba3bab58cae900000080000000008a440962fb17f0fe928a3d930137743fe63b8f4c0ce5a5da63991310103d9aef3cfc3a1edbf691316fec9b75970fbfb2b0e8d8edfc6ec7628db77c4969403074bc8c480e68d0895f1e410f4e4ea6e2d6b160ca9f',
ethID: '0xbc8c480e68d0895f1e410f4e4ea6e2d6b160ca9f'
}
Auth
let qrJson = iden3.auth.parseQRhex(qrHex);
let qrKSign = iden3.utils.addrFromSig(qrJson.challenge, qrJson.signature);
id.authorizeKSignClaim(kc, id.keyOperational, qrKSign, 'appToAuthName', 'authz', unixtimeFrom, unixtimeUntil).then(res => {
let ksignProof = res.data.proofOfClaim;
iden3.auth.resolv(qrJson.url, id.keyOperational, qrJson.challenge, qrJson.signature, qrKSign, ksignProof).then(res => {
alert('centralized auth success, the website will refresh with the jwt');
})
.catch(function (error) {
alert(error);
});
})
.catch(function (error) {
alert(error);
});
Centralized Apps integration
The following instructions are for centralized apps, to integrate the iden3 system for authentication.
Once having a centrauth
backend running ( https://github.com/iden3/go-iden3 ).
Include the iden3js
library:
const iden3 = require('iden3');
Or in the html include:
<script src="iden3js-bundle.js"></script>
Add in the html the div that will contain the QR:
<div id="qrcodediv"></div>
<textarea id="qrHex" rows="4" cols="30" readonly="readonly"></textarea>
In the js:
let passphrase = 'this is a test passphrase';
const authurl = 'http://IPcentrauth:5000';
const authwsurl = 'ws://IPcentrauth:5000';
let kc = new iden3.KeyContainer('localstorage');
kc.unlock(passphrase);
let ksign = kc.generateKey();
let auth = new iden3.Auth(kc, ksign, authurl, authwsurl, function(authData) {
alert('✔️ Logged in');
});
auth.printQr('qrcodediv');
let qrHex = auth.qrHex();
document.getElementById("qrHex").value = qrHex;
Tests
To run all tests, needs to have a running Relay node.
npm test
Browserify bundle
To generate the browserify bundle:
browserify index.js --standalone iden3 > iden3js-bundle.js
WARNING
All code here is experimental and WIP
License
iden3js is part of the iden3 project copyright 2018 0kims association and published with GPL-3 license, please check the LICENSE file for more details.