-
Notifications
You must be signed in to change notification settings - Fork 8
/
identity.js
100 lines (79 loc) · 2.85 KB
/
identity.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
const Readable = require('stream').Readable
const pump = require('pump')
const collect = require('collect-stream')
const ln = require('hyperdrive-ln')
const encrypted = require('encrypted-message')
const bufferJSON = require('buffer-json')
const META_FILE = '.identity.json'
const ACCEPT_MESSAGE = 'APPROVED'
module.exports = Identity
function Identity (archive) {
if (!(this instanceof Identity)) return new Identity(archive)
this.archive = archive
this.key = archive.key
}
Identity.prototype.setMeta = function (meta, cb) {
pump(source(JSON.stringify(meta)), this.archive.createFileWriteStream(META_FILE), cb)
}
Identity.prototype.getMeta = function (cb) {
collect(this.archive.createFileReadStream(META_FILE), cb)
}
Identity.prototype.serviceLinkToken = function (service, archiveKey) {
var payload = encrypted.message(service.keyPair, {publicKey: this.archive.key}, archiveKey)
return JSON.stringify({
service: {
publicKey: service.keyPair.publicKey,
meta: service.meta
},
payload: payload
}, bufferJSON.replacer)
}
Identity.prototype.acceptLinkToken = function (token, cb) {
var archive = this.archive
token = JSON.parse(token, bufferJSON.reviver)
var secretKey = this.archive.metadata.secretKey
var link = encrypted.openMessage({publicKey: token.service.publicKey}, {secretKey}, token.payload)
if (!link) return cb(new Error('unable to read token'))
var resp = JSON.stringify(createResponse(
{ publicKey: token.service.publicKey }, // service
{ secretKey: archive.metadata.secretKey } // self
), bufferJSON.replacer)
pump(source(resp), archive.createFileWriteStream(proofPath(token.service.publicKey)), err => {
if (err) return cb(err)
ln.link(archive, linkPath(token.service.publicKey), link, token.service.meta, cb)
})
function createResponse (service, self) {
return encrypted.message(self, service, ACCEPT_MESSAGE)
}
}
Identity.prototype.verifyAcceptingness = function (service, cb) {
var archive = this.archive
archive.list((err, entries) => {
if (err) return cb(err)
var found = false
for (var i = 0; i < entries.length; i++) {
if (entries[i].name === proofPath(service.keyPair.publicKey)) {
collect(archive.createFileReadStream(proofPath(service.keyPair.publicKey)), (err, data) => {
if (err) return cb(err)
var msg = encrypted.openMessage({publicKey: archive.key}, {secretKey: service.keyPair.secretKey}, JSON.parse(data, bufferJSON.reviver))
cb(null, msg.toString() === ACCEPT_MESSAGE)
})
found = true
break
}
}
if (!found) cb(null) // no error, but not verified
})
}
function source (str) {
var s = new Readable()
s.push(str)
s.push(null)
return s
}
function proofPath (key) {
return `.proofs/${key.toString('hex')}`
}
function linkPath (key) {
return `.links/${key.toString('hex')}`
}