oydid 0.4.4 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/oydid/basic.rb +149 -33
- data/lib/oydid/didcomm.rb +9 -9
- data/lib/oydid/log.rb +14 -7
- data/lib/oydid/vc.rb +264 -0
- data/lib/oydid.rb +283 -113
- data/spec/input/basic/sample_b16_dec.doc +1 -0
- data/spec/input/basic/{sample_enc.doc → sample_b16_enc.doc} +0 -0
- data/spec/input/basic/sample_b17_edec.doc +1 -0
- data/spec/input/basic/{sample_hash.doc → sample_b17_enc.doc} +0 -0
- data/spec/input/basic/sample_b32_dec.doc +1 -0
- data/spec/{output/basic/sample_dec.doc → input/basic/sample_b32_enc.doc} +0 -0
- data/spec/input/basic/{sample_dec.doc → sample_b58_dec.doc} +0 -0
- data/spec/input/basic/sample_b58_enc.doc +1 -0
- data/spec/input/basic/sample_b64_dec.doc +1 -0
- data/spec/input/basic/sample_b64_enc.doc +1 -0
- data/spec/input/basic/sample_blake2b-16_b16_hash.doc +1 -0
- data/spec/input/basic/sample_blake2b-32_b32_hash.doc +1 -0
- data/spec/input/basic/sample_blake2b-64_b58_hash.doc +1 -0
- data/spec/input/basic/sample_invalid2_readkey.doc +1 -1
- data/spec/input/basic/sample_invalid3_readkey.doc +1 -1
- data/spec/input/basic/sample_readkey.doc +1 -1
- data/spec/input/basic/sample_sha2-256_b58_hash.doc +1 -0
- data/spec/input/basic/sample_sha2-512_b58_hash.doc +1 -0
- data/spec/input/basic/sample_sha3-224_b64_hash.doc +1 -0
- data/spec/output/basic/sample_b16_dec.doc +1 -0
- data/spec/output/basic/sample_b16_enc.doc +1 -0
- data/spec/output/basic/sample_b17_edec.doc +2 -0
- data/spec/output/basic/sample_b17_enc.doc +1 -0
- data/spec/output/basic/sample_b32_dec.doc +1 -0
- data/spec/output/basic/sample_b32_enc.doc +1 -0
- data/spec/output/basic/sample_b58_dec.doc +1 -0
- data/spec/output/basic/{sample_enc.doc → sample_b58_enc.doc} +0 -0
- data/spec/output/basic/sample_b64_dec.doc +1 -0
- data/spec/output/basic/sample_b64_enc.doc +1 -0
- data/spec/output/basic/sample_blake2b-16_b16_hash.doc +1 -0
- data/spec/output/basic/sample_blake2b-32_b32_hash.doc +1 -0
- data/spec/output/basic/sample_blake2b-64_b58_hash.doc +1 -0
- data/spec/output/basic/{sample_hash.doc → sample_sha2-256_b58_hash.doc} +0 -0
- data/spec/output/basic/sample_sha2-512_b58_hash.doc +1 -0
- data/spec/output/basic/sample_sha3-224_b64_hash.doc +1 -0
- data/spec/oydid_spec.rb +95 -13
- metadata +72 -19
data/lib/oydid.rb
CHANGED
@@ -13,12 +13,17 @@ require 'json/canonicalization'
|
|
13
13
|
require 'oydid/basic'
|
14
14
|
require 'oydid/log'
|
15
15
|
require 'oydid/didcomm'
|
16
|
+
require 'oydid/vc'
|
16
17
|
|
17
18
|
class Oydid
|
18
19
|
|
19
20
|
LOCATION_PREFIX = "@"
|
20
21
|
DEFAULT_LOCATION = "https://oydid.ownyourdata.eu"
|
21
|
-
|
22
|
+
DEFAULT_DIGEST = "sha2-256"
|
23
|
+
SUPPORTED_DIGESTS = ["sha2-256", "sha2-512", "sha3-224", "sha3-256", "sha3-384", "sha3-512", "blake2b-16", "blake2b-32", "blake2b-64"]
|
24
|
+
DEFAULT_ENCODING = "base58btc"
|
25
|
+
SUPPORTED_ENCODINGS = ["base16", "base32", "base58btc", "base64"]
|
26
|
+
LOG_HASH_OPTIONS = {:digest => "sha2-256", :encode => "base58btc"}
|
22
27
|
|
23
28
|
# expected DID format: did:oyd:123
|
24
29
|
def self.read(did, options)
|
@@ -33,8 +38,6 @@ class Oydid
|
|
33
38
|
"message": "",
|
34
39
|
"verification": ""
|
35
40
|
}.transform_keys(&:to_s)
|
36
|
-
did_hash = did.delete_prefix("did:oyd:")
|
37
|
-
did10 = did_hash[0,10]
|
38
41
|
|
39
42
|
# get did location
|
40
43
|
did_location = ""
|
@@ -52,13 +55,20 @@ class Oydid
|
|
52
55
|
did = tmp[0]
|
53
56
|
did_location = tmp[1]
|
54
57
|
end
|
58
|
+
if did.include?(CGI.escape LOCATION_PREFIX)
|
59
|
+
tmp = did.split(CGI.escape LOCATION_PREFIX)
|
60
|
+
did = tmp[0]
|
61
|
+
did_location = tmp[1]
|
62
|
+
end
|
55
63
|
end
|
56
64
|
if did_location == ""
|
57
65
|
did_location = DEFAULT_LOCATION
|
58
66
|
end
|
67
|
+
did_hash = did.delete_prefix("did:oyd:")
|
68
|
+
did10 = did_hash[0,10]
|
59
69
|
|
60
70
|
# retrieve DID document
|
61
|
-
did_document = retrieve_document(
|
71
|
+
did_document = retrieve_document(did_hash, did10 + ".doc", did_location, options)
|
62
72
|
if did_document.first.nil?
|
63
73
|
return [nil, did_document.last]
|
64
74
|
end
|
@@ -140,15 +150,18 @@ class Oydid
|
|
140
150
|
end
|
141
151
|
|
142
152
|
def self.simulate_did(content, did, mode, options)
|
143
|
-
|
153
|
+
did_doc, did_key, did_log, msg = Oydid.generate_base(content, did, mode, options)
|
154
|
+
user_did = did_doc[:did]
|
144
155
|
return [user_did, msg]
|
145
156
|
end
|
146
|
-
|
157
|
+
|
147
158
|
def self.generate_base(content, did, mode, options)
|
148
159
|
# input validation
|
149
160
|
did_doc = JSON.parse(content.to_json) rescue nil
|
150
161
|
if did_doc.nil?
|
151
|
-
|
162
|
+
if !content.nil?
|
163
|
+
return [nil, nil, nil, "invalid payload"]
|
164
|
+
end
|
152
165
|
end
|
153
166
|
did_old = nil
|
154
167
|
log_old = nil
|
@@ -165,35 +178,35 @@ class Oydid
|
|
165
178
|
operation_mode = 2 # CREATE
|
166
179
|
if options[:doc_key].nil?
|
167
180
|
if options[:doc_enc].nil?
|
168
|
-
privateKey, msg = generate_private_key(options[:doc_pwd].to_s, 'ed25519-priv')
|
181
|
+
privateKey, msg = generate_private_key(options[:doc_pwd].to_s, 'ed25519-priv', options)
|
169
182
|
else
|
170
|
-
privateKey, msg = decode_private_key(options[:doc_enc].to_s)
|
183
|
+
privateKey, msg = decode_private_key(options[:doc_enc].to_s, options)
|
171
184
|
end
|
172
185
|
else
|
173
|
-
privateKey, msg = read_private_key(options[:doc_key].to_s)
|
186
|
+
privateKey, msg = read_private_key(options[:doc_key].to_s, options)
|
174
187
|
if privateKey.nil?
|
175
|
-
return [nil, nil, nil,
|
188
|
+
return [nil, nil, nil, "private document key not found"]
|
176
189
|
end
|
177
190
|
end
|
178
191
|
if options[:rev_key].nil?
|
179
192
|
if options[:rev_enc].nil?
|
180
|
-
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv')
|
193
|
+
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv', options)
|
181
194
|
else
|
182
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
195
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
183
196
|
end
|
184
197
|
else
|
185
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
198
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
186
199
|
if revocationKey.nil?
|
187
|
-
return [nil, nil, nil,
|
200
|
+
return [nil, nil, nil, "private revocation key not found"]
|
188
201
|
end
|
189
202
|
end
|
190
203
|
else # mode == "update" => read information
|
191
204
|
did_info, msg = read(did, options)
|
192
205
|
if did_info.nil?
|
193
|
-
return [nil, nil, nil,
|
206
|
+
return [nil, nil, nil, "cannot resolve DID (on updating DID)"]
|
194
207
|
end
|
195
208
|
if did_info["error"] != 0
|
196
|
-
return [nil, nil, nil,
|
209
|
+
return [nil, nil, nil, did_info["message"].to_s]
|
197
210
|
end
|
198
211
|
|
199
212
|
did = did_info["did"]
|
@@ -215,75 +228,75 @@ class Oydid
|
|
215
228
|
if options[:old_doc_key].nil?
|
216
229
|
if options[:old_doc_enc].nil?
|
217
230
|
if options[:old_doc_pwd].nil?
|
218
|
-
privateKey_old = read_private_storage(did10_old + "_private_key.
|
231
|
+
privateKey_old = read_private_storage(did10_old + "_private_key.enc")
|
219
232
|
else
|
220
|
-
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, 'ed25519-priv')
|
233
|
+
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, 'ed25519-priv', options)
|
221
234
|
end
|
222
235
|
else
|
223
|
-
privateKey_old, msg = decode_private_key(options[:old_doc_enc].to_s)
|
236
|
+
privateKey_old, msg = decode_private_key(options[:old_doc_enc].to_s, options)
|
224
237
|
end
|
225
238
|
else
|
226
|
-
privateKey_old, msg = read_private_key(options[:old_doc_key].to_s)
|
239
|
+
privateKey_old, msg = read_private_key(options[:old_doc_key].to_s, options)
|
227
240
|
end
|
241
|
+
|
228
242
|
if privateKey_old.nil?
|
229
|
-
return [nil, nil, nil,
|
243
|
+
return [nil, nil, nil, "invalid or missing old private document key"]
|
230
244
|
end
|
231
245
|
if options[:old_rev_key].nil?
|
232
246
|
if options[:old_rev_enc].nil?
|
233
247
|
if options[:old_rev_pwd].nil?
|
234
|
-
revocationKey_old = read_private_storage(did10_old + "_revocation_key.
|
248
|
+
revocationKey_old = read_private_storage(did10_old + "_revocation_key.enc")
|
235
249
|
else
|
236
|
-
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, 'ed25519-priv')
|
250
|
+
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, 'ed25519-priv', options)
|
237
251
|
end
|
238
252
|
else
|
239
|
-
revocationKey_old, msg = decode_private_key(options[:old_rev_enc].to_s)
|
253
|
+
revocationKey_old, msg = decode_private_key(options[:old_rev_enc].to_s, options)
|
240
254
|
end
|
241
255
|
else
|
242
|
-
revocationKey_old, msg = read_private_key(options[:old_rev_key].to_s)
|
256
|
+
revocationKey_old, msg = read_private_key(options[:old_rev_key].to_s, options)
|
243
257
|
end
|
244
258
|
if revocationKey_old.nil?
|
245
|
-
return [nil, nil, nil,
|
259
|
+
return [nil, nil, nil, "invalid or missing old private revocation key"]
|
246
260
|
end
|
247
|
-
|
248
261
|
# key management
|
249
262
|
if options[:doc_key].nil?
|
250
263
|
if options[:doc_enc].nil?
|
251
|
-
privateKey, msg = generate_private_key(options[:doc_pwd].to_s, 'ed25519-priv')
|
264
|
+
privateKey, msg = generate_private_key(options[:doc_pwd].to_s, 'ed25519-priv', options)
|
252
265
|
else
|
253
|
-
privateKey, msg = decode_private_key(options[:doc_enc].to_s)
|
266
|
+
privateKey, msg = decode_private_key(options[:doc_enc].to_s, options)
|
254
267
|
end
|
255
268
|
else
|
256
|
-
privateKey, msg = read_private_key(options[:doc_key].to_s)
|
269
|
+
privateKey, msg = read_private_key(options[:doc_key].to_s, options)
|
257
270
|
end
|
258
271
|
# if options[:rev_key].nil? && options[:rev_pwd].nil? && options[:rev_enc].nil?
|
259
272
|
# revocationLog = read_private_storage(did10 + "_revocation.json")
|
260
273
|
# if revocationLog.nil?
|
261
|
-
# return [nil, nil, nil,
|
274
|
+
# return [nil, nil, nil, "invalid or missing old revocation log"]
|
262
275
|
# end
|
263
276
|
# else
|
264
277
|
if options[:rev_key].nil?
|
265
278
|
if options[:rev_enc].nil?
|
266
279
|
if options[:rev_pwd].nil?
|
267
|
-
revocationKey, msg = generate_private_key("", 'ed25519-priv')
|
280
|
+
revocationKey, msg = generate_private_key("", 'ed25519-priv', options)
|
268
281
|
else
|
269
|
-
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv')
|
282
|
+
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv', options)
|
270
283
|
end
|
271
284
|
else
|
272
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
285
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
273
286
|
end
|
274
287
|
else
|
275
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
288
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
276
289
|
end
|
277
290
|
|
278
291
|
# re-build revocation document
|
279
292
|
did_old_doc = did_info["doc"]["doc"]
|
280
293
|
ts_old = did_info["log"].last["ts"]
|
281
|
-
publicKey_old = public_key(privateKey_old).first
|
282
|
-
pubRevoKey_old = public_key(revocationKey_old).first
|
294
|
+
publicKey_old = public_key(privateKey_old, options).first
|
295
|
+
pubRevoKey_old = public_key(revocationKey_old, options).first
|
283
296
|
did_key_old = publicKey_old + ":" + pubRevoKey_old
|
284
297
|
subDid = {"doc": did_old_doc, "key": did_key_old}.to_json
|
285
|
-
subDidHash =
|
286
|
-
signedSubDidHash = sign(subDidHash, revocationKey_old).first
|
298
|
+
subDidHash = multi_hash(canonical(subDid), LOG_HASH_OPTIONS).first
|
299
|
+
signedSubDidHash = sign(subDidHash, revocationKey_old, options).first
|
287
300
|
revocationLog = {
|
288
301
|
"ts": ts_old,
|
289
302
|
"op": 1, # REVOKE
|
@@ -292,38 +305,41 @@ class Oydid
|
|
292
305
|
# end
|
293
306
|
revoc_log = JSON.parse(revocationLog)
|
294
307
|
revoc_log["previous"] = [
|
295
|
-
|
296
|
-
|
308
|
+
multi_hash(canonical(log_old[did_info["doc_log_id"].to_i]), LOG_HASH_OPTIONS).first,
|
309
|
+
multi_hash(canonical(log_old[did_info["termination_log_id"].to_i]), LOG_HASH_OPTIONS).first
|
297
310
|
]
|
298
|
-
prev_hash = [
|
311
|
+
prev_hash = [multi_hash(canonical(revoc_log), LOG_HASH_OPTIONS).first]
|
299
312
|
end
|
300
|
-
|
301
|
-
|
302
|
-
pubRevoKey = public_key(revocationKey).first
|
313
|
+
publicKey = public_key(privateKey, options).first
|
314
|
+
pubRevoKey = public_key(revocationKey, options).first
|
303
315
|
did_key = publicKey + ":" + pubRevoKey
|
304
316
|
|
305
317
|
# build new revocation document
|
306
318
|
subDid = {"doc": did_doc, "key": did_key}.to_json
|
307
|
-
|
308
|
-
|
319
|
+
retVal = multi_hash(canonical(subDid), LOG_HASH_OPTIONS)
|
320
|
+
if retVal.first.nil?
|
321
|
+
return [nil, nil, nil, retVal.last]
|
322
|
+
end
|
323
|
+
subDidHash = retVal.first
|
324
|
+
signedSubDidHash = sign(subDidHash, revocationKey, options).first
|
309
325
|
r1 = { "ts": ts,
|
310
326
|
"op": 1, # REVOKE
|
311
327
|
"doc": subDidHash,
|
312
328
|
"sig": signedSubDidHash }.transform_keys(&:to_s)
|
313
329
|
|
314
330
|
# build termination log entry
|
315
|
-
l2_doc =
|
331
|
+
l2_doc = multi_hash(canonical(r1), LOG_HASH_OPTIONS).first
|
316
332
|
if !doc_location.nil?
|
317
333
|
l2_doc += LOCATION_PREFIX + doc_location.to_s
|
318
334
|
end
|
319
335
|
l2 = { "ts": ts,
|
320
336
|
"op": 0, # TERMINATE
|
321
337
|
"doc": l2_doc,
|
322
|
-
"sig": sign(l2_doc, privateKey).first,
|
338
|
+
"sig": sign(l2_doc, privateKey, options).first,
|
323
339
|
"previous": [] }.transform_keys(&:to_s)
|
324
340
|
|
325
341
|
# build actual DID document
|
326
|
-
log_str =
|
342
|
+
log_str = multi_hash(canonical(l2), LOG_HASH_OPTIONS).first
|
327
343
|
if !doc_location.nil?
|
328
344
|
log_str += LOCATION_PREFIX + doc_location.to_s
|
329
345
|
end
|
@@ -332,7 +348,7 @@ class Oydid
|
|
332
348
|
"log": log_str }.transform_keys(&:to_s)
|
333
349
|
|
334
350
|
# create DID
|
335
|
-
l1_doc =
|
351
|
+
l1_doc = multi_hash(canonical(didDocument), options).first
|
336
352
|
if !doc_location.nil?
|
337
353
|
l1_doc += LOCATION_PREFIX + doc_location.to_s
|
338
354
|
end
|
@@ -345,13 +361,13 @@ class Oydid
|
|
345
361
|
"ts": ts,
|
346
362
|
"op": 4, # CLONE
|
347
363
|
"doc": l1_doc,
|
348
|
-
"sig": sign(l1_doc, privateKey).first,
|
364
|
+
"sig": sign(l1_doc, privateKey, options).first,
|
349
365
|
"previous": [options[:previous_clone].to_s]
|
350
366
|
}
|
351
367
|
retVal = HTTParty.post(options[:source_location] + "/log/" + options[:source_did],
|
352
368
|
headers: { 'Content-Type' => 'application/json' },
|
353
369
|
body: {"log": new_log}.to_json )
|
354
|
-
prev_hash = [
|
370
|
+
prev_hash = [multi_hash(canonical(new_log), LOG_HASH_OPTIONS).first]
|
355
371
|
end
|
356
372
|
|
357
373
|
# build creation log entry
|
@@ -359,17 +375,40 @@ class Oydid
|
|
359
375
|
l1 = { "ts": ts,
|
360
376
|
"op": operation_mode, # UPDATE
|
361
377
|
"doc": l1_doc,
|
362
|
-
"sig": sign(l1_doc, privateKey_old).first,
|
378
|
+
"sig": sign(l1_doc, privateKey_old, options).first,
|
363
379
|
"previous": prev_hash }.transform_keys(&:to_s)
|
364
380
|
else
|
365
381
|
l1 = { "ts": ts,
|
366
382
|
"op": operation_mode, # CREATE
|
367
383
|
"doc": l1_doc,
|
368
|
-
"sig": sign(l1_doc, privateKey).first,
|
384
|
+
"sig": sign(l1_doc, privateKey, options).first,
|
369
385
|
"previous": prev_hash }.transform_keys(&:to_s)
|
370
386
|
end
|
371
387
|
|
372
|
-
|
388
|
+
# did, didDocument, revoc_log, l1, l2, r1, privateKey, revocationKey, did_old, log_old, msg = Oydid.generate_base(content, "", "create", options)
|
389
|
+
# did_doc = [did, didDocument, did_old]
|
390
|
+
# did_log = [revoc_log, l1, l2, r1, log_old]
|
391
|
+
# did_key = [privateKey, revocationKey]
|
392
|
+
|
393
|
+
did_doc = {
|
394
|
+
:did => did,
|
395
|
+
:didDocument => didDocument,
|
396
|
+
:did_old => did_old
|
397
|
+
}
|
398
|
+
did_log = {
|
399
|
+
:revoc_log => revoc_log,
|
400
|
+
:l1 => l1,
|
401
|
+
:l2 => l2,
|
402
|
+
:r1 => r1,
|
403
|
+
:log_old => log_old
|
404
|
+
}
|
405
|
+
did_key = {
|
406
|
+
:privateKey => privateKey,
|
407
|
+
:revocationKey => revocationKey
|
408
|
+
}
|
409
|
+
|
410
|
+
return [did_doc, did_key, did_log, ""]
|
411
|
+
# return [did, didDocument, revoc_log, l1, l2, r1, privateKey, revocationKey, did_old, log_old, ""]
|
373
412
|
end
|
374
413
|
|
375
414
|
def self.publish(did, didDocument, logs, options)
|
@@ -415,11 +454,22 @@ class Oydid
|
|
415
454
|
end
|
416
455
|
|
417
456
|
def self.write(content, did, mode, options)
|
418
|
-
|
457
|
+
did_doc, did_key, did_log, msg = generate_base(content, did, mode, options)
|
458
|
+
did = did_doc[:did]
|
459
|
+
didDocument = did_doc[:didDocument]
|
460
|
+
did_old = did_doc[:did_old]
|
461
|
+
revoc_log = did_log[:revoc_log]
|
462
|
+
l1 = did_log[:l1]
|
463
|
+
l2 = did_log[:l2]
|
464
|
+
r1 = did_log[:r1]
|
465
|
+
log_old = did_log[:log_old]
|
466
|
+
privateKey = did_key[:privateKey]
|
467
|
+
revocationKey = did_key[:revocationKey]
|
468
|
+
# did, didDocument, revoc_log, l1, l2, r1, privateKey, revocationKey, did_old, log_old, msg = generate_base(content, did, mode, options)
|
469
|
+
|
419
470
|
if msg != ""
|
420
471
|
return [nil, msg]
|
421
472
|
end
|
422
|
-
|
423
473
|
did_hash = did.delete_prefix("did:oyd:")
|
424
474
|
did10 = did_hash[0,10]
|
425
475
|
did_old_hash = did_old.delete_prefix("did:oyd:") rescue nil
|
@@ -435,7 +485,6 @@ class Oydid
|
|
435
485
|
doc_location = DEFAULT_LOCATION
|
436
486
|
end
|
437
487
|
end
|
438
|
-
|
439
488
|
case doc_location.to_s
|
440
489
|
when /^http/
|
441
490
|
logs = [revoc_log, l1, l2].flatten.compact
|
@@ -463,8 +512,8 @@ class Oydid
|
|
463
512
|
retVal["revocation_key"] = revocationKey
|
464
513
|
retVal["revocation_log"] = r1
|
465
514
|
else
|
466
|
-
write_private_storage(privateKey, did10 + "_private_key.
|
467
|
-
write_private_storage(revocationKey, did10 + "_revocation_key.
|
515
|
+
write_private_storage(privateKey, did10 + "_private_key.enc")
|
516
|
+
write_private_storage(revocationKey, did10 + "_revocation_key.enc")
|
468
517
|
write_private_storage(r1.to_json, did10 + "_revocation.json")
|
469
518
|
end
|
470
519
|
|
@@ -509,15 +558,15 @@ class Oydid
|
|
509
558
|
if options[:old_doc_key].nil?
|
510
559
|
if options[:old_doc_enc].nil?
|
511
560
|
if options[:old_doc_pwd].nil?
|
512
|
-
privateKey_old = read_private_storage(did10_old + "_private_key.
|
561
|
+
privateKey_old = read_private_storage(did10_old + "_private_key.enc")
|
513
562
|
else
|
514
|
-
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, 'ed25519-priv')
|
563
|
+
privateKey_old, msg = generate_private_key(options[:old_doc_pwd].to_s, 'ed25519-priv', options)
|
515
564
|
end
|
516
565
|
else
|
517
|
-
privateKey_old, msg = decode_private_key(options[:old_doc_enc].to_s)
|
566
|
+
privateKey_old, msg = decode_private_key(options[:old_doc_enc].to_s, options)
|
518
567
|
end
|
519
568
|
else
|
520
|
-
privateKey_old, msg = read_private_key(options[:old_doc_key].to_s)
|
569
|
+
privateKey_old, msg = read_private_key(options[:old_doc_key].to_s, options)
|
521
570
|
end
|
522
571
|
if privateKey_old.nil?
|
523
572
|
return [nil, "invalid or missing old private document key"]
|
@@ -525,42 +574,42 @@ class Oydid
|
|
525
574
|
if options[:old_rev_key].nil?
|
526
575
|
if options[:old_rev_enc].nil?
|
527
576
|
if options[:old_rev_pwd].nil?
|
528
|
-
revocationKey_old = read_private_storage(did10_old + "_revocation_key.
|
577
|
+
revocationKey_old = read_private_storage(did10_old + "_revocation_key.enc")
|
529
578
|
else
|
530
|
-
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, 'ed25519-priv')
|
579
|
+
revocationKey_old, msg = generate_private_key(options[:old_rev_pwd].to_s, 'ed25519-priv', options)
|
531
580
|
end
|
532
581
|
else
|
533
|
-
revocationKey_old, msg = decode_private_key(options[:old_rev_enc].to_s)
|
582
|
+
revocationKey_old, msg = decode_private_key(options[:old_rev_enc].to_s, options)
|
534
583
|
end
|
535
584
|
else
|
536
|
-
revocationKey_old, msg = read_private_key(options[:old_rev_key].to_s)
|
585
|
+
revocationKey_old, msg = read_private_key(options[:old_rev_key].to_s, options)
|
537
586
|
end
|
538
587
|
if revocationKey_old.nil?
|
539
588
|
return [nil, "invalid or missing old private revocation key"]
|
540
589
|
end
|
541
590
|
|
542
591
|
if options[:rev_key].nil? && options[:rev_pwd].nil? && options[:rev_enc].nil?
|
543
|
-
revocationKey, msg = read_private_key(did10 + "_revocation_key.
|
592
|
+
revocationKey, msg = read_private_key(did10 + "_revocation_key.enc", options)
|
544
593
|
revocationLog = read_private_storage(did10 + "_revocation.json")
|
545
594
|
else
|
546
595
|
if options[:rev_pwd].nil?
|
547
596
|
if options[:rev_enc].nil?
|
548
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
597
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
549
598
|
else
|
550
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
599
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
551
600
|
end
|
552
601
|
else
|
553
|
-
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv')
|
602
|
+
revocationKey, msg = generate_private_key(options[:rev_pwd].to_s, 'ed25519-priv', options)
|
554
603
|
end
|
555
604
|
# re-build revocation document
|
556
605
|
did_old_doc = did_info["doc"]["doc"]
|
557
606
|
ts_old = did_info["log"].last["ts"]
|
558
|
-
publicKey_old = public_key(privateKey_old).first
|
559
|
-
pubRevoKey_old = public_key(revocationKey_old).first
|
607
|
+
publicKey_old = public_key(privateKey_old, options).first
|
608
|
+
pubRevoKey_old = public_key(revocationKey_old, options).first
|
560
609
|
did_key_old = publicKey_old + ":" + pubRevoKey_old
|
561
610
|
subDid = {"doc": did_old_doc, "key": did_key_old}.to_json
|
562
|
-
subDidHash =
|
563
|
-
signedSubDidHash = sign(subDidHash, revocationKey_old).first
|
611
|
+
subDidHash = multi_hash(canonical(subDid), LOG_HASH_OPTIONS).first
|
612
|
+
signedSubDidHash = sign(subDidHash, revocationKey_old, options).first
|
564
613
|
revocationLog = {
|
565
614
|
"ts": ts_old,
|
566
615
|
"op": 1, # REVOKE
|
@@ -574,8 +623,8 @@ class Oydid
|
|
574
623
|
|
575
624
|
revoc_log = JSON.parse(revocationLog)
|
576
625
|
revoc_log["previous"] = [
|
577
|
-
|
578
|
-
|
626
|
+
multi_hash(canonical(log_old[did_info["doc_log_id"].to_i]), LOG_HASH_OPTIONS).first,
|
627
|
+
multi_hash(canonical(log_old[did_info["termination_log_id"].to_i]), LOG_HASH_OPTIONS).first,
|
579
628
|
]
|
580
629
|
return [revoc_log, ""]
|
581
630
|
end
|
@@ -628,10 +677,16 @@ class Oydid
|
|
628
677
|
target_location = DEFAULT_LOCATION
|
629
678
|
end
|
630
679
|
if did.include?(LOCATION_PREFIX)
|
631
|
-
|
632
|
-
did =
|
633
|
-
source_location =
|
680
|
+
tmp = did.split(LOCATION_PREFIX)
|
681
|
+
did = tmp[0]
|
682
|
+
source_location = tmp[1]
|
634
683
|
end
|
684
|
+
if did.include?(CGI.escape LOCATION_PREFIX)
|
685
|
+
tmp = did.split(CGI.escape LOCATION_PREFIX)
|
686
|
+
did = tmp[0]
|
687
|
+
source_location = tmp[1]
|
688
|
+
end
|
689
|
+
|
635
690
|
if source_location.to_s == ""
|
636
691
|
source_location = DEFAULT_LOCATION
|
637
692
|
end
|
@@ -657,7 +712,7 @@ class Oydid
|
|
657
712
|
# write did to new location
|
658
713
|
options[:doc_location] = target_location
|
659
714
|
options[:log_location] = target_location
|
660
|
-
options[:previous_clone] =
|
715
|
+
options[:previous_clone] = multi_hash(canonical(source_log), LOG_HASH_OPTIONS).first + LOCATION_PREFIX + source_location
|
661
716
|
options[:source_location] = source_location
|
662
717
|
options[:source_did] = source_did["did"]
|
663
718
|
retVal, msg = write(source_did["doc"]["doc"], nil, "clone", options)
|
@@ -665,6 +720,122 @@ class Oydid
|
|
665
720
|
end
|
666
721
|
|
667
722
|
def self.w3c(did_info, options)
|
723
|
+
did = percent_encode(did_info["did"])
|
724
|
+
if !did.start_with?("did:oyd:")
|
725
|
+
did = "did:oyd:" + did
|
726
|
+
end
|
727
|
+
|
728
|
+
didDoc = did_info.transform_keys(&:to_s)["doc"]
|
729
|
+
pubDocKey = didDoc["key"].split(":")[0] rescue ""
|
730
|
+
pubRevKey = didDoc["key"].split(":")[1] rescue ""
|
731
|
+
|
732
|
+
wd = {}
|
733
|
+
if didDoc["doc"].is_a?(Hash)
|
734
|
+
if didDoc["doc"]["@context"].nil?
|
735
|
+
wd["@context"] = ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
736
|
+
else
|
737
|
+
if didDoc["doc"]["@context"].is_a?(Array)
|
738
|
+
wd["@context"] = ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"] + didDoc["doc"]["@context"]
|
739
|
+
else
|
740
|
+
wd["@context"] = ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1", didDoc["doc"]["@context"]]
|
741
|
+
end
|
742
|
+
didDoc["doc"].delete("@context")
|
743
|
+
end
|
744
|
+
else
|
745
|
+
wd["@context"] = ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
746
|
+
end
|
747
|
+
wd["id"] = percent_encode(did)
|
748
|
+
wd["verificationMethod"] = [{
|
749
|
+
"id": did + "#key-doc",
|
750
|
+
"type": "Ed25519VerificationKey2020",
|
751
|
+
"controller": did,
|
752
|
+
"publicKeyMultibase": pubDocKey
|
753
|
+
},{
|
754
|
+
"id": did + "#key-rev",
|
755
|
+
"type": "Ed25519VerificationKey2020",
|
756
|
+
"controller": did,
|
757
|
+
"publicKeyMultibase": pubRevKey
|
758
|
+
}]
|
759
|
+
|
760
|
+
equivalentIds = []
|
761
|
+
did_info["log"].each do |log|
|
762
|
+
if log["op"] == 2 || log["op"] == 3
|
763
|
+
eid = percent_encode("did:oyd:" + log["doc"])
|
764
|
+
if eid != did
|
765
|
+
equivalentIds << eid
|
766
|
+
end
|
767
|
+
end
|
768
|
+
end unless did_info["log"].nil?
|
769
|
+
if equivalentIds.length > 0
|
770
|
+
wd[:alsoKnownAs] = equivalentIds
|
771
|
+
end
|
772
|
+
|
773
|
+
if didDoc["doc"].is_a?(Hash) && !didDoc["doc"]["service"].nil?
|
774
|
+
location = options[:location]
|
775
|
+
if location.nil?
|
776
|
+
location = get_location(did_info["did"].to_s)
|
777
|
+
end
|
778
|
+
wd = wd.merge(didDoc["doc"])
|
779
|
+
wdf = wd["service"].first
|
780
|
+
wdf = { "id": did + "#payload",
|
781
|
+
"type": "Custom",
|
782
|
+
"serviceEndpoint": location }.merge(wdf)
|
783
|
+
wd["service"] = [wdf] + wd["service"].drop(1)
|
784
|
+
else
|
785
|
+
payload = nil
|
786
|
+
if didDoc["doc"].is_a?(Hash)
|
787
|
+
didDoc = didDoc["doc"]
|
788
|
+
if didDoc["authentication"].to_s != ""
|
789
|
+
wd["authentication"] = didDoc["authentication"]
|
790
|
+
didDoc.delete("authentication")
|
791
|
+
end
|
792
|
+
if didDoc["assertionMethod"].to_s != ""
|
793
|
+
wd["assertionMethod"] = didDoc["assertionMethod"]
|
794
|
+
didDoc.delete("assertionMethod")
|
795
|
+
end
|
796
|
+
if didDoc["keyAgreement"].to_s != ""
|
797
|
+
wd["keyAgreement"] = didDoc["keyAgreement"]
|
798
|
+
didDoc.delete("keyAgreement")
|
799
|
+
end
|
800
|
+
if didDoc["capabilityInvocation"].to_s != ""
|
801
|
+
wd["capabilityInvocation"] = didDoc["capabilityInvocation"]
|
802
|
+
didDoc.delete("capabilityInvocation")
|
803
|
+
end
|
804
|
+
if didDoc["capabilityDelegation"].to_s != ""
|
805
|
+
wd["capabilityDelegation"] = didDoc["capabilityDelegation"]
|
806
|
+
didDoc.delete("capabilityDelegation")
|
807
|
+
end
|
808
|
+
payload = didDoc
|
809
|
+
else
|
810
|
+
payload = didDoc["doc"]
|
811
|
+
end
|
812
|
+
if !payload.nil?
|
813
|
+
location = options[:location]
|
814
|
+
if location.nil?
|
815
|
+
location = get_location(did_info["did"].to_s)
|
816
|
+
end
|
817
|
+
if payload.is_a?(Array) &&
|
818
|
+
payload.length == 1 &&
|
819
|
+
payload.first.is_a?(Hash) &&
|
820
|
+
!payload.first["id"].nil? &&
|
821
|
+
!payload.first["type"].nil? &&
|
822
|
+
!payload.first["serviceEndpoint"].nil?
|
823
|
+
wd["service"] = payload
|
824
|
+
else
|
825
|
+
wd["service"] = [{
|
826
|
+
"id": did + "#payload",
|
827
|
+
"type": "Custom",
|
828
|
+
"serviceEndpoint": location,
|
829
|
+
"payload": payload
|
830
|
+
}]
|
831
|
+
end
|
832
|
+
end
|
833
|
+
end
|
834
|
+
return wd
|
835
|
+
end
|
836
|
+
|
837
|
+
|
838
|
+
def self.w3c_legacy(did_info, options)
|
668
839
|
did = did_info["did"]
|
669
840
|
if !did.start_with?("did:oyd:")
|
670
841
|
did = "did:oyd:" + did
|
@@ -675,8 +846,8 @@ class Oydid
|
|
675
846
|
pubRevKey = didDoc["key"].split(":")[1] rescue ""
|
676
847
|
|
677
848
|
wd = {}
|
678
|
-
wd["@context"] = "https://www.w3.org/ns/did/v1"
|
679
|
-
wd["id"] = did
|
849
|
+
wd["@context"] = ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
850
|
+
wd["id"] = percent_encode(did)
|
680
851
|
wd["verificationMethod"] = [{
|
681
852
|
"id": did + "#key-doc",
|
682
853
|
"type": "Ed25519VerificationKey2020",
|
@@ -689,47 +860,46 @@ class Oydid
|
|
689
860
|
"publicKeyMultibase": pubRevKey
|
690
861
|
}]
|
691
862
|
|
692
|
-
if didDoc["@context"]
|
863
|
+
if didDoc["@context"] == ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
693
864
|
didDoc.delete("@context")
|
694
865
|
end
|
695
|
-
if didDoc["doc"].
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
didDoc.
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
newDidDoc=[newDidDoc]
|
866
|
+
if !didDoc["doc"].nil?
|
867
|
+
newDidDoc = []
|
868
|
+
if didDoc.is_a?(Hash)
|
869
|
+
if didDoc["authentication"].to_s != ""
|
870
|
+
wd["authentication"] = didDoc["authentication"]
|
871
|
+
didDoc.delete("authentication")
|
872
|
+
end
|
873
|
+
if didDoc["service"].to_s != ""
|
874
|
+
if didDoc["service"].is_a?(Array)
|
875
|
+
newDidDoc = didDoc.dup
|
876
|
+
newDidDoc.delete("service")
|
877
|
+
if newDidDoc == {}
|
878
|
+
newDidDoc = []
|
879
|
+
else
|
880
|
+
if !newDidDoc.is_a?(Array)
|
881
|
+
newDidDoc=[newDidDoc]
|
882
|
+
end
|
713
883
|
end
|
884
|
+
newDidDoc << didDoc["service"]
|
885
|
+
newDidDoc = newDidDoc.flatten
|
886
|
+
else
|
887
|
+
newDidDoc = didDoc["service"]
|
714
888
|
end
|
715
|
-
newDidDoc << didDoc["service"]
|
716
|
-
newDidDoc = newDidDoc.flatten
|
717
889
|
else
|
718
|
-
newDidDoc = didDoc["
|
890
|
+
newDidDoc = didDoc["doc"]
|
719
891
|
end
|
720
892
|
else
|
721
|
-
newDidDoc = didDoc
|
893
|
+
newDidDoc = didDoc["doc"]
|
722
894
|
end
|
723
|
-
|
724
|
-
newDidDoc = didDoc
|
895
|
+
wd["service"] = newDidDoc
|
725
896
|
end
|
726
|
-
wd["service"] = newDidDoc
|
727
897
|
return wd
|
728
898
|
end
|
729
899
|
|
730
900
|
def self.fromW3C(didDocument, options)
|
731
901
|
didDocument = didDocument.transform_keys(&:to_s)
|
732
|
-
if didDocument["@context"]
|
902
|
+
if didDocument["@context"] == ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
733
903
|
didDocument.delete("@context")
|
734
904
|
end
|
735
905
|
didDocument
|