oydid 0.4.4 → 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 +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
|