signify-ts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -0
- package/dist/keri/core/cigar.d.ts +8 -0
- package/dist/keri/core/cipher.d.ts +5 -0
- package/dist/keri/core/core.d.ts +68 -0
- package/dist/keri/core/decrypter.d.ts +10 -0
- package/dist/keri/core/diger.d.ts +21 -0
- package/dist/keri/core/encrypter.d.ts +9 -0
- package/dist/keri/core/indexer.d.ts +88 -0
- package/dist/keri/core/keeping.d.ts +1 -0
- package/dist/keri/core/kering.d.ts +5 -0
- package/dist/keri/core/manager.d.ts +151 -0
- package/dist/keri/core/matter.d.ts +47 -0
- package/dist/keri/core/siger.d.ts +22 -0
- package/dist/keri/core/signer.d.ts +34 -0
- package/dist/keri/core/utils.d.ts +16 -0
- package/dist/signify-ts.cjs.development.js +13 -0
- package/dist/signify-ts.cjs.development.js.map +1 -0
- package/dist/signify-ts.cjs.production.min.js +2 -0
- package/dist/signify-ts.cjs.production.min.js.map +1 -0
- package/dist/signify-ts.esm.js +9 -0
- package/dist/signify-ts.esm.js.map +1 -0
- package/package.json +66 -0
- package/src/index.ts +6 -0
- package/src/keri/core/cigar.ts +19 -0
- package/src/keri/core/cipher.ts +25 -0
- package/src/keri/core/core.ts +174 -0
- package/src/keri/core/decrypter.ts +66 -0
- package/src/keri/core/diger.ts +82 -0
- package/src/keri/core/encrypter.ts +60 -0
- package/src/keri/core/indexer.ts +406 -0
- package/src/keri/core/keeping.ts +9 -0
- package/src/keri/core/kering.ts +12 -0
- package/src/keri/core/manager.ts +874 -0
- package/src/keri/core/matter.ts +252 -0
- package/src/keri/core/salter.ts +85 -0
- package/src/keri/core/siger.ts +39 -0
- package/src/keri/core/signer.ts +112 -0
- package/src/keri/core/tsconfig.json +100 -0
- package/src/keri/core/utils.ts +94 -0
- package/src/keri/core/verfer.ts +33 -0
|
@@ -0,0 +1,874 @@
|
|
|
1
|
+
import {Encrypter} from "./encrypter"
|
|
2
|
+
import {Decrypter} from "./decrypter"
|
|
3
|
+
import {Salter, Tier} from "./salter"
|
|
4
|
+
import {Signer} from "./signer"
|
|
5
|
+
import {Verfer} from "./verfer";
|
|
6
|
+
import {MtrDex} from "./matter";
|
|
7
|
+
import {Diger} from "./diger";
|
|
8
|
+
import {Cigar} from "./cigar";
|
|
9
|
+
import {Siger} from "./siger";
|
|
10
|
+
import {b} from "./core";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export enum Algos {
|
|
14
|
+
randy = "randy",
|
|
15
|
+
salty = "salty"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class PubLot {
|
|
19
|
+
public pubs: Array<string> = new Array<string>() // list qb64 public keys.
|
|
20
|
+
public ridx: number = 0 // index of rotation (est event) that uses public key set
|
|
21
|
+
public kidx: number = 0 // index of key in sequence of public keys
|
|
22
|
+
public dt:string = "" // datetime ISO8601 when key set created
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class PreSit {
|
|
26
|
+
public old: PubLot = new PubLot() //previous publot
|
|
27
|
+
public new: PubLot = new PubLot() //newly current publot
|
|
28
|
+
public nxt: PubLot = new PubLot() //next public publot
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class PrePrm {
|
|
32
|
+
public pidx: number = 0 // prefix index for this keypair sequence
|
|
33
|
+
public algo: Algos = Algos.salty // salty default uses indices and salt to create new key pairs
|
|
34
|
+
public salt: string = '' // empty salt used for salty algo.
|
|
35
|
+
public stem: string = '' // default unique path stem for salty algo
|
|
36
|
+
public tier: string = '' // security tier for stretch index salty algo
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class PubSet {
|
|
41
|
+
pubs: Array<string> = new Array<string>() // list qb64 public keys.
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Creator {
|
|
45
|
+
create(codes: Array<string> | undefined, count: number, code: string, transferable: boolean,
|
|
46
|
+
pidx: number, ridx: number, kidx: number, temp: boolean): Array<Signer>
|
|
47
|
+
get salt(): string
|
|
48
|
+
get stem(): string
|
|
49
|
+
get tier(): Tier
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class RandyCreator implements Creator {
|
|
53
|
+
|
|
54
|
+
create(codes: Array<string> | undefined = undefined, count: number = 1, code: string = MtrDex.Ed25519_Seed,
|
|
55
|
+
transferable: boolean = true): Array<Signer> {
|
|
56
|
+
let signers = new Array<Signer>()
|
|
57
|
+
if (codes == undefined) {
|
|
58
|
+
codes = new Array(count).fill(code)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
codes.forEach(function(code) {
|
|
62
|
+
signers.push(new Signer({code: code, transferable: transferable}))
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return signers
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get salt(): string {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get stem(): string {
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get tier(): Tier {
|
|
77
|
+
return Tier.low;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class SaltyCreator implements Creator {
|
|
82
|
+
|
|
83
|
+
public salter: Salter
|
|
84
|
+
private readonly _stem: string
|
|
85
|
+
constructor(salt: string | undefined = undefined, tier: Tier | undefined = undefined,
|
|
86
|
+
stem: string | undefined = undefined) {
|
|
87
|
+
|
|
88
|
+
this.salter = new Salter({qb64: salt, tier: tier})
|
|
89
|
+
this._stem = stem == undefined ? "" : stem
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get salt(): string {
|
|
94
|
+
return this.salter.qb64;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get stem(): string {
|
|
98
|
+
return this._stem;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get tier(): Tier {
|
|
102
|
+
return this.salter.tier;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
create(codes: Array<string> | undefined = undefined, count: number = 1, code: string = MtrDex.Ed25519_Seed,
|
|
106
|
+
transferable: boolean = true, pidx: number = 0, ridx: number = 0, kidx: number = 0,
|
|
107
|
+
temp: boolean = false): Array<Signer> {
|
|
108
|
+
let signers = new Array<Signer>()
|
|
109
|
+
if (codes == undefined) {
|
|
110
|
+
codes = new Array(count).fill(code)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let stem = this.stem == "" ? pidx.toString(16) : this.stem
|
|
114
|
+
|
|
115
|
+
codes.forEach((code, idx) => {
|
|
116
|
+
let path = stem + ridx.toString(16) + (kidx+idx).toString(16)
|
|
117
|
+
signers.push(this.salter.signer(code, transferable, path, this.tier, temp))
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return signers
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export class Creatory {
|
|
126
|
+
private _make: any
|
|
127
|
+
constructor(algo: Algos = Algos.salty) {
|
|
128
|
+
switch(algo) {
|
|
129
|
+
case Algos.randy:
|
|
130
|
+
this._make = this._makeRandy
|
|
131
|
+
break;
|
|
132
|
+
case Algos.salty:
|
|
133
|
+
this._make = this._makeSalty
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`unsupported algo=${algo}`)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
make(...args: any[]) {
|
|
141
|
+
return this._make(...args)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_makeRandy() {
|
|
145
|
+
return new RandyCreator()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_makeSalty(...args: any[]) {
|
|
149
|
+
return new SaltyCreator(...args)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface ManagerArgs {
|
|
154
|
+
ks?: KeyStore | undefined
|
|
155
|
+
seed?: string | undefined
|
|
156
|
+
aeid?: string | undefined
|
|
157
|
+
pidx?: number | undefined
|
|
158
|
+
algo?: string | undefined
|
|
159
|
+
salt?: string | undefined
|
|
160
|
+
tier?: string | undefined
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface InceptArgs {
|
|
164
|
+
icodes?: any | undefined
|
|
165
|
+
icount?: number
|
|
166
|
+
icode?: string
|
|
167
|
+
ncodes?: any | undefined
|
|
168
|
+
ncount?: number
|
|
169
|
+
ncode?: string
|
|
170
|
+
dcode?: string
|
|
171
|
+
algo?: Algos | undefined
|
|
172
|
+
salt?: string | undefined
|
|
173
|
+
stem?: string | undefined
|
|
174
|
+
tier?: string | undefined
|
|
175
|
+
rooted?: boolean
|
|
176
|
+
transferable?: boolean
|
|
177
|
+
temp?: boolean
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface RotateArgs {
|
|
181
|
+
pre: string
|
|
182
|
+
ncodes?: any | undefined
|
|
183
|
+
ncount?: number
|
|
184
|
+
ncode?: string
|
|
185
|
+
dcode?: string
|
|
186
|
+
transferable?: boolean
|
|
187
|
+
temp?: boolean
|
|
188
|
+
erase?: boolean
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
interface SignArgs {
|
|
192
|
+
ser: Uint8Array
|
|
193
|
+
pubs?: Array<string> | undefined
|
|
194
|
+
verfers?: Array<Verfer> | undefined
|
|
195
|
+
indexed?: boolean
|
|
196
|
+
indices?: Array<number> | undefined
|
|
197
|
+
ondices?: Array<number> | undefined
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export class Manager {
|
|
201
|
+
private _seed: string
|
|
202
|
+
private _encrypter: Encrypter | undefined
|
|
203
|
+
private _decrypter: Decrypter | undefined
|
|
204
|
+
private _ks: KeyStore
|
|
205
|
+
|
|
206
|
+
constructor({ks, seed, aeid, pidx, algo, salt, tier}: ManagerArgs) {
|
|
207
|
+
|
|
208
|
+
this._ks = ks == undefined ? new Keeper() : ks
|
|
209
|
+
this._seed = seed == undefined ? "" : seed
|
|
210
|
+
this._encrypter = undefined
|
|
211
|
+
this._decrypter = undefined
|
|
212
|
+
|
|
213
|
+
aeid = aeid == undefined ? "" : aeid
|
|
214
|
+
pidx = pidx == undefined ? 0 : pidx
|
|
215
|
+
algo = algo == undefined ? Algos.salty : algo
|
|
216
|
+
|
|
217
|
+
if (salt == undefined) {
|
|
218
|
+
salt = new Salter({}).qb64
|
|
219
|
+
} else {
|
|
220
|
+
if (new Salter({qb64: salt}).qb64 != salt) {
|
|
221
|
+
throw new Error(`Invalid qb64 for salt=${salt}.`)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
tier = tier == undefined ? Tier.low : tier
|
|
226
|
+
|
|
227
|
+
if (this.pidx == undefined) {
|
|
228
|
+
this.pidx = pidx
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (this.algo == undefined) {
|
|
232
|
+
this.algo = algo
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (this.salt == undefined) {
|
|
236
|
+
this.salt = salt
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (this.tier == undefined) {
|
|
240
|
+
this.tier = tier
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (this.aeid == undefined) {
|
|
244
|
+
this.updateAeid(aeid, this._seed)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
get ks(): KeyStore {
|
|
249
|
+
return this._ks
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
get encrypter(): Encrypter {
|
|
253
|
+
return this._encrypter!
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
get decrypter(): Decrypter {
|
|
257
|
+
return this._decrypter!
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
get seed(): string {
|
|
261
|
+
return this._seed
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
get aeid(): string | undefined {
|
|
265
|
+
return this.ks.getGbls('aeid')
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
get pidx(): number | undefined {
|
|
269
|
+
let pidx = this.ks.getGbls('pidx')
|
|
270
|
+
if (pidx != undefined) {
|
|
271
|
+
return parseInt(pidx, 16)
|
|
272
|
+
}
|
|
273
|
+
return undefined
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
set pidx(pidx: number | undefined) {
|
|
277
|
+
this.ks.pinGbls('pidx', pidx!.toString(16))
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
get salt(): string | undefined{
|
|
281
|
+
let salt = this.ks.getGbls('salt')
|
|
282
|
+
if (this._decrypter != undefined) {
|
|
283
|
+
return this._decrypter?.decrypt(b(salt)).qb64
|
|
284
|
+
}
|
|
285
|
+
return salt
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
set salt(salt: string | undefined) {
|
|
289
|
+
if(this._encrypter != undefined) {
|
|
290
|
+
salt = this._encrypter.encrypt(b(salt)).qb64
|
|
291
|
+
}
|
|
292
|
+
this.ks.pinGbls('salt', salt!)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
get tier(): string | undefined {
|
|
296
|
+
return this.ks.getGbls('tier')
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
set tier(tier: string | undefined) {
|
|
300
|
+
this.ks.pinGbls('tier', tier!)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
get algo(): Algos | undefined {
|
|
304
|
+
let a = this.ks.getGbls('algo')
|
|
305
|
+
let ta = a as keyof typeof Algos
|
|
306
|
+
return Algos[ta]
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
set algo(algo: string | undefined) {
|
|
310
|
+
this.ks.pinGbls('algo', algo!)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private updateAeid(aeid: string | undefined, seed: string) {
|
|
314
|
+
if (this.aeid != undefined) {
|
|
315
|
+
let seed = b(this._seed)
|
|
316
|
+
if (this._seed == undefined || !this._encrypter?.verifySeed(seed)) {
|
|
317
|
+
throw new Error(`Last seed missing or provided last seed "
|
|
318
|
+
"not associated with last aeid=${this.aeid}.`)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (aeid != "" && aeid != undefined) {
|
|
323
|
+
if (aeid != this.aeid) {
|
|
324
|
+
this._encrypter = new Encrypter({}, b(aeid))
|
|
325
|
+
if (seed == undefined || !this._encrypter.verifySeed(b(seed))) {
|
|
326
|
+
throw new Error(`Seed missing or provided seed not associated"
|
|
327
|
+
" with provided aeid=${aeid}.`)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
// Unlike KERIpy, we don't support unencrypted secrets
|
|
332
|
+
throw new Error("Invalid use of Manager, unencrypted keystore not supported")
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let salt = this.salt
|
|
336
|
+
if(salt != undefined) {
|
|
337
|
+
this.salt = salt
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (this._decrypter != undefined) {
|
|
341
|
+
for (const [keys, data] of this.ks.prmsElements()) {
|
|
342
|
+
if (data.salt != undefined) {
|
|
343
|
+
let salter = this._decrypter.decrypt(b(data.salt))
|
|
344
|
+
data.salt = this._encrypter == undefined ? salter.qb64 : this._encrypter.encrypt(null, salter)
|
|
345
|
+
this.ks.pinPrms(keys, data)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const [pubKey, signer] of this.ks.prisElements(this._decrypter)) {
|
|
350
|
+
this.ks.pinPris(pubKey, signer, this._encrypter!)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
this.ks.pinGbls("aeid", aeid) // set aeid in db
|
|
356
|
+
this._seed = seed // set .seed in memory
|
|
357
|
+
|
|
358
|
+
// update .decrypter
|
|
359
|
+
this._decrypter = seed != undefined ? new Decrypter({}, b(seed)) : undefined
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
incept({icodes=undefined, icount=1, icode=MtrDex.Ed25519_Seed,
|
|
363
|
+
ncodes=undefined, ncount=1, ncode=MtrDex.Ed25519_Seed,
|
|
364
|
+
dcode=MtrDex.Blake3_256, algo=undefined, salt=undefined, stem=undefined, tier=undefined,
|
|
365
|
+
rooted=true, transferable=true, temp=false }: InceptArgs): [Array<Verfer>, Array<Diger>] {
|
|
366
|
+
|
|
367
|
+
if (rooted && algo == undefined) {
|
|
368
|
+
algo = this.algo
|
|
369
|
+
}
|
|
370
|
+
if (rooted && salt == undefined) {
|
|
371
|
+
salt = this.salt
|
|
372
|
+
}
|
|
373
|
+
if (rooted && tier == undefined) {
|
|
374
|
+
tier = this.tier
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
let pidx = this.pidx
|
|
378
|
+
let ridx = 0
|
|
379
|
+
let kidx = 0
|
|
380
|
+
|
|
381
|
+
let creator = new Creatory(algo).make(salt, tier, stem)
|
|
382
|
+
|
|
383
|
+
if (icodes == undefined) {
|
|
384
|
+
if (icount < 0) {
|
|
385
|
+
throw new Error(`Invalid icount=${icount} must be >= 0.`)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
icodes = new Array<string>(icount).fill(icode)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
let isigners = creator.create(icodes, 0, MtrDex.Ed25519_Seed, transferable, pidx, ridx, kidx, temp)
|
|
392
|
+
let verfers = Array.from(isigners, (signer: Signer) => signer.verfer)
|
|
393
|
+
|
|
394
|
+
if (ncodes == undefined) {
|
|
395
|
+
if (ncount < 0) {
|
|
396
|
+
throw new Error(`Invalid ncount=${ncount} must be >= 0.`)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
ncodes = new Array<string>(ncount).fill(ncode)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
let nsigners = creator.create(ncodes, 0, MtrDex.Ed25519_Seed, transferable, pidx, ridx+1, kidx+icodes.length,
|
|
403
|
+
temp)
|
|
404
|
+
|
|
405
|
+
let digers = Array.from(nsigners, (signer: Signer) => new Diger({code: dcode}, signer.verfer.qb64b))
|
|
406
|
+
|
|
407
|
+
let pp = new PrePrm()
|
|
408
|
+
pp.pidx = pidx!
|
|
409
|
+
pp.algo = algo!
|
|
410
|
+
pp.salt = this._encrypter?.encrypt(b(creator.salt)).qb64
|
|
411
|
+
pp.stem = creator.stem
|
|
412
|
+
pp.tier = creator.tier
|
|
413
|
+
|
|
414
|
+
let dt = new Date().toString()
|
|
415
|
+
let nw = new PubLot()
|
|
416
|
+
nw.pubs = Array.from(verfers, (verfer: Verfer) => verfer.qb64)
|
|
417
|
+
nw.ridx = ridx
|
|
418
|
+
nw.kidx = kidx
|
|
419
|
+
nw.dt = dt
|
|
420
|
+
|
|
421
|
+
let nt = new PubLot()
|
|
422
|
+
nt.pubs = Array.from(nsigners, (signer: Signer) => signer.verfer.qb64)
|
|
423
|
+
nt.ridx = ridx + 1
|
|
424
|
+
nt.kidx = kidx + icodes.length
|
|
425
|
+
nt.dt = dt
|
|
426
|
+
|
|
427
|
+
let ps = new PreSit()
|
|
428
|
+
ps.new = nw
|
|
429
|
+
ps.nxt = nt
|
|
430
|
+
|
|
431
|
+
let pre = verfers[0].qb64
|
|
432
|
+
if (!this.ks.putPres(pre, verfers[0].qb64b)) {
|
|
433
|
+
throw new Error(`Already incepted pre=${pre}.`)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (!this.ks.putPrms(pre, pp)) {
|
|
437
|
+
throw new Error(`Already incepted prm for pre=${pre}.`)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
this.pidx = pidx! + 1
|
|
441
|
+
|
|
442
|
+
if (!this.ks.putSits(pre, ps)) {
|
|
443
|
+
throw new Error(`Already incepted sit for pre=${pre}.`)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
isigners.forEach((signer: Signer) => {
|
|
447
|
+
this.ks.putPris(signer.verfer.qb64, signer, this._encrypter!)
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
let pubSet = new PubSet()
|
|
451
|
+
pubSet.pubs = ps.new.pubs
|
|
452
|
+
this.ks.putPubs(riKey(pre, ridx), pubSet)
|
|
453
|
+
|
|
454
|
+
nsigners.forEach((signer: Signer) => {
|
|
455
|
+
this.ks.putPris(signer.verfer.qb64, signer, this._encrypter!)
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
let nxtPubSet = new PubSet()
|
|
459
|
+
nxtPubSet.pubs = ps.nxt.pubs
|
|
460
|
+
this.ks.putPubs(riKey(pre, ridx+1), nxtPubSet)
|
|
461
|
+
|
|
462
|
+
return [verfers, digers]
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
move(old: string, gnu: string) {
|
|
466
|
+
if (old == gnu) {
|
|
467
|
+
return
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (this.ks.getPres(old) == undefined) {
|
|
471
|
+
throw new Error(`Nonexistent old pre=${old}, nothing to assign.`)
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (this.ks.getPres(gnu) != undefined) {
|
|
475
|
+
throw new Error(`Preexistent new pre=${gnu} may not clobber.`)
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
let oldprm = this.ks.getPrms(old)
|
|
479
|
+
if (oldprm == undefined) {
|
|
480
|
+
throw new Error(`Nonexistent old prm for pre=${old}, nothing to move.`)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (this.ks.getPrms(gnu) != undefined) {
|
|
484
|
+
throw new Error(`Preexistent new prm for pre=${gnu} may not clobber.`)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
let oldsit = this.ks.getSits(old)
|
|
488
|
+
if (oldsit == undefined) {
|
|
489
|
+
throw new Error(`Nonexistent old sit for pre=${old}, nothing to move.`)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (this.ks.getSits(gnu) != undefined) {
|
|
493
|
+
throw new Error(`Preexistent new sit for pre=${gnu} may not clobber.`)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (!this.ks.putPrms(gnu, oldprm)) {
|
|
497
|
+
throw new Error(`Failed moving prm from old pre=${old} to new pre=${gnu}.`)
|
|
498
|
+
} else {
|
|
499
|
+
this.ks.remPrms(old)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (!this.ks.putSits(gnu, oldsit)) {
|
|
503
|
+
throw new Error(`Failed moving sit from old pre=${old} to new pre=${gnu}.`)
|
|
504
|
+
} else {
|
|
505
|
+
this.ks.remSits(old)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
let i = 0
|
|
509
|
+
while (true) {
|
|
510
|
+
let pl = this.ks.getPubs(riKey(old, i))
|
|
511
|
+
if (pl == undefined) {
|
|
512
|
+
break
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (!this.ks.putPubs(riKey(gnu, i), pl)) {
|
|
516
|
+
throw new Error(`Failed moving pubs at pre=${old} ri=${i} to new pre=${gnu}`)
|
|
517
|
+
}
|
|
518
|
+
i = i + 1
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (!this.ks.pinPres(old, b(gnu))) {
|
|
522
|
+
throw new Error(`Failed assiging new pre=${gnu} to old pre=${old}.`)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (!this.ks.putPres(gnu, b(gnu))) {
|
|
526
|
+
throw new Error(`Failed assiging new pre=${gnu}.`)
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
rotate({pre, ncodes=undefined, ncount=1, ncode=MtrDex.Ed25519_Seed, dcode=MtrDex.Blake3_256,
|
|
531
|
+
transferable=true, temp=false, erase=true}:RotateArgs) {
|
|
532
|
+
let pp = this.ks.getPrms(pre)
|
|
533
|
+
if (pp == undefined) {
|
|
534
|
+
throw new Error(`Attempt to rotate nonexistent pre=${pre}.`)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
let ps = this.ks.getSits(pre)
|
|
538
|
+
if (ps == undefined) {
|
|
539
|
+
throw new Error(`Attempt to rotate nonexistent pre=${pre}.`)
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (ps.nxt.pubs == undefined) {
|
|
543
|
+
throw new Error(`Attempt to rotate nontransferable pre=${pre}.`)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
let old = ps.old
|
|
547
|
+
ps.old = ps.new
|
|
548
|
+
ps.new = ps.nxt
|
|
549
|
+
|
|
550
|
+
if (this.aeid != undefined && this.decrypter == undefined) {
|
|
551
|
+
throw new Error("Unauthorized decryption attempt. Aeid but no decrypter.")
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
let verfers = new Array<Verfer>()
|
|
555
|
+
ps.new.pubs.forEach((pub) => {
|
|
556
|
+
let signer = this.ks.getPris(pub, this.decrypter)
|
|
557
|
+
if (signer == undefined) {
|
|
558
|
+
throw new Error(`Missing prikey in db for pubkey=${pub}`)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
verfers.push(signer.verfer)
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
let salt = pp.salt
|
|
565
|
+
if (salt != undefined && salt != "") {
|
|
566
|
+
salt = this.decrypter.decrypt(b(salt)).qb64
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
let creator = new Creatory(pp.algo).make(salt, pp.stem, pp.tier)
|
|
570
|
+
|
|
571
|
+
if (ncodes == undefined) {
|
|
572
|
+
if (ncount < 0) {
|
|
573
|
+
throw new Error(`Invalid count=${ncount} must be >= 0`)
|
|
574
|
+
}
|
|
575
|
+
ncodes = new Array<string>(ncount).fill(ncode)
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
let pidx = pp.pidx
|
|
579
|
+
let ridx = ps.new.ridx + 1
|
|
580
|
+
let kidx = ps.nxt.kidx + ps.new.pubs.length
|
|
581
|
+
|
|
582
|
+
let signers = creator.create(ncodes, 0, undefined, transferable, pidx, ridx, kidx, temp)
|
|
583
|
+
let digers = Array.from(signers, (signer: Signer) => new Diger({code: dcode}, signer.verfer.qb64b))
|
|
584
|
+
|
|
585
|
+
let dt = new Date().toString()
|
|
586
|
+
ps.nxt = new PubLot()
|
|
587
|
+
ps.nxt.pubs = Array.from(signers, (signer: Signer) => signer.verfer.qb64)
|
|
588
|
+
ps.nxt.ridx = ridx
|
|
589
|
+
ps.nxt.kidx = kidx
|
|
590
|
+
ps.nxt.dt = dt
|
|
591
|
+
|
|
592
|
+
if (!this.ks.pinSits(pre, ps)) {
|
|
593
|
+
throw new Error(`Problem updating pubsit db for pre=${pre}.`)
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
signers.forEach((signer: Signer) => {
|
|
597
|
+
this.ks.putPris(signer.verfer.qb64, signer, this.encrypter)
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
let newPs = new PubSet()
|
|
601
|
+
newPs.pubs = ps.nxt.pubs
|
|
602
|
+
this.ks.putPubs(riKey(pre, ps.nxt.ridx), newPs)
|
|
603
|
+
|
|
604
|
+
if (erase) {
|
|
605
|
+
old.pubs.forEach((pub) => {
|
|
606
|
+
this.ks.remPubs(pub)
|
|
607
|
+
})
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return [verfers, digers]
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
sign({ser, pubs=undefined, verfers=undefined, indexed=true, indices=undefined, ondices=undefined}: SignArgs) {
|
|
614
|
+
let signers = new Array<Signer>()
|
|
615
|
+
|
|
616
|
+
if (pubs == undefined && verfers == undefined) {
|
|
617
|
+
throw new Error("pubs or verfers required")
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (pubs != undefined) {
|
|
621
|
+
if (this.aeid != undefined && this.decrypter == undefined) {
|
|
622
|
+
throw new Error("Unauthorized decryption attempt. Aeid but no decrypter.")
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
pubs.forEach((pub) => {
|
|
626
|
+
let signer = this.ks.getPris(pub, this.decrypter)
|
|
627
|
+
if (signer == undefined) {
|
|
628
|
+
throw new Error(`Missing prikey in db for pubkey=${pub}`)
|
|
629
|
+
}
|
|
630
|
+
signers.push(signer)
|
|
631
|
+
})
|
|
632
|
+
} else {
|
|
633
|
+
verfers!.forEach((verfer: Verfer) => {
|
|
634
|
+
let signer = this.ks.getPris(verfer.qb64, this.decrypter)
|
|
635
|
+
if (signer == undefined) {
|
|
636
|
+
throw new Error(`Missing prikey in db for pubkey=${verfer.qb64}`)
|
|
637
|
+
}
|
|
638
|
+
signers.push(signer)
|
|
639
|
+
})
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (indices != undefined && indices.length != signers.length) {
|
|
643
|
+
throw new Error(`Mismatch indices length=${indices.length} and resultant signers length=${signers.length}`)
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (ondices != undefined && ondices.length != signers.length) {
|
|
647
|
+
throw new Error(`Mismatch ondices length=${ondices.length} and resultant signers length=${signers.length}`)
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (indexed) {
|
|
651
|
+
let sigers = new Array<Siger>()
|
|
652
|
+
signers.forEach((signer, idx) => {
|
|
653
|
+
let i
|
|
654
|
+
if (indices != undefined) {
|
|
655
|
+
i = indices[idx]
|
|
656
|
+
if (i < 0) {
|
|
657
|
+
throw new Error(`Invalid signing index = ${i}, not whole number.`)
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
i = idx
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
let o
|
|
664
|
+
if (ondices != undefined) {
|
|
665
|
+
o = ondices[idx]
|
|
666
|
+
if (o <= 0) {
|
|
667
|
+
throw new Error(`Invalid other signing index = {o}, not None or not whole number.`)
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
o = i
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
let only = o == undefined
|
|
674
|
+
sigers.push(signer.sign(ser, i, only, o) as Siger)
|
|
675
|
+
})
|
|
676
|
+
return sigers
|
|
677
|
+
} else {
|
|
678
|
+
let cigars = new Array<Cigar>()
|
|
679
|
+
signers.forEach((signer: Signer) => {
|
|
680
|
+
cigars.push(signer.sign(ser) as Cigar)
|
|
681
|
+
})
|
|
682
|
+
|
|
683
|
+
return cigars
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
export function riKey(pre: string, ridx: number) {
|
|
689
|
+
return pre + "." + ridx.toString(16).padStart(32, '0')
|
|
690
|
+
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export interface KeyStore {
|
|
694
|
+
getGbls(key: string): string | undefined
|
|
695
|
+
pinGbls(key: string, val: string): void
|
|
696
|
+
|
|
697
|
+
prmsElements(): Array<[string, PrePrm]>
|
|
698
|
+
getPrms(keys: string) :PrePrm | undefined
|
|
699
|
+
pinPrms(keys: string, data: PrePrm): void
|
|
700
|
+
putPrms(keys: string, data: PrePrm): boolean
|
|
701
|
+
remPrms(keys: string): boolean
|
|
702
|
+
|
|
703
|
+
prisElements(decrypter: Decrypter): Array<[string, Signer]>
|
|
704
|
+
getPris(keys: string, decrypter: Decrypter): Signer | undefined
|
|
705
|
+
pinPris(keys: string, data: Signer, encrypter: Encrypter): void
|
|
706
|
+
putPris(pubKey: string, signer: Signer, encrypter: Encrypter): boolean
|
|
707
|
+
|
|
708
|
+
getPres(pre: string): Uint8Array | undefined
|
|
709
|
+
putPres(pre: string, val: Uint8Array): boolean
|
|
710
|
+
pinPres(pre: string, val: Uint8Array): boolean
|
|
711
|
+
|
|
712
|
+
getSits(keys: string) :PreSit | undefined
|
|
713
|
+
putSits(pre: string, val: PreSit): boolean
|
|
714
|
+
pinSits(pre: string, val: PreSit): boolean
|
|
715
|
+
remSits(keys: string): boolean
|
|
716
|
+
|
|
717
|
+
getPubs(keys: string): PubSet | undefined
|
|
718
|
+
putPubs(keys: string, data: PubSet): boolean
|
|
719
|
+
remPubs(keys: string): boolean
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/*
|
|
723
|
+
In memory test implementation of Keeper key store
|
|
724
|
+
*/
|
|
725
|
+
class Keeper implements KeyStore {
|
|
726
|
+
private readonly _gbls: Map<string, string>
|
|
727
|
+
private readonly _pris: Map<string, Uint8Array>
|
|
728
|
+
private readonly _pres: Map<string, Uint8Array>
|
|
729
|
+
private readonly _prms: Map<string, PrePrm>
|
|
730
|
+
private readonly _sits: Map<string, PreSit>
|
|
731
|
+
private readonly _pubs: Map<string, PubSet>
|
|
732
|
+
|
|
733
|
+
constructor() {
|
|
734
|
+
this._gbls = new Map<string, string>()
|
|
735
|
+
this._pris = new Map<string, Uint8Array>()
|
|
736
|
+
this._pres = new Map<string, Uint8Array>()
|
|
737
|
+
this._prms = new Map<string, PrePrm>()
|
|
738
|
+
this._sits = new Map<string, PreSit>()
|
|
739
|
+
this._pubs = new Map<string, PubSet>()
|
|
740
|
+
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
getGbls(key: string): string | undefined {
|
|
744
|
+
return this._gbls.get(key)
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
pinGbls(key: string, val: string): void {
|
|
748
|
+
this._gbls.set(key, val)
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
prmsElements(): Array<[string, PrePrm]> {
|
|
752
|
+
let out = new Array<[string, PrePrm]>()
|
|
753
|
+
this._prms.forEach((value, key) => {
|
|
754
|
+
out.push([key, value])
|
|
755
|
+
})
|
|
756
|
+
|
|
757
|
+
return out
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
getPrms(keys: string) :PrePrm | undefined {
|
|
761
|
+
return this._prms.get(keys)
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
pinPrms(keys: string, data: PrePrm): void {
|
|
765
|
+
this._prms.set(keys, data)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
putPrms(keys: string, data: PrePrm): boolean {
|
|
769
|
+
if (this._prms.has(keys)) {
|
|
770
|
+
return false
|
|
771
|
+
}
|
|
772
|
+
this._prms.set(keys, data)
|
|
773
|
+
return true
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
remPrms(keys: string): boolean {
|
|
777
|
+
return this._prms.delete(keys)
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
prisElements(decrypter: Decrypter): Array<[string, Signer]> {
|
|
781
|
+
let out = new Array<[string, Signer]>()
|
|
782
|
+
this._pris.forEach(function(val, pubKey) {
|
|
783
|
+
let verfer = new Verfer({qb64: pubKey})
|
|
784
|
+
let signer = decrypter.decrypt(val, null, verfer.transferable)
|
|
785
|
+
out.push([pubKey, signer])
|
|
786
|
+
})
|
|
787
|
+
return out
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
pinPris(pubKey: string, signer: Signer, encrypter: Encrypter): void {
|
|
791
|
+
let cipher = encrypter.encrypt(null, signer)
|
|
792
|
+
this._pris.set(pubKey, cipher.qb64b)
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
putPris(pubKey: string, signer: Signer, encrypter: Encrypter): boolean {
|
|
796
|
+
if (this._pris.has(pubKey)) {
|
|
797
|
+
return false
|
|
798
|
+
}
|
|
799
|
+
let cipher = encrypter.encrypt(null, signer)
|
|
800
|
+
this._pris.set(pubKey, cipher.qb64b)
|
|
801
|
+
return true
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
getPris(pubKey: string, decrypter: Decrypter): Signer | undefined {
|
|
805
|
+
let val = this._pris.get(pubKey)
|
|
806
|
+
if (val == undefined) {
|
|
807
|
+
return undefined
|
|
808
|
+
}
|
|
809
|
+
let verfer = new Verfer({qb64: pubKey})
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
return decrypter.decrypt(val, null, verfer.transferable)
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
remPris(pubKey: string): void {
|
|
816
|
+
this._pris.delete(pubKey)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
getPres(pre: string): Uint8Array | undefined {
|
|
820
|
+
return this._pres.get(pre)
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
pinPres(pre: string, val: Uint8Array): boolean {
|
|
824
|
+
this._pres.set(pre, val)
|
|
825
|
+
return true
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
putPres(pre: string, val: Uint8Array): boolean {
|
|
829
|
+
if (this._pres.has(pre)) {
|
|
830
|
+
return false
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
this._pres.set(pre, val)
|
|
834
|
+
return true
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
getSits(keys: string) :PreSit | undefined {
|
|
838
|
+
return this._sits.get(keys)
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
putSits(pre: string, val: PreSit): boolean {
|
|
842
|
+
if (this._sits.has(pre)) {
|
|
843
|
+
return false
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
this._sits.set(pre, val)
|
|
847
|
+
return true
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
pinSits(pre: string, val: PreSit): boolean {
|
|
851
|
+
this._sits.set(pre, val)
|
|
852
|
+
return true
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
remSits(keys: string): boolean {
|
|
856
|
+
return this._sits.delete(keys)
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
getPubs(keys: string): PubSet | undefined {
|
|
860
|
+
return this._pubs.get(keys)
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
putPubs(keys: string, data: PubSet): boolean {
|
|
864
|
+
if (this._pubs.has(keys)) {
|
|
865
|
+
return false
|
|
866
|
+
}
|
|
867
|
+
this._pubs.set(keys, data)
|
|
868
|
+
return true
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
remPubs(keys: string): boolean {
|
|
872
|
+
return this._pubs.delete(keys)
|
|
873
|
+
}
|
|
874
|
+
}
|