oydid 0.4.3 → 0.5.3
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/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
|