-
Notifications
You must be signed in to change notification settings - Fork 41
/
keys.ts
113 lines (101 loc) · 4.1 KB
/
keys.ts
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
101
102
103
104
105
106
107
108
109
110
111
112
113
import * as debug from '../debug'
import { schnorr } from '@noble/curves/secp256k1'
import { bytesToHex } from '@noble/hashes/utils'
import * as ns from '../ns'
import { store } from 'solid-logic'
import { NamedNode } from 'rdflib'
import * as $rdf from 'rdflib'
import { getExistingPublicKey, pubKeyUrl, privKeyUrl, getExistingPrivateKey } from '../utils/keyHelpers/accessData'
import { setAcl, keyContainerAclBody, keyAclBody } from '../utils/keyHelpers/acl'
export function generatePrivateKey (): string {
return bytesToHex(schnorr.utils.randomPrivateKey())
}
export function generatePublicKey (privateKey: string): string {
return bytesToHex(schnorr.getPublicKey(privateKey))
}
/**
* getPublicKey
* used for displaying messages in chat, therefore does not
* create a new key if not found
* @param webId
* @returns string | undefined
*/
export async function getPublicKey (webId: NamedNode) {
await store.fetcher.load(webId)
const publicKeyDoc = await pubKeyUrl(webId)
try {
await store.fetcher.load(publicKeyDoc) // url.href)
const key = store.any(webId, ns.solid('publicKey'))
return key?.value // as NamedNode
} catch (err) {
return undefined
}
}
export async function getPrivateKey (webId: NamedNode) {
await store.fetcher.load(webId)
// find keys url's
const publicKeyDoc = await pubKeyUrl(webId)
const privateKeyDoc = await privKeyUrl(webId)
// find key pair
const publicKey = await getExistingPublicKey(webId, publicKeyDoc)
let privateKey = await getExistingPrivateKey(webId, privateKeyDoc)
// is publicKey valid ?
let validPublicKey = true
if (privateKey && (publicKey !== generatePublicKey(privateKey as string))) {
if (confirm('This is strange the publicKey is not valid for\n' + webId?.uri +
'\'shall we repair keeping the private key ?')) validPublicKey = false
}
// create key pair or repair publicKey
if (!privateKey || !publicKey || !validPublicKey) {
let del: any[] = []
let add: any[] = []
if (!privateKey) {
// add = []
privateKey = generatePrivateKey()
add = [$rdf.st(webId, ns.solid('privateKey'), $rdf.literal(privateKey), store.sym(privateKeyDoc))]
await saveKey(privateKeyDoc, [], add, webId.uri)
}
if (!publicKey || !validPublicKey) {
del = []
// delete invalid public key
if (publicKey) {
del = [$rdf.st(webId, ns.solid('publicKey'), $rdf.lit(publicKey), store.sym(publicKeyDoc))]
debug.log('delete invalid publicKey ' + del)
}
// update new valid key
const newPublicKey = generatePublicKey(privateKey)
add = [$rdf.st(webId, ns.solid('publicKey'), $rdf.literal(newPublicKey), store.sym(publicKeyDoc))]
await saveKey(publicKeyDoc, del, add)
}
const keyContainer = privateKeyDoc.substring(0, privateKeyDoc.lastIndexOf('/') + 1)
await setAcl(keyContainer, keyContainerAclBody(webId.uri)) // includes DELETE and PUT
}
return privateKey as string
}
const deleteKeyAcl = async (keyDoc: string) => {
await store.fetcher.load(keyDoc)
const keyAclDoc = store.any(store.sym(keyDoc), store.sym('http://www.iana.org/assignments/link-relations/acl'))
if (keyAclDoc) {
// delete READ only keyAclDoc. This is possible if the webId is an owner
try {
const response = await store.fetcher.webOperation('DELETE', keyAclDoc.value) // this may fail if webId is not an owner
debug.log('delete keyAcl' + keyAclDoc.value + ' ' + response.status) // should test 404 and 2xx
} catch (err) {
if (err.response.status !== 404) { throw new Error(err) }
debug.log('delete keyAcl' + keyAclDoc.value + ' ' + err.response.status) // should test 404 and 2xx
}
}
}
/**
* delete acl if keydoc exists
* create/edit keyDoc
* set keyDoc acl
*/
async function saveKey (keyDoc: string, del, add, me: string = '') {
await deleteKeyAcl(keyDoc)
// save key
await store.updater.updateMany(del, add) // or a promise store.updater.update ?
// create READ only ACL
const aclBody = keyAclBody(keyDoc, me)
await setAcl(keyDoc, aclBody)
}