oydid 0.4.3 → 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 +204 -26
- data/lib/oydid/didcomm.rb +25 -6
- data/lib/oydid/log.rb +15 -7
- data/lib/oydid/vc.rb +264 -0
- data/lib/oydid.rb +286 -111
- 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
|
@@ -139,11 +149,19 @@ class Oydid
|
|
139
149
|
return write(content, did, "update", options)
|
140
150
|
end
|
141
151
|
|
152
|
+
def self.simulate_did(content, did, mode, options)
|
153
|
+
did_doc, did_key, did_log, msg = Oydid.generate_base(content, did, mode, options)
|
154
|
+
user_did = did_doc[:did]
|
155
|
+
return [user_did, msg]
|
156
|
+
end
|
157
|
+
|
142
158
|
def self.generate_base(content, did, mode, options)
|
143
159
|
# input validation
|
144
160
|
did_doc = JSON.parse(content.to_json) rescue nil
|
145
161
|
if did_doc.nil?
|
146
|
-
|
162
|
+
if !content.nil?
|
163
|
+
return [nil, nil, nil, "invalid payload"]
|
164
|
+
end
|
147
165
|
end
|
148
166
|
did_old = nil
|
149
167
|
log_old = nil
|
@@ -160,35 +178,35 @@ class Oydid
|
|
160
178
|
operation_mode = 2 # CREATE
|
161
179
|
if options[:doc_key].nil?
|
162
180
|
if options[:doc_enc].nil?
|
163
|
-
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)
|
164
182
|
else
|
165
|
-
privateKey, msg = decode_private_key(options[:doc_enc].to_s)
|
183
|
+
privateKey, msg = decode_private_key(options[:doc_enc].to_s, options)
|
166
184
|
end
|
167
185
|
else
|
168
|
-
privateKey, msg = read_private_key(options[:doc_key].to_s)
|
186
|
+
privateKey, msg = read_private_key(options[:doc_key].to_s, options)
|
169
187
|
if privateKey.nil?
|
170
|
-
return [nil, nil, nil,
|
188
|
+
return [nil, nil, nil, "private document key not found"]
|
171
189
|
end
|
172
190
|
end
|
173
191
|
if options[:rev_key].nil?
|
174
192
|
if options[:rev_enc].nil?
|
175
|
-
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)
|
176
194
|
else
|
177
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
195
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
178
196
|
end
|
179
197
|
else
|
180
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
198
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
181
199
|
if revocationKey.nil?
|
182
|
-
return [nil, nil, nil,
|
200
|
+
return [nil, nil, nil, "private revocation key not found"]
|
183
201
|
end
|
184
202
|
end
|
185
203
|
else # mode == "update" => read information
|
186
204
|
did_info, msg = read(did, options)
|
187
205
|
if did_info.nil?
|
188
|
-
return [nil, nil, nil,
|
206
|
+
return [nil, nil, nil, "cannot resolve DID (on updating DID)"]
|
189
207
|
end
|
190
208
|
if did_info["error"] != 0
|
191
|
-
return [nil, nil, nil,
|
209
|
+
return [nil, nil, nil, did_info["message"].to_s]
|
192
210
|
end
|
193
211
|
|
194
212
|
did = did_info["did"]
|
@@ -210,75 +228,75 @@ class Oydid
|
|
210
228
|
if options[:old_doc_key].nil?
|
211
229
|
if options[:old_doc_enc].nil?
|
212
230
|
if options[:old_doc_pwd].nil?
|
213
|
-
privateKey_old = read_private_storage(did10_old + "_private_key.
|
231
|
+
privateKey_old = read_private_storage(did10_old + "_private_key.enc")
|
214
232
|
else
|
215
|
-
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)
|
216
234
|
end
|
217
235
|
else
|
218
|
-
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)
|
219
237
|
end
|
220
238
|
else
|
221
|
-
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)
|
222
240
|
end
|
241
|
+
|
223
242
|
if privateKey_old.nil?
|
224
|
-
return [nil, nil, nil,
|
243
|
+
return [nil, nil, nil, "invalid or missing old private document key"]
|
225
244
|
end
|
226
245
|
if options[:old_rev_key].nil?
|
227
246
|
if options[:old_rev_enc].nil?
|
228
247
|
if options[:old_rev_pwd].nil?
|
229
|
-
revocationKey_old = read_private_storage(did10_old + "_revocation_key.
|
248
|
+
revocationKey_old = read_private_storage(did10_old + "_revocation_key.enc")
|
230
249
|
else
|
231
|
-
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)
|
232
251
|
end
|
233
252
|
else
|
234
|
-
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)
|
235
254
|
end
|
236
255
|
else
|
237
|
-
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)
|
238
257
|
end
|
239
258
|
if revocationKey_old.nil?
|
240
|
-
return [nil, nil, nil,
|
259
|
+
return [nil, nil, nil, "invalid or missing old private revocation key"]
|
241
260
|
end
|
242
|
-
|
243
261
|
# key management
|
244
262
|
if options[:doc_key].nil?
|
245
263
|
if options[:doc_enc].nil?
|
246
|
-
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)
|
247
265
|
else
|
248
|
-
privateKey, msg = decode_private_key(options[:doc_enc].to_s)
|
266
|
+
privateKey, msg = decode_private_key(options[:doc_enc].to_s, options)
|
249
267
|
end
|
250
268
|
else
|
251
|
-
privateKey, msg = read_private_key(options[:doc_key].to_s)
|
269
|
+
privateKey, msg = read_private_key(options[:doc_key].to_s, options)
|
252
270
|
end
|
253
271
|
# if options[:rev_key].nil? && options[:rev_pwd].nil? && options[:rev_enc].nil?
|
254
272
|
# revocationLog = read_private_storage(did10 + "_revocation.json")
|
255
273
|
# if revocationLog.nil?
|
256
|
-
# return [nil, nil, nil,
|
274
|
+
# return [nil, nil, nil, "invalid or missing old revocation log"]
|
257
275
|
# end
|
258
276
|
# else
|
259
277
|
if options[:rev_key].nil?
|
260
278
|
if options[:rev_enc].nil?
|
261
279
|
if options[:rev_pwd].nil?
|
262
|
-
revocationKey, msg = generate_private_key("", 'ed25519-priv')
|
280
|
+
revocationKey, msg = generate_private_key("", 'ed25519-priv', options)
|
263
281
|
else
|
264
|
-
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)
|
265
283
|
end
|
266
284
|
else
|
267
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
285
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
268
286
|
end
|
269
287
|
else
|
270
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
288
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
271
289
|
end
|
272
290
|
|
273
291
|
# re-build revocation document
|
274
292
|
did_old_doc = did_info["doc"]["doc"]
|
275
293
|
ts_old = did_info["log"].last["ts"]
|
276
|
-
publicKey_old = public_key(privateKey_old).first
|
277
|
-
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
|
278
296
|
did_key_old = publicKey_old + ":" + pubRevoKey_old
|
279
297
|
subDid = {"doc": did_old_doc, "key": did_key_old}.to_json
|
280
|
-
subDidHash =
|
281
|
-
signedSubDidHash = sign(subDidHash, revocationKey_old).first
|
298
|
+
subDidHash = multi_hash(canonical(subDid), LOG_HASH_OPTIONS).first
|
299
|
+
signedSubDidHash = sign(subDidHash, revocationKey_old, options).first
|
282
300
|
revocationLog = {
|
283
301
|
"ts": ts_old,
|
284
302
|
"op": 1, # REVOKE
|
@@ -287,38 +305,41 @@ class Oydid
|
|
287
305
|
# end
|
288
306
|
revoc_log = JSON.parse(revocationLog)
|
289
307
|
revoc_log["previous"] = [
|
290
|
-
|
291
|
-
|
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
|
292
310
|
]
|
293
|
-
prev_hash = [
|
311
|
+
prev_hash = [multi_hash(canonical(revoc_log), LOG_HASH_OPTIONS).first]
|
294
312
|
end
|
295
|
-
|
296
|
-
|
297
|
-
pubRevoKey = public_key(revocationKey).first
|
313
|
+
publicKey = public_key(privateKey, options).first
|
314
|
+
pubRevoKey = public_key(revocationKey, options).first
|
298
315
|
did_key = publicKey + ":" + pubRevoKey
|
299
316
|
|
300
317
|
# build new revocation document
|
301
318
|
subDid = {"doc": did_doc, "key": did_key}.to_json
|
302
|
-
|
303
|
-
|
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
|
304
325
|
r1 = { "ts": ts,
|
305
326
|
"op": 1, # REVOKE
|
306
327
|
"doc": subDidHash,
|
307
328
|
"sig": signedSubDidHash }.transform_keys(&:to_s)
|
308
329
|
|
309
330
|
# build termination log entry
|
310
|
-
l2_doc =
|
331
|
+
l2_doc = multi_hash(canonical(r1), LOG_HASH_OPTIONS).first
|
311
332
|
if !doc_location.nil?
|
312
333
|
l2_doc += LOCATION_PREFIX + doc_location.to_s
|
313
334
|
end
|
314
335
|
l2 = { "ts": ts,
|
315
336
|
"op": 0, # TERMINATE
|
316
337
|
"doc": l2_doc,
|
317
|
-
"sig": sign(l2_doc, privateKey).first,
|
338
|
+
"sig": sign(l2_doc, privateKey, options).first,
|
318
339
|
"previous": [] }.transform_keys(&:to_s)
|
319
340
|
|
320
341
|
# build actual DID document
|
321
|
-
log_str =
|
342
|
+
log_str = multi_hash(canonical(l2), LOG_HASH_OPTIONS).first
|
322
343
|
if !doc_location.nil?
|
323
344
|
log_str += LOCATION_PREFIX + doc_location.to_s
|
324
345
|
end
|
@@ -327,7 +348,7 @@ class Oydid
|
|
327
348
|
"log": log_str }.transform_keys(&:to_s)
|
328
349
|
|
329
350
|
# create DID
|
330
|
-
l1_doc =
|
351
|
+
l1_doc = multi_hash(canonical(didDocument), options).first
|
331
352
|
if !doc_location.nil?
|
332
353
|
l1_doc += LOCATION_PREFIX + doc_location.to_s
|
333
354
|
end
|
@@ -340,13 +361,13 @@ class Oydid
|
|
340
361
|
"ts": ts,
|
341
362
|
"op": 4, # CLONE
|
342
363
|
"doc": l1_doc,
|
343
|
-
"sig": sign(l1_doc, privateKey).first,
|
364
|
+
"sig": sign(l1_doc, privateKey, options).first,
|
344
365
|
"previous": [options[:previous_clone].to_s]
|
345
366
|
}
|
346
367
|
retVal = HTTParty.post(options[:source_location] + "/log/" + options[:source_did],
|
347
368
|
headers: { 'Content-Type' => 'application/json' },
|
348
369
|
body: {"log": new_log}.to_json )
|
349
|
-
prev_hash = [
|
370
|
+
prev_hash = [multi_hash(canonical(new_log), LOG_HASH_OPTIONS).first]
|
350
371
|
end
|
351
372
|
|
352
373
|
# build creation log entry
|
@@ -354,17 +375,40 @@ class Oydid
|
|
354
375
|
l1 = { "ts": ts,
|
355
376
|
"op": operation_mode, # UPDATE
|
356
377
|
"doc": l1_doc,
|
357
|
-
"sig": sign(l1_doc, privateKey_old).first,
|
378
|
+
"sig": sign(l1_doc, privateKey_old, options).first,
|
358
379
|
"previous": prev_hash }.transform_keys(&:to_s)
|
359
380
|
else
|
360
381
|
l1 = { "ts": ts,
|
361
382
|
"op": operation_mode, # CREATE
|
362
383
|
"doc": l1_doc,
|
363
|
-
"sig": sign(l1_doc, privateKey).first,
|
384
|
+
"sig": sign(l1_doc, privateKey, options).first,
|
364
385
|
"previous": prev_hash }.transform_keys(&:to_s)
|
365
386
|
end
|
366
387
|
|
367
|
-
|
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, ""]
|
368
412
|
end
|
369
413
|
|
370
414
|
def self.publish(did, didDocument, logs, options)
|
@@ -410,11 +454,22 @@ class Oydid
|
|
410
454
|
end
|
411
455
|
|
412
456
|
def self.write(content, did, mode, options)
|
413
|
-
|
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
|
+
|
414
470
|
if msg != ""
|
415
471
|
return [nil, msg]
|
416
472
|
end
|
417
|
-
|
418
473
|
did_hash = did.delete_prefix("did:oyd:")
|
419
474
|
did10 = did_hash[0,10]
|
420
475
|
did_old_hash = did_old.delete_prefix("did:oyd:") rescue nil
|
@@ -430,7 +485,6 @@ class Oydid
|
|
430
485
|
doc_location = DEFAULT_LOCATION
|
431
486
|
end
|
432
487
|
end
|
433
|
-
|
434
488
|
case doc_location.to_s
|
435
489
|
when /^http/
|
436
490
|
logs = [revoc_log, l1, l2].flatten.compact
|
@@ -458,8 +512,8 @@ class Oydid
|
|
458
512
|
retVal["revocation_key"] = revocationKey
|
459
513
|
retVal["revocation_log"] = r1
|
460
514
|
else
|
461
|
-
write_private_storage(privateKey, did10 + "_private_key.
|
462
|
-
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")
|
463
517
|
write_private_storage(r1.to_json, did10 + "_revocation.json")
|
464
518
|
end
|
465
519
|
|
@@ -504,15 +558,15 @@ class Oydid
|
|
504
558
|
if options[:old_doc_key].nil?
|
505
559
|
if options[:old_doc_enc].nil?
|
506
560
|
if options[:old_doc_pwd].nil?
|
507
|
-
privateKey_old = read_private_storage(did10_old + "_private_key.
|
561
|
+
privateKey_old = read_private_storage(did10_old + "_private_key.enc")
|
508
562
|
else
|
509
|
-
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)
|
510
564
|
end
|
511
565
|
else
|
512
|
-
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)
|
513
567
|
end
|
514
568
|
else
|
515
|
-
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)
|
516
570
|
end
|
517
571
|
if privateKey_old.nil?
|
518
572
|
return [nil, "invalid or missing old private document key"]
|
@@ -520,42 +574,42 @@ class Oydid
|
|
520
574
|
if options[:old_rev_key].nil?
|
521
575
|
if options[:old_rev_enc].nil?
|
522
576
|
if options[:old_rev_pwd].nil?
|
523
|
-
revocationKey_old = read_private_storage(did10_old + "_revocation_key.
|
577
|
+
revocationKey_old = read_private_storage(did10_old + "_revocation_key.enc")
|
524
578
|
else
|
525
|
-
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)
|
526
580
|
end
|
527
581
|
else
|
528
|
-
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)
|
529
583
|
end
|
530
584
|
else
|
531
|
-
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)
|
532
586
|
end
|
533
587
|
if revocationKey_old.nil?
|
534
588
|
return [nil, "invalid or missing old private revocation key"]
|
535
589
|
end
|
536
590
|
|
537
591
|
if options[:rev_key].nil? && options[:rev_pwd].nil? && options[:rev_enc].nil?
|
538
|
-
revocationKey, msg = read_private_key(did10 + "_revocation_key.
|
592
|
+
revocationKey, msg = read_private_key(did10 + "_revocation_key.enc", options)
|
539
593
|
revocationLog = read_private_storage(did10 + "_revocation.json")
|
540
594
|
else
|
541
595
|
if options[:rev_pwd].nil?
|
542
596
|
if options[:rev_enc].nil?
|
543
|
-
revocationKey, msg = read_private_key(options[:rev_key].to_s)
|
597
|
+
revocationKey, msg = read_private_key(options[:rev_key].to_s, options)
|
544
598
|
else
|
545
|
-
revocationKey, msg = decode_private_key(options[:rev_enc].to_s)
|
599
|
+
revocationKey, msg = decode_private_key(options[:rev_enc].to_s, options)
|
546
600
|
end
|
547
601
|
else
|
548
|
-
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)
|
549
603
|
end
|
550
604
|
# re-build revocation document
|
551
605
|
did_old_doc = did_info["doc"]["doc"]
|
552
606
|
ts_old = did_info["log"].last["ts"]
|
553
|
-
publicKey_old = public_key(privateKey_old).first
|
554
|
-
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
|
555
609
|
did_key_old = publicKey_old + ":" + pubRevoKey_old
|
556
610
|
subDid = {"doc": did_old_doc, "key": did_key_old}.to_json
|
557
|
-
subDidHash =
|
558
|
-
signedSubDidHash = sign(subDidHash, revocationKey_old).first
|
611
|
+
subDidHash = multi_hash(canonical(subDid), LOG_HASH_OPTIONS).first
|
612
|
+
signedSubDidHash = sign(subDidHash, revocationKey_old, options).first
|
559
613
|
revocationLog = {
|
560
614
|
"ts": ts_old,
|
561
615
|
"op": 1, # REVOKE
|
@@ -569,8 +623,8 @@ class Oydid
|
|
569
623
|
|
570
624
|
revoc_log = JSON.parse(revocationLog)
|
571
625
|
revoc_log["previous"] = [
|
572
|
-
|
573
|
-
|
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,
|
574
628
|
]
|
575
629
|
return [revoc_log, ""]
|
576
630
|
end
|
@@ -623,10 +677,16 @@ class Oydid
|
|
623
677
|
target_location = DEFAULT_LOCATION
|
624
678
|
end
|
625
679
|
if did.include?(LOCATION_PREFIX)
|
626
|
-
|
627
|
-
did =
|
628
|
-
source_location =
|
680
|
+
tmp = did.split(LOCATION_PREFIX)
|
681
|
+
did = tmp[0]
|
682
|
+
source_location = tmp[1]
|
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]
|
629
688
|
end
|
689
|
+
|
630
690
|
if source_location.to_s == ""
|
631
691
|
source_location = DEFAULT_LOCATION
|
632
692
|
end
|
@@ -652,7 +712,7 @@ class Oydid
|
|
652
712
|
# write did to new location
|
653
713
|
options[:doc_location] = target_location
|
654
714
|
options[:log_location] = target_location
|
655
|
-
options[:previous_clone] =
|
715
|
+
options[:previous_clone] = multi_hash(canonical(source_log), LOG_HASH_OPTIONS).first + LOCATION_PREFIX + source_location
|
656
716
|
options[:source_location] = source_location
|
657
717
|
options[:source_did] = source_did["did"]
|
658
718
|
retVal, msg = write(source_did["doc"]["doc"], nil, "clone", options)
|
@@ -660,6 +720,122 @@ class Oydid
|
|
660
720
|
end
|
661
721
|
|
662
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)
|
663
839
|
did = did_info["did"]
|
664
840
|
if !did.start_with?("did:oyd:")
|
665
841
|
did = "did:oyd:" + did
|
@@ -670,8 +846,8 @@ class Oydid
|
|
670
846
|
pubRevKey = didDoc["key"].split(":")[1] rescue ""
|
671
847
|
|
672
848
|
wd = {}
|
673
|
-
wd["@context"] = "https://www.w3.org/ns/did/v1"
|
674
|
-
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)
|
675
851
|
wd["verificationMethod"] = [{
|
676
852
|
"id": did + "#key-doc",
|
677
853
|
"type": "Ed25519VerificationKey2020",
|
@@ -684,47 +860,46 @@ class Oydid
|
|
684
860
|
"publicKeyMultibase": pubRevKey
|
685
861
|
}]
|
686
862
|
|
687
|
-
if didDoc["@context"]
|
863
|
+
if didDoc["@context"] == ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
688
864
|
didDoc.delete("@context")
|
689
865
|
end
|
690
|
-
if didDoc["doc"].
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
didDoc.
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
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
|
708
883
|
end
|
884
|
+
newDidDoc << didDoc["service"]
|
885
|
+
newDidDoc = newDidDoc.flatten
|
886
|
+
else
|
887
|
+
newDidDoc = didDoc["service"]
|
709
888
|
end
|
710
|
-
newDidDoc << didDoc["service"]
|
711
|
-
newDidDoc = newDidDoc.flatten
|
712
889
|
else
|
713
|
-
newDidDoc = didDoc["
|
890
|
+
newDidDoc = didDoc["doc"]
|
714
891
|
end
|
715
892
|
else
|
716
|
-
newDidDoc = didDoc
|
893
|
+
newDidDoc = didDoc["doc"]
|
717
894
|
end
|
718
|
-
|
719
|
-
newDidDoc = didDoc
|
895
|
+
wd["service"] = newDidDoc
|
720
896
|
end
|
721
|
-
wd["service"] = newDidDoc
|
722
897
|
return wd
|
723
898
|
end
|
724
899
|
|
725
900
|
def self.fromW3C(didDocument, options)
|
726
901
|
didDocument = didDocument.transform_keys(&:to_s)
|
727
|
-
if didDocument["@context"]
|
902
|
+
if didDocument["@context"] == ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]
|
728
903
|
didDocument.delete("@context")
|
729
904
|
end
|
730
905
|
didDocument
|