oydid 0.5.6 → 0.6.1
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.
- checksums.yaml +4 -4
- data/LICENSE +10 -18
- data/VERSION +1 -1
- data/lib/oydid/basic.rb +545 -58
- data/lib/oydid/didcomm.rb +58 -0
- data/lib/oydid/log.rb +16 -6
- data/lib/oydid/vc.rb +367 -61
- data/lib/oydid.rb +322 -143
- metadata +131 -37
data/lib/oydid.rb
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require 'simple_dag'
|
|
5
4
|
require 'jwt'
|
|
5
|
+
require 'jwt/eddsa'
|
|
6
|
+
require 'rdf'
|
|
7
|
+
require 'rdf/normalize'
|
|
8
|
+
require 'json'
|
|
9
|
+
require 'json/ld'
|
|
6
10
|
require 'rbnacl'
|
|
7
11
|
require 'ed25519'
|
|
12
|
+
require 'openssl'
|
|
8
13
|
require 'httparty'
|
|
9
14
|
require 'multibases'
|
|
10
|
-
require 'multihashes'
|
|
11
15
|
require 'multicodecs'
|
|
16
|
+
require 'simple_dag'
|
|
17
|
+
require 'securerandom'
|
|
12
18
|
require 'json/canonicalization'
|
|
13
19
|
require 'oydid/basic'
|
|
14
20
|
require 'oydid/log'
|
|
@@ -24,6 +30,8 @@ class Oydid
|
|
|
24
30
|
DEFAULT_ENCODING = "base58btc"
|
|
25
31
|
SUPPORTED_ENCODINGS = ["base16", "base32", "base58btc", "base64"]
|
|
26
32
|
LOG_HASH_OPTIONS = {:digest => "sha2-256", :encode => "base58btc"}
|
|
33
|
+
ED25519_SECURITY_SUITE = "https://w3id.org/security/suites/ed25519-2020/v1"
|
|
34
|
+
JWS_SECURITY_SUITE = "https://w3id.org/security/suites/jws-2020/v1"
|
|
27
35
|
DEFAULT_PUBLIC_RESOLVER = "https://dev.uniresolver.io/1.0/identifiers/"
|
|
28
36
|
|
|
29
37
|
# full Multicodecs table: https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
@@ -178,7 +186,8 @@ class Oydid
|
|
|
178
186
|
if !content.nil?
|
|
179
187
|
return [nil, nil, nil, "invalid payload"]
|
|
180
188
|
end
|
|
181
|
-
end
|
|
189
|
+
end
|
|
190
|
+
|
|
182
191
|
did_old = nil
|
|
183
192
|
log_old = nil
|
|
184
193
|
prev_hash = []
|
|
@@ -190,22 +199,73 @@ class Oydid
|
|
|
190
199
|
ts = options[:ts]
|
|
191
200
|
end
|
|
192
201
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
options[:cmsm2] = false
|
|
203
|
+
if options[:cmsm]
|
|
204
|
+
if did_doc["key"].nil?
|
|
205
|
+
return [nil, nil, nil, "CMSM requires public key"]
|
|
206
|
+
end
|
|
207
|
+
cmsm_keys = did_doc["key"].split(':')
|
|
208
|
+
did_doc.delete("key")
|
|
209
|
+
if did_doc == {}
|
|
210
|
+
did_doc = nil
|
|
211
|
+
end
|
|
212
|
+
if cmsm_keys.count == 1
|
|
213
|
+
publicKey = cmsm_keys.first
|
|
214
|
+
revocationKey, msg = generate_private_key("", options[:key_type]+'-priv', options)
|
|
215
|
+
pubRevoKey = public_key(revocationKey, options).first
|
|
216
|
+
else
|
|
217
|
+
return [nil, nil, nil, "CMSM with multiple keys is not yet supported"]
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# check if information for provided key already exists
|
|
221
|
+
payload, msg = check_cmsm(publicKey, options)
|
|
222
|
+
if !payload.nil? && !did_doc.nil? && !did_doc["opt"].nil?
|
|
223
|
+
if payload.is_a?(String)
|
|
224
|
+
payload = JSON.parse(payload) rescue nil
|
|
225
|
+
end
|
|
226
|
+
if payload.nil?
|
|
227
|
+
return [nil, nil, nil, "invalid persisted data in CMSM flow"]
|
|
228
|
+
end
|
|
229
|
+
did_doc = JSON.parse(did_doc.to_json)
|
|
230
|
+
if did_doc["opt"].nil?
|
|
231
|
+
if options[:sig].nil?
|
|
232
|
+
return [nil, nil, nil, "1missing signature in CMSM flow (sig)"]
|
|
233
|
+
end
|
|
234
|
+
l2_sig = options[:sig]
|
|
235
|
+
else
|
|
236
|
+
if did_doc["opt"]["sig"].nil?
|
|
237
|
+
return [nil, nil, nil, "2missing signature in CMSM flow (sig)"]
|
|
238
|
+
end
|
|
239
|
+
l2_sig = did_doc["opt"]["sig"]
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
options[:cmsm2] = true
|
|
243
|
+
privateKey = nil
|
|
244
|
+
|
|
245
|
+
revocationKey = payload["revocationKey"]
|
|
246
|
+
did_doc = payload["did_doc"]
|
|
247
|
+
did_key = payload["did_key"]
|
|
248
|
+
l2_doc = payload["l2_doc"]
|
|
249
|
+
r1 = payload["r1"]
|
|
250
|
+
end
|
|
251
|
+
else
|
|
252
|
+
# key management
|
|
253
|
+
tmp_did_hash = did.delete_prefix("did:oyd:") rescue ""
|
|
254
|
+
tmp_did10 = tmp_did_hash[0,10] + "_private_key.enc" rescue ""
|
|
255
|
+
privateKey, msg = getPrivateKey(options[:doc_enc], options[:doc_pwd], options[:doc_key], tmp_did10, options)
|
|
199
256
|
if privateKey.nil?
|
|
200
|
-
|
|
257
|
+
privateKey, msg = generate_private_key("", options[:key_type]+'-priv', options)
|
|
258
|
+
if privateKey.nil?
|
|
259
|
+
return [nil, nil, nil, "private document key not found"]
|
|
260
|
+
end
|
|
201
261
|
end
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
revocationKey, msg = getPrivateKey(options[:rev_enc], options[:rev_pwd], options[:rev_key], tmp_did10, options)
|
|
205
|
-
if revocationKey.nil?
|
|
206
|
-
revocationKey, msg = generate_private_key("", 'ed25519-priv', options)
|
|
262
|
+
tmp_did10 = tmp_did_hash[0,10] + "_revocation_key.enc" rescue ""
|
|
263
|
+
revocationKey, msg = getPrivateKey(options[:rev_enc], options[:rev_pwd], options[:rev_key], tmp_did10, options)
|
|
207
264
|
if revocationKey.nil?
|
|
208
|
-
|
|
265
|
+
revocationKey, msg = generate_private_key("", options[:key_type]+'-priv', options)
|
|
266
|
+
if revocationKey.nil?
|
|
267
|
+
return [nil, nil, nil, "private revocation key not found"]
|
|
268
|
+
end
|
|
209
269
|
end
|
|
210
270
|
end
|
|
211
271
|
|
|
@@ -239,12 +299,13 @@ class Oydid
|
|
|
239
299
|
log_old = did_info["log"]
|
|
240
300
|
|
|
241
301
|
# check if provided old keys are native DID keys or delegates ==================
|
|
242
|
-
|
|
243
|
-
old_privateKey, msg = getPrivateKey(options[:old_doc_enc], options[:old_doc_pwd], options[:old_doc_key],
|
|
244
|
-
|
|
245
|
-
old_revocationKey, msg = getPrivateKey(options[:old_rev_enc], options[:old_rev_pwd], options[:old_rev_key],
|
|
302
|
+
tmp_old_doc_did10 = did10_old + "_private_key.enc" rescue ""
|
|
303
|
+
old_privateKey, msg = getPrivateKey(options[:old_doc_enc], options[:old_doc_pwd], options[:old_doc_key], tmp_old_doc_did10, options)
|
|
304
|
+
tmp_old_rev_did10 = did10_old + "_revocation_key.enc" rescue ""
|
|
305
|
+
old_revocationKey, msg = getPrivateKey(options[:old_rev_enc], options[:old_rev_pwd], options[:old_rev_key], tmp_old_rev_did10, options)
|
|
246
306
|
old_publicDocKey = public_key(old_privateKey, {}).first
|
|
247
307
|
old_publicRevKey = public_key(old_revocationKey, {}).first
|
|
308
|
+
|
|
248
309
|
old_did_key = old_publicDocKey + ":" + old_publicRevKey
|
|
249
310
|
|
|
250
311
|
# compare old keys with existing DID Document & generate revocation record
|
|
@@ -299,49 +360,79 @@ class Oydid
|
|
|
299
360
|
]
|
|
300
361
|
prev_hash = [multi_hash(canonical(revoc_log), LOG_HASH_OPTIONS).first]
|
|
301
362
|
end
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
363
|
+
if !options[:cmsm2]
|
|
364
|
+
if !options[:cmsm]
|
|
365
|
+
publicKey = public_key(privateKey, options).first
|
|
366
|
+
pubRevoKey = public_key(revocationKey, options).first
|
|
367
|
+
end
|
|
368
|
+
did_key = publicKey + ":" + pubRevoKey
|
|
305
369
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
370
|
+
if options[:keyAgreement]
|
|
371
|
+
if did_doc.nil?
|
|
372
|
+
did_doc = {}
|
|
373
|
+
end
|
|
374
|
+
did_doc[:keyAgreement] = ["#key-doc"]
|
|
375
|
+
did_doc = did_doc.transform_keys(&:to_s)
|
|
309
376
|
end
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
did_doc =
|
|
377
|
+
if options[:x25519_keyAgreement]
|
|
378
|
+
if did_doc.nil?
|
|
379
|
+
did_doc = {}
|
|
380
|
+
end
|
|
381
|
+
did_doc[:keyAgreement] = [{
|
|
382
|
+
"id": "#key-doc-x25519",
|
|
383
|
+
"type": "X25519KeyAgreementKey2019",
|
|
384
|
+
"publicKeyMultibase": public_key(privateKey, options, 'x25519-pub').first
|
|
385
|
+
}]
|
|
386
|
+
did_doc = did_doc.transform_keys(&:to_s)
|
|
387
|
+
end
|
|
388
|
+
if options[:authentication]
|
|
389
|
+
if did_doc.nil?
|
|
390
|
+
did_doc = {}
|
|
391
|
+
end
|
|
392
|
+
did_doc[:authentication] = ["#key-doc"]
|
|
393
|
+
did_doc = did_doc.transform_keys(&:to_s)
|
|
320
394
|
end
|
|
321
|
-
did_doc[:authentication] = [{
|
|
322
|
-
"id": "#key-doc"
|
|
323
|
-
}]
|
|
324
|
-
did_doc = did_doc.transform_keys(&:to_s)
|
|
325
|
-
end
|
|
326
395
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
396
|
+
# build new revocation document
|
|
397
|
+
subDid = {"doc": did_doc, "key": did_key}.to_json
|
|
398
|
+
retVal = multi_hash(canonical(subDid), LOG_HASH_OPTIONS)
|
|
399
|
+
if retVal.first.nil?
|
|
400
|
+
return [nil, nil, nil, retVal.last]
|
|
401
|
+
end
|
|
402
|
+
subDidHash = retVal.first
|
|
403
|
+
signedSubDidHash = sign(subDidHash, revocationKey, LOG_HASH_OPTIONS).first
|
|
404
|
+
r1 = { "ts": ts,
|
|
405
|
+
"op": 1, # REVOKE
|
|
406
|
+
"doc": subDidHash,
|
|
407
|
+
"sig": signedSubDidHash }.transform_keys(&:to_s)
|
|
408
|
+
|
|
409
|
+
# build termination log entry
|
|
410
|
+
l2_doc = multi_hash(canonical(r1), LOG_HASH_OPTIONS).first
|
|
411
|
+
if !doc_location.nil?
|
|
412
|
+
l2_doc += LOCATION_PREFIX + doc_location.to_s
|
|
413
|
+
end
|
|
339
414
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
415
|
+
if options[:cmsm]
|
|
416
|
+
# persist data
|
|
417
|
+
payload = {
|
|
418
|
+
revocationKey: revocationKey,
|
|
419
|
+
did_doc: did_doc,
|
|
420
|
+
did_key: did_key,
|
|
421
|
+
l2_doc: l2_doc,
|
|
422
|
+
r1: r1
|
|
423
|
+
}
|
|
424
|
+
success, msg = persist_cmsm(publicKey, payload, options)
|
|
425
|
+
|
|
426
|
+
cmsm_doc = {
|
|
427
|
+
cmsm: true,
|
|
428
|
+
pk: publicKey,
|
|
429
|
+
sign: l2_doc
|
|
430
|
+
}
|
|
431
|
+
return [cmsm_doc, nil, r1, "cmsm"]
|
|
432
|
+
end
|
|
433
|
+
l2_sig = sign(l2_doc, privateKey, options).first
|
|
344
434
|
end
|
|
435
|
+
|
|
345
436
|
if options[:confirm_logs].nil?
|
|
346
437
|
previous_array = []
|
|
347
438
|
else
|
|
@@ -350,7 +441,7 @@ class Oydid
|
|
|
350
441
|
l2 = { "ts": ts,
|
|
351
442
|
"op": 0, # TERMINATE
|
|
352
443
|
"doc": l2_doc,
|
|
353
|
-
"sig":
|
|
444
|
+
"sig": l2_sig,
|
|
354
445
|
"previous": previous_array }.transform_keys(&:to_s)
|
|
355
446
|
|
|
356
447
|
# build actual DID document
|
|
@@ -387,11 +478,15 @@ class Oydid
|
|
|
387
478
|
|
|
388
479
|
# build creation log entry
|
|
389
480
|
log_revoke_encrypted_array = nil
|
|
481
|
+
l1_sig = nil
|
|
390
482
|
if operation_mode == 3 # UPDATE
|
|
483
|
+
if !options[:cmsm]
|
|
484
|
+
l1_sig = sign(l1_doc, old_privateKey, options).first
|
|
485
|
+
end
|
|
391
486
|
l1 = { "ts": ts,
|
|
392
487
|
"op": operation_mode, # UPDATE
|
|
393
488
|
"doc": l1_doc,
|
|
394
|
-
"sig":
|
|
489
|
+
"sig": l1_sig,
|
|
395
490
|
"previous": prev_hash }.transform_keys(&:to_s)
|
|
396
491
|
options[:confirm_logs].each do |el|
|
|
397
492
|
# read each log entry to check if it is a revocation delegation
|
|
@@ -407,10 +502,13 @@ class Oydid
|
|
|
407
502
|
end
|
|
408
503
|
end unless options[:confirm_logs].nil?
|
|
409
504
|
else
|
|
505
|
+
if !options[:cmsm]
|
|
506
|
+
l1_sig = sign(l1_doc, privateKey, options).first
|
|
507
|
+
end
|
|
410
508
|
l1 = { "ts": ts,
|
|
411
509
|
"op": operation_mode, # CREATE
|
|
412
510
|
"doc": l1_doc,
|
|
413
|
-
"sig":
|
|
511
|
+
"sig": l1_sig,
|
|
414
512
|
"previous": prev_hash }.transform_keys(&:to_s)
|
|
415
513
|
end
|
|
416
514
|
|
|
@@ -480,13 +578,69 @@ class Oydid
|
|
|
480
578
|
write_private_storage(didDocument.to_json, did10 + ".doc")
|
|
481
579
|
write_private_storage(did, did10 + ".did")
|
|
482
580
|
end
|
|
581
|
+
|
|
483
582
|
return [true, ""]
|
|
484
583
|
|
|
485
584
|
end
|
|
486
585
|
|
|
586
|
+
def self.persist_cmsm(pubkey, payload, options)
|
|
587
|
+
doc_location = options[:doc_location]
|
|
588
|
+
if doc_location.to_s == ""
|
|
589
|
+
doc_location = DEFAULT_LOCATION
|
|
590
|
+
end
|
|
591
|
+
doc_location = doc_location.sub("%3A%2F%2F","://").sub("%3A", ":")
|
|
592
|
+
|
|
593
|
+
my_body = {
|
|
594
|
+
pubkey: pubkey,
|
|
595
|
+
payload: payload.to_json
|
|
596
|
+
}
|
|
597
|
+
case doc_location.to_s
|
|
598
|
+
when /^http/
|
|
599
|
+
persist_url = doc_location.to_s + "/cmsm"
|
|
600
|
+
retVal = HTTParty.post(persist_url,
|
|
601
|
+
headers: { 'Content-Type' => 'application/json' },
|
|
602
|
+
body: my_body.to_json )
|
|
603
|
+
if retVal.code != 200
|
|
604
|
+
err_msg = retVal.parsed_response("error").to_s rescue "invalid response from " + doc_location.to_s + "/cmsm"
|
|
605
|
+
return [false, err_msg]
|
|
606
|
+
end
|
|
607
|
+
else
|
|
608
|
+
return [nil, "location not supported for persisting data in cmsm-flow"]
|
|
609
|
+
end
|
|
610
|
+
return [true, ""]
|
|
611
|
+
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
def self.check_cmsm(pubkey, options)
|
|
615
|
+
doc_location = options[:doc_location]
|
|
616
|
+
if doc_location.to_s == ""
|
|
617
|
+
doc_location = DEFAULT_LOCATION
|
|
618
|
+
end
|
|
619
|
+
doc_location = doc_location.sub("%3A%2F%2F","://").sub("%3A", ":")
|
|
620
|
+
|
|
621
|
+
case doc_location.to_s
|
|
622
|
+
when /^http/
|
|
623
|
+
retVal = HTTParty.get(doc_location + "/cmsm/" + pubkey)
|
|
624
|
+
if retVal.code != 200
|
|
625
|
+
msg = retVal.parsed_response["error"].to_s rescue ""
|
|
626
|
+
if msg.to_s == ""
|
|
627
|
+
msg = "invalid response from " + doc_location.to_s + "/cmsm/" + pubkey.to_s
|
|
628
|
+
end
|
|
629
|
+
return [nil, msg]
|
|
630
|
+
end
|
|
631
|
+
return [retVal.parsed_response.transform_keys(&:to_s), ""]
|
|
632
|
+
else
|
|
633
|
+
return [nil, "location not supported for querying data in cmsm-flow"]
|
|
634
|
+
end
|
|
635
|
+
return [payload, ""]
|
|
636
|
+
end
|
|
637
|
+
|
|
487
638
|
def self.write(content, did, mode, options)
|
|
488
639
|
did_doc, did_key, did_log, msg = generate_base(content, did, mode, options)
|
|
489
640
|
if msg != ""
|
|
641
|
+
if msg == "cmsm"
|
|
642
|
+
return [did_doc, 'cmsm']
|
|
643
|
+
end
|
|
490
644
|
return [nil, msg]
|
|
491
645
|
end
|
|
492
646
|
did = did_doc[:did]
|
|
@@ -517,6 +671,7 @@ class Oydid
|
|
|
517
671
|
doc_location = DEFAULT_LOCATION
|
|
518
672
|
end
|
|
519
673
|
end
|
|
674
|
+
|
|
520
675
|
case doc_location.to_s
|
|
521
676
|
when /^http/
|
|
522
677
|
logs = [revoc_log, l1, l2, r1_encrypted].flatten.compact
|
|
@@ -526,6 +681,7 @@ class Oydid
|
|
|
526
681
|
write_private_storage([log_old, revoc_log, l1, l2].flatten.compact.to_json, did10_old + ".log")
|
|
527
682
|
end
|
|
528
683
|
end
|
|
684
|
+
|
|
529
685
|
success, msg = publish(did, didDocument, logs, options)
|
|
530
686
|
|
|
531
687
|
if success
|
|
@@ -534,7 +690,7 @@ class Oydid
|
|
|
534
690
|
"did" => did.clone,
|
|
535
691
|
"doc" => didDocument.clone
|
|
536
692
|
}
|
|
537
|
-
doc_w3c =
|
|
693
|
+
doc_w3c = w3c(w3c_input, options)
|
|
538
694
|
didDocument = didDocumentBackup
|
|
539
695
|
retVal = {
|
|
540
696
|
"did" => did,
|
|
@@ -667,15 +823,16 @@ class Oydid
|
|
|
667
823
|
did10_old = did10.dup
|
|
668
824
|
log_old = did_info["log"]
|
|
669
825
|
|
|
826
|
+
msg = ""
|
|
670
827
|
if options[:old_doc_key].nil?
|
|
671
828
|
if options[:old_doc_enc].nil?
|
|
672
829
|
if options[:old_doc_pwd].nil?
|
|
673
830
|
privateKey_old = read_private_storage(did10_old + "_private_key.enc")
|
|
674
831
|
else
|
|
675
|
-
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, '
|
|
832
|
+
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, options[:key_type]+'-priv', options)
|
|
676
833
|
end
|
|
677
834
|
else
|
|
678
|
-
privateKey_old
|
|
835
|
+
privateKey_old = options[:old_doc_enc].to_s
|
|
679
836
|
end
|
|
680
837
|
else
|
|
681
838
|
privateKey_old, msg = read_private_key(options[:old_doc_key].to_s, options)
|
|
@@ -688,10 +845,10 @@ class Oydid
|
|
|
688
845
|
if options[:old_rev_pwd].nil?
|
|
689
846
|
revocationKey_old = read_private_storage(did10_old + "_revocation_key.enc")
|
|
690
847
|
else
|
|
691
|
-
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, '
|
|
848
|
+
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, options[:key_type]+'-priv', options)
|
|
692
849
|
end
|
|
693
850
|
else
|
|
694
|
-
revocationKey_old
|
|
851
|
+
revocationKey_old = options[:old_rev_enc].to_s
|
|
695
852
|
end
|
|
696
853
|
else
|
|
697
854
|
revocationKey_old, msg = read_private_key(options[:old_rev_key].to_s, options)
|
|
@@ -706,20 +863,21 @@ class Oydid
|
|
|
706
863
|
else
|
|
707
864
|
|
|
708
865
|
# check if provided old keys are native DID keys or delegates ==================
|
|
866
|
+
msg = ""
|
|
709
867
|
if options[:doc_key].nil?
|
|
710
868
|
if options[:doc_enc].nil?
|
|
711
|
-
old_privateKey, msg = generate_private_key(options[:old_doc_pwd].to_s, '
|
|
869
|
+
old_privateKey, msg = generate_private_key(options[:old_doc_pwd].to_s, options[:key_type]+'-priv', options)
|
|
712
870
|
else
|
|
713
|
-
old_privateKey
|
|
871
|
+
old_privateKey = options[:old_doc_enc].to_s
|
|
714
872
|
end
|
|
715
873
|
else
|
|
716
874
|
old_privateKey, msg = read_private_key(options[:old_doc_key].to_s, options)
|
|
717
875
|
end
|
|
718
876
|
if options[:rev_key].nil?
|
|
719
877
|
if options[:rev_enc].nil?
|
|
720
|
-
old_revocationKey, msg = generate_private_key(options[:old_rev_pwd].to_s, '
|
|
878
|
+
old_revocationKey, msg = generate_private_key(options[:old_rev_pwd].to_s, options[:key_type]+'-priv', options)
|
|
721
879
|
else
|
|
722
|
-
old_revocationKey
|
|
880
|
+
old_revocationKey = options[:old_rev_enc].to_s
|
|
723
881
|
end
|
|
724
882
|
else
|
|
725
883
|
old_revocationKey, msg = read_private_key(options[:old_rev_key].to_s, options)
|
|
@@ -772,30 +930,6 @@ class Oydid
|
|
|
772
930
|
return [nil, "cannot decrypt revocation log entry: " + msg]
|
|
773
931
|
end
|
|
774
932
|
end # compare old keys with existing DID Document
|
|
775
|
-
|
|
776
|
-
# if options[:rev_pwd].nil?
|
|
777
|
-
# if options[:rev_enc].nil?
|
|
778
|
-
# revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
|
779
|
-
# else
|
|
780
|
-
# revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
|
781
|
-
# end
|
|
782
|
-
# else
|
|
783
|
-
# revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv', options)
|
|
784
|
-
# end
|
|
785
|
-
# # re-build revocation document
|
|
786
|
-
# did_old_doc = did_info["doc"]["doc"]
|
|
787
|
-
# ts_old = did_info["log"].last["ts"]
|
|
788
|
-
# publicKey_old = public_key(privateKey_old, options).first
|
|
789
|
-
# pubRevoKey_old = public_key(revocationKey_old, options).first
|
|
790
|
-
# did_key_old = publicKey_old + ":" + pubRevoKey_old
|
|
791
|
-
# subDid = {"doc": did_old_doc, "key": did_key_old}.to_json
|
|
792
|
-
# subDidHash = multi_hash(canonical(subDid), LOG_HASH_OPTIONS).first
|
|
793
|
-
# signedSubDidHash = sign(subDidHash, revocationKey_old, options).first
|
|
794
|
-
# revocationLog = {
|
|
795
|
-
# "ts": ts_old,
|
|
796
|
-
# "op": 1, # REVOKE
|
|
797
|
-
# "doc": subDidHash,
|
|
798
|
-
# "sig": signedSubDidHash }.transform_keys(&:to_s).to_json
|
|
799
933
|
end
|
|
800
934
|
|
|
801
935
|
if revocationLog.nil?
|
|
@@ -997,38 +1131,89 @@ class Oydid
|
|
|
997
1131
|
end
|
|
998
1132
|
end
|
|
999
1133
|
|
|
1134
|
+
oyd_context = ["https://www.w3.org/ns/did/v1"]
|
|
1135
|
+
pubkey = multi_decode(pubDocKey).first
|
|
1136
|
+
if pubkey.bytes.length == 34
|
|
1137
|
+
code = pubkey.bytes.first
|
|
1138
|
+
digest = pubkey[-32..]
|
|
1139
|
+
else
|
|
1140
|
+
if pubkey.start_with?("\x80\x24".dup.force_encoding('ASCII-8BIT'))
|
|
1141
|
+
code = 4608 # Bytes 0x80 0x24 sind das Varint-Encoding des Multicodec-Codes 0x1200 (p256-pub)
|
|
1142
|
+
# 4608 == Oydid.read_varint("\x80$") oder "\x80\x24".force_encoding('ASCII-8BIT')
|
|
1143
|
+
else
|
|
1144
|
+
code = pubkey.unpack('n').first
|
|
1145
|
+
end
|
|
1146
|
+
digest = pubkey[-1*(pubkey.bytes.length-2)..]
|
|
1147
|
+
end
|
|
1148
|
+
case Multicodecs[code].name
|
|
1149
|
+
when 'ed25519-pub'
|
|
1150
|
+
oyd_context << "https://w3id.org/security/suites/ed25519-2020/v1"
|
|
1151
|
+
when 'p256-pub'
|
|
1152
|
+
oyd_context << "https://w3id.org/security/suites/jws-2020/v1"
|
|
1153
|
+
else
|
|
1154
|
+
return {"error": "unsupported key codec (" + Multicodecs[code].name.to_s + ")"}
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1000
1157
|
wd = {}
|
|
1001
1158
|
if didDoc["doc"].is_a?(Hash)
|
|
1002
1159
|
if didDoc["doc"]["@context"].nil?
|
|
1003
|
-
wd["@context"] =
|
|
1160
|
+
wd["@context"] = oyd_context
|
|
1004
1161
|
else
|
|
1005
1162
|
if didDoc["doc"]["@context"].is_a?(Array)
|
|
1006
|
-
wd["@context"] = (
|
|
1163
|
+
wd["@context"] = (oyd_context + didDoc["doc"]["@context"]).uniq
|
|
1007
1164
|
else
|
|
1008
|
-
|
|
1165
|
+
oyd_context << didDoc["doc"]["@context"]
|
|
1166
|
+
wd["@context"] = oyd_context.uniq
|
|
1009
1167
|
end
|
|
1010
1168
|
didDoc["doc"].delete("@context")
|
|
1011
1169
|
end
|
|
1012
1170
|
else
|
|
1013
|
-
wd["@context"] =
|
|
1171
|
+
wd["@context"] = oyd_context
|
|
1014
1172
|
end
|
|
1015
1173
|
wd["id"] = percent_encode(did)
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
"
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1174
|
+
case Multicodecs[code].name
|
|
1175
|
+
when 'ed25519-pub'
|
|
1176
|
+
wd["verificationMethod"] = [{
|
|
1177
|
+
"id": did + "#key-doc",
|
|
1178
|
+
"type": "Ed25519VerificationKey2020",
|
|
1179
|
+
"controller": did,
|
|
1180
|
+
"publicKeyMultibase": pubDocKey
|
|
1181
|
+
},{
|
|
1182
|
+
"id": did + "#key-rev",
|
|
1183
|
+
"type": "Ed25519VerificationKey2020",
|
|
1184
|
+
"controller": did,
|
|
1185
|
+
"publicKeyMultibase": pubRevKey
|
|
1186
|
+
}]
|
|
1187
|
+
when 'p256-pub'
|
|
1188
|
+
pubDocKey_jwk, msg = public_key_to_jwk(pubDocKey)
|
|
1189
|
+
if pubDocKey_jwk.nil?
|
|
1190
|
+
return {"error": "document key: " + msg.to_s}
|
|
1191
|
+
end
|
|
1192
|
+
pubRevKey_jwk, msg = public_key_to_jwk(pubRevKey)
|
|
1193
|
+
if pubRevKey_jwk.nil?
|
|
1194
|
+
return {"error": "revocation key: " + msg.to_s}
|
|
1195
|
+
end
|
|
1196
|
+
wd["verificationMethod"] = [{
|
|
1197
|
+
"id": did + "#key-doc",
|
|
1198
|
+
"type": "JsonWebKey2020",
|
|
1199
|
+
"controller": did,
|
|
1200
|
+
"publicKeyJwk": pubDocKey_jwk
|
|
1201
|
+
},{
|
|
1202
|
+
"id": did + "#key-rev",
|
|
1203
|
+
"type": "JsonWebKey2020",
|
|
1204
|
+
"controller": did,
|
|
1205
|
+
"publicKeyJwk": pubRevKey_jwk
|
|
1206
|
+
}]
|
|
1207
|
+
else
|
|
1208
|
+
return {"error": "unsupported key codec (" + Multicodecs[code].name.to_s + ")"}
|
|
1209
|
+
end
|
|
1210
|
+
|
|
1027
1211
|
if !delegateDocKeys.nil? && delegateDocKeys.count > 0
|
|
1028
1212
|
i = 0
|
|
1029
1213
|
wd["capabilityDelegation"] = []
|
|
1030
1214
|
delegateDocKeys.each do |key|
|
|
1031
1215
|
i += 1
|
|
1216
|
+
|
|
1032
1217
|
delegaton_object = {
|
|
1033
1218
|
"id": did + "#key-delegate-doc-" + i.to_s,
|
|
1034
1219
|
"type": "Ed25519VerificationKey2020",
|
|
@@ -1082,7 +1267,10 @@ class Oydid
|
|
|
1082
1267
|
end
|
|
1083
1268
|
wdf = { "id": did + "#payload",
|
|
1084
1269
|
"type": "Custom",
|
|
1085
|
-
"serviceEndpoint": location }.merge(wdf)
|
|
1270
|
+
"serviceEndpoint": location }.transform_keys(&:to_s).merge(wdf)
|
|
1271
|
+
if wdf["id"][0] == '#'
|
|
1272
|
+
wdf["id"] = did + wdf["id"]
|
|
1273
|
+
end
|
|
1086
1274
|
wd["service"] = [wdf] + wd["service"].drop(1)
|
|
1087
1275
|
end
|
|
1088
1276
|
else
|
|
@@ -1090,42 +1278,33 @@ class Oydid
|
|
|
1090
1278
|
if didDoc["doc"].is_a?(Hash)
|
|
1091
1279
|
if didDoc["doc"] != {}
|
|
1092
1280
|
didDoc = didDoc["doc"]
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
didDoc.delete("keyAgreement")
|
|
1281
|
+
# special handling for Verification Methods
|
|
1282
|
+
vms = [ "authentication",
|
|
1283
|
+
"assertionMethod",
|
|
1284
|
+
"keyAgreement",
|
|
1285
|
+
"capabilityInvocation",
|
|
1286
|
+
"capabilityDelegation" ]
|
|
1287
|
+
|
|
1288
|
+
vms.each do |vm|
|
|
1289
|
+
if didDoc[vm].to_s != ""
|
|
1290
|
+
new_entries = []
|
|
1291
|
+
didDoc[vm].each do |el|
|
|
1292
|
+
if el.is_a?(String)
|
|
1293
|
+
new_entries << percent_encode(did) + el
|
|
1294
|
+
else
|
|
1295
|
+
new_el = el.transform_keys(&:to_s)
|
|
1296
|
+
new_el["id"] = percent_encode(did) + new_el["id"]
|
|
1297
|
+
new_entries << new_el
|
|
1298
|
+
end
|
|
1299
|
+
end unless didDoc[vm].nil?
|
|
1300
|
+
if new_entries.length > 0
|
|
1301
|
+
wd[vm] = new_entries
|
|
1302
|
+
else
|
|
1303
|
+
wd[vm] = didDoc[vm]
|
|
1304
|
+
end
|
|
1305
|
+
didDoc.delete(vm)
|
|
1119
1306
|
end
|
|
1120
1307
|
end
|
|
1121
|
-
if didDoc["capabilityInvocation"].to_s != ""
|
|
1122
|
-
wd["capabilityInvocation"] = didDoc["capabilityInvocation"]
|
|
1123
|
-
didDoc.delete("capabilityInvocation")
|
|
1124
|
-
end
|
|
1125
|
-
if didDoc["capabilityDelegation"].to_s != ""
|
|
1126
|
-
wd["capabilityDelegation"] = didDoc["capabilityDelegation"]
|
|
1127
|
-
didDoc.delete("capabilityDelegation")
|
|
1128
|
-
end
|
|
1129
1308
|
if didDoc["alsoKnownAs"].to_s != ""
|
|
1130
1309
|
if didDoc["alsoKnownAs"].is_a?(Array)
|
|
1131
1310
|
dda = didDoc["alsoKnownAs"]
|