ppldid 1.0.0
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 +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +201 -0
- data/README.md +2 -0
- data/VERSION +1 -0
- data/lib/oydid/basic.rb +278 -0
- data/lib/oydid/didcomm.rb +120 -0
- data/lib/oydid/log.rb +394 -0
- data/lib/oydid.rb +738 -0
- data/spec/input/basic/arrays.json +8 -0
- data/spec/input/basic/french.json +6 -0
- data/spec/input/basic/sample2_get_location.doc +1 -0
- data/spec/input/basic/sample2_retrieve_document.doc +1 -0
- data/spec/input/basic/sample3_retrieve_document.doc +1 -0
- data/spec/input/basic/sample4_retrieve_document.doc +1 -0
- data/spec/input/basic/sample5_retrieve_document.doc +1 -0
- data/spec/input/basic/sample_dec.doc +1 -0
- data/spec/input/basic/sample_enc.doc +1 -0
- data/spec/input/basic/sample_get_location.doc +1 -0
- data/spec/input/basic/sample_hash.doc +1 -0
- data/spec/input/basic/sample_invalid2_readkey.doc +1 -0
- data/spec/input/basic/sample_invalid2_verify.doc +1 -0
- data/spec/input/basic/sample_invalid3_readkey.doc +1 -0
- data/spec/input/basic/sample_invalid3_verify.doc +1 -0
- data/spec/input/basic/sample_invalid_privkey.doc +1 -0
- data/spec/input/basic/sample_invalid_readkey.doc +1 -0
- data/spec/input/basic/sample_invalid_sign.doc +1 -0
- data/spec/input/basic/sample_invalid_verify.doc +1 -0
- data/spec/input/basic/sample_key.doc +1 -0
- data/spec/input/basic/sample_readkey.doc +1 -0
- data/spec/input/basic/sample_retrieve_document.doc +1 -0
- data/spec/input/basic/sample_sign.doc +1 -0
- data/spec/input/basic/sample_valid_privkey.doc +1 -0
- data/spec/input/basic/sample_verify.doc +1 -0
- data/spec/input/basic/structures.json +8 -0
- data/spec/input/basic/unicode.json +3 -0
- data/spec/input/basic/values.json +5 -0
- data/spec/input/basic/wierd.json +11 -0
- data/spec/input/basic/zQmaBZTghn.doc +1 -0
- data/spec/input/log/sample0_dag2array.doc +1 -0
- data/spec/input/log/sample0_dag_did.doc +1 -0
- data/spec/input/log/sample1_dag_did.doc +1 -0
- data/spec/input/log/sample1_dag_update.doc +1 -0
- data/spec/input/log/sample2_dag_did.doc +1 -0
- data/spec/input/log/sample2_dag_update.doc +1 -0
- data/spec/input/log/sample2_retrieve_log.doc +1 -0
- data/spec/input/log/sample3_dag_did.doc +1 -0
- data/spec/input/log/sample3_dag_update.doc +1 -0
- data/spec/input/log/sample3_retrieve_log.doc +1 -0
- data/spec/input/log/sample4_dag_did.doc +1 -0
- data/spec/input/log/sample4_dag_update.doc +1 -0
- data/spec/input/log/sample4_retrieve_log.doc +1 -0
- data/spec/input/log/sample5_dag_update.doc +1 -0
- data/spec/input/log/sample5_retrieve_log.doc +1 -0
- data/spec/input/log/sample6_dag_update.doc +1 -0
- data/spec/input/log/sample6_retrieve_log.doc +1 -0
- data/spec/input/log/sample7_dag_update.doc +1 -0
- data/spec/input/log/sample7_retrieve_log.doc +1 -0
- data/spec/input/log/sample8_dag_update.doc +1 -0
- data/spec/input/log/sample_addhash.doc +1 -0
- data/spec/input/log/sample_dag_update.doc +1 -0
- data/spec/input/log/sample_match_log.doc +1 -0
- data/spec/input/log/sample_op1_addhash.doc +1 -0
- data/spec/input/log/sample_retrieve_log.doc +1 -0
- data/spec/input/main/sample0_read.doc +1 -0
- data/spec/output/basic/arrays.json +1 -0
- data/spec/output/basic/french.json +1 -0
- data/spec/output/basic/sample2_get_location.doc +1 -0
- data/spec/output/basic/sample2_retrieve_document.doc +1 -0
- data/spec/output/basic/sample3_retrieve_document.doc +1 -0
- data/spec/output/basic/sample4_retrieve_document.doc +1 -0
- data/spec/output/basic/sample5_retrieve_document.doc +1 -0
- data/spec/output/basic/sample_dec.doc +1 -0
- data/spec/output/basic/sample_enc.doc +1 -0
- data/spec/output/basic/sample_get_location.doc +1 -0
- data/spec/output/basic/sample_hash.doc +1 -0
- data/spec/output/basic/sample_invalid2_readkey.doc +1 -0
- data/spec/output/basic/sample_invalid2_verify.doc +1 -0
- data/spec/output/basic/sample_invalid3_readkey.doc +1 -0
- data/spec/output/basic/sample_invalid3_verify.doc +1 -0
- data/spec/output/basic/sample_invalid_privkey.doc +1 -0
- data/spec/output/basic/sample_invalid_readkey.doc +1 -0
- data/spec/output/basic/sample_invalid_sign.doc +1 -0
- data/spec/output/basic/sample_invalid_verify.doc +1 -0
- data/spec/output/basic/sample_key.doc +1 -0
- data/spec/output/basic/sample_readkey.doc +1 -0
- data/spec/output/basic/sample_retrieve_document.doc +1 -0
- data/spec/output/basic/sample_sign.doc +1 -0
- data/spec/output/basic/sample_valid_privkey.doc +1 -0
- data/spec/output/basic/sample_verify.doc +1 -0
- data/spec/output/basic/structures.json +1 -0
- data/spec/output/basic/unicode.json +1 -0
- data/spec/output/basic/values.json +1 -0
- data/spec/output/basic/wierd.json +1 -0
- data/spec/output/log/sample0_dag2array.doc +1 -0
- data/spec/output/log/sample0_dag_did.doc +1 -0
- data/spec/output/log/sample1_dag_did.doc +1 -0
- data/spec/output/log/sample1_dag_update.doc +1 -0
- data/spec/output/log/sample2_dag_did.doc +1 -0
- data/spec/output/log/sample2_dag_update.doc +1 -0
- data/spec/output/log/sample2_retrieve_log.doc +1 -0
- data/spec/output/log/sample3_dag_did.doc +1 -0
- data/spec/output/log/sample3_dag_update.doc +1 -0
- data/spec/output/log/sample3_retrieve_log.doc +1 -0
- data/spec/output/log/sample4_dag_did.doc +1 -0
- data/spec/output/log/sample4_dag_update.doc +1 -0
- data/spec/output/log/sample4_retrieve_log.doc +1 -0
- data/spec/output/log/sample5_dag_update.doc +1 -0
- data/spec/output/log/sample5_retrieve_log.doc +1 -0
- data/spec/output/log/sample6_dag_update.doc +1 -0
- data/spec/output/log/sample6_retrieve_log.doc +1 -0
- data/spec/output/log/sample7_dag_update.doc +1 -0
- data/spec/output/log/sample7_retrieve_log.doc +1 -0
- data/spec/output/log/sample8_dag_update.doc +1 -0
- data/spec/output/log/sample_addhash.doc +1 -0
- data/spec/output/log/sample_dag_update.doc +1 -0
- data/spec/output/log/sample_match_log.doc +1 -0
- data/spec/output/log/sample_op1_addhash.doc +1 -0
- data/spec/output/log/sample_retrieve_log.doc +1 -0
- data/spec/output/main/sample0_read.doc +1 -0
- data/spec/oydid_spec.rb +170 -0
- data/spec/spec_helper.rb +31 -0
- metadata +420 -0
data/lib/oydid/log.rb
ADDED
@@ -0,0 +1,394 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
class Oydid
|
5
|
+
# log functions -----------------------------
|
6
|
+
def self.add_hash(log)
|
7
|
+
log.map do |item|
|
8
|
+
i = item.dup
|
9
|
+
i.delete("previous")
|
10
|
+
item["entry-hash"] = hash(canonical(item))
|
11
|
+
if item.transform_keys(&:to_s)["op"] == 1
|
12
|
+
item["sub-entry-hash"] = hash(canonical(i))
|
13
|
+
end
|
14
|
+
item
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# check if signature matches current document
|
19
|
+
# check if signature in log is correct
|
20
|
+
def self.match_log_did?(log, doc)
|
21
|
+
message = log["doc"].to_s
|
22
|
+
signature = log["sig"].to_s
|
23
|
+
public_keys = doc["key"].to_s
|
24
|
+
public_key = public_keys.split(":")[0] rescue ""
|
25
|
+
return verify(message, signature, public_key).first
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.retrieve_log(did_hash, log_file, log_location, options)
|
29
|
+
if log_location == ""
|
30
|
+
log_location = DEFAULT_LOCATION
|
31
|
+
end
|
32
|
+
if !(log_location == "" || log_location == "local")
|
33
|
+
if !log_location.start_with?("http")
|
34
|
+
log_location = "https://" + log_location
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
case log_location
|
39
|
+
when /^http/
|
40
|
+
log_location = log_location.sub("%3A%2F%2F","://")
|
41
|
+
retVal = HTTParty.get(log_location + "/log/" + did_hash)
|
42
|
+
if retVal.code != 200
|
43
|
+
msg = retVal.parsed_response("error").to_s rescue
|
44
|
+
"invalid response from " + log_location.to_s + "/log/" + did_hash.to_s
|
45
|
+
|
46
|
+
return [nil, msg]
|
47
|
+
end
|
48
|
+
if options.transform_keys(&:to_s)["trace"]
|
49
|
+
if options[:silent].nil? || !options[:silent]
|
50
|
+
puts "GET log for " + did_hash + " from " + log_location
|
51
|
+
end
|
52
|
+
end
|
53
|
+
retVal = JSON.parse(retVal.to_s) rescue nil
|
54
|
+
return [retVal, ""]
|
55
|
+
when "", "local"
|
56
|
+
doc = JSON.parse(read_private_storage(log_file)) rescue {}
|
57
|
+
if doc == {}
|
58
|
+
return [nil, "cannot read file '" + log_file + "'"]
|
59
|
+
end
|
60
|
+
return [doc, ""]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.dag_did(logs, options)
|
65
|
+
dag = DAG.new
|
66
|
+
dag_log = []
|
67
|
+
log_hash = []
|
68
|
+
|
69
|
+
# calculate hash values for each entry and build vertices
|
70
|
+
i = 0
|
71
|
+
create_entries = 0
|
72
|
+
create_index = nil
|
73
|
+
terminate_indices = []
|
74
|
+
logs.each do |el|
|
75
|
+
if el["op"].to_i == 2
|
76
|
+
create_entries += 1
|
77
|
+
create_index = i
|
78
|
+
end
|
79
|
+
if el["op"].to_i == 0
|
80
|
+
terminate_indices << i
|
81
|
+
end
|
82
|
+
log_hash << Oydid.hash(Oydid.canonical(el))
|
83
|
+
dag_log << dag.add_vertex(id: i)
|
84
|
+
i += 1
|
85
|
+
end unless logs.nil?
|
86
|
+
|
87
|
+
if create_entries != 1
|
88
|
+
return [nil, nil, nil, "wrong number of CREATE entries (" + create_entries.to_s + ") in log" ]
|
89
|
+
end
|
90
|
+
if terminate_indices.length == 0
|
91
|
+
return [nil, nil, nil, "missing TERMINATE entries" ]
|
92
|
+
end
|
93
|
+
|
94
|
+
# create edges between vertices
|
95
|
+
i = 0
|
96
|
+
logs.each do |el|
|
97
|
+
el["previous"].each do |p|
|
98
|
+
position = log_hash.find_index(p)
|
99
|
+
if !position.nil?
|
100
|
+
dag.add_edge from: dag_log[position], to: dag_log[i]
|
101
|
+
end
|
102
|
+
end unless el["previous"] == []
|
103
|
+
i += 1
|
104
|
+
end unless logs.nil?
|
105
|
+
|
106
|
+
# identify tangling TERMINATE entry
|
107
|
+
i = 0
|
108
|
+
terminate_entries = 0
|
109
|
+
terminate_overall = 0
|
110
|
+
terminate_index = nil
|
111
|
+
logs.each do |el|
|
112
|
+
if el["op"].to_i == 0
|
113
|
+
if dag.vertices[i].successors.length == 0
|
114
|
+
terminate_entries += 1
|
115
|
+
terminate_index = i
|
116
|
+
end
|
117
|
+
terminate_overall += 1
|
118
|
+
end
|
119
|
+
i += 1
|
120
|
+
end unless logs.nil?
|
121
|
+
|
122
|
+
if terminate_entries != 1 && !options[:log_complete]
|
123
|
+
if options[:silent].nil? || !options[:silent]
|
124
|
+
return [nil, nil, nil, "cannot resolve DID" ]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
return [dag, create_index, terminate_index, ""]
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.dag2array(dag, log_array, index, result, options)
|
131
|
+
if options.transform_keys(&:to_s)["trace"]
|
132
|
+
if options[:silent].nil? || !options[:silent]
|
133
|
+
puts " vertex " + index.to_s + " at " + log_array[index]["ts"].to_s + " op: " + log_array[index]["op"].to_s + " doc: " + log_array[index]["doc"].to_s
|
134
|
+
end
|
135
|
+
end
|
136
|
+
result << log_array[index]
|
137
|
+
dag.vertices[index].successors.each do |s|
|
138
|
+
# check if successor has predecessor that is not self (i.e. REVOKE with TERMINATE)
|
139
|
+
s.predecessors.each do |p|
|
140
|
+
if p[:id] != index
|
141
|
+
if options.transform_keys(&:to_s)["trace"]
|
142
|
+
if options[:silent].nil? || !options[:silent]
|
143
|
+
puts " vertex " + p[:id].to_s + " at " + log_array[p[:id]]["ts"].to_s + " op: " + log_array[p[:id]]["op"].to_s + " doc: " + log_array[p[:id]]["doc"].to_s
|
144
|
+
end
|
145
|
+
end
|
146
|
+
result << log_array[p[:id]]
|
147
|
+
end
|
148
|
+
end unless s.predecessors.length < 2
|
149
|
+
dag2array(dag, log_array, s[:id], result, options)
|
150
|
+
end unless dag.vertices[index].successors.count == 0
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.dag_update(currentDID, options)
|
155
|
+
i = 0
|
156
|
+
doc_location = ""
|
157
|
+
initial_did = currentDID["did"].to_s.dup
|
158
|
+
initial_did = initial_did.delete_prefix("did:ppld:")
|
159
|
+
if initial_did.include?(LOCATION_PREFIX)
|
160
|
+
tmp = initial_did.split(LOCATION_PREFIX)
|
161
|
+
initial_did = tmp[0]
|
162
|
+
doc_location = tmp[1]
|
163
|
+
end
|
164
|
+
current_public_doc_key = ""
|
165
|
+
verification_output = false
|
166
|
+
currentDID["log"].each do |el|
|
167
|
+
case el["op"]
|
168
|
+
when 2,3 # CREATE, UPDATE
|
169
|
+
currentDID["doc_log_id"] = i
|
170
|
+
doc_did = el["doc"]
|
171
|
+
did_hash = doc_did.delete_prefix("did:ppld:")
|
172
|
+
did_hash = did_hash.split(LOCATION_PREFIX).first
|
173
|
+
did10 = did_hash[0,10]
|
174
|
+
doc = retrieve_document_raw(doc_did, did10 + ".doc", doc_location, {})
|
175
|
+
if doc.first.nil?
|
176
|
+
currentDID["error"] = 2
|
177
|
+
msg = doc.last.to_s
|
178
|
+
if msg == ""
|
179
|
+
msg = "cannot retrieve " + doc_did.to_s
|
180
|
+
end
|
181
|
+
currentDID["message"] = msg
|
182
|
+
return currentDID
|
183
|
+
end
|
184
|
+
doc = doc.first["doc"]
|
185
|
+
if el["op"] == 2 # CREATE
|
186
|
+
if !match_log_did?(el, doc)
|
187
|
+
currentDID["error"] = 1
|
188
|
+
currentDID["message"] = "Signatures in log don't match"
|
189
|
+
return currentDID
|
190
|
+
end
|
191
|
+
end
|
192
|
+
currentDID["did"] = doc_did
|
193
|
+
currentDID["doc"] = doc
|
194
|
+
# since hash is guaranteed during retrieve_document this check is not necessary
|
195
|
+
# if hash(canonical(doc)) != did_hash
|
196
|
+
# currentDID["error"] = 1
|
197
|
+
# currentDID["message"] = "DID identifier and DID document don't match"
|
198
|
+
# if did_hash == initial_did
|
199
|
+
# verification_output = true
|
200
|
+
# end
|
201
|
+
# if verification_output
|
202
|
+
# currentDID["verification"] += "identifier: " + did_hash.to_s + "\n"
|
203
|
+
# currentDID["verification"] += "⛔ does not match DID Document:" + "\n"
|
204
|
+
# currentDID["verification"] += JSON.pretty_generate(doc) + "\n"
|
205
|
+
# currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
206
|
+
# end
|
207
|
+
# return currentDID
|
208
|
+
# end
|
209
|
+
if did_hash == initial_did
|
210
|
+
verification_output = true
|
211
|
+
end
|
212
|
+
if verification_output
|
213
|
+
currentDID["verification"] += "identifier: " + did_hash.to_s + "\n"
|
214
|
+
currentDID["verification"] += "✅ is hash of DID Document:" + "\n"
|
215
|
+
currentDID["verification"] += JSON.pretty_generate(doc) + "\n"
|
216
|
+
currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
217
|
+
end
|
218
|
+
current_public_doc_key = currentDID["doc"]["key"].split(":").first rescue ""
|
219
|
+
|
220
|
+
when 0 # TERMINATE
|
221
|
+
currentDID["termination_log_id"] = i
|
222
|
+
|
223
|
+
doc_did = currentDID["did"]
|
224
|
+
did_hash = doc_did.delete_prefix("did:ppld:")
|
225
|
+
did_hash = did_hash.split(LOCATION_PREFIX).first
|
226
|
+
did10 = did_hash[0,10]
|
227
|
+
doc = retrieve_document_raw(doc_did, did10 + ".doc", doc_location, {})
|
228
|
+
# since it retrieves a DID that previously existed, this test is not necessary
|
229
|
+
# if doc.first.nil?
|
230
|
+
# currentDID["error"] = 2
|
231
|
+
# currentDID["message"] = doc.last.to_s
|
232
|
+
# return currentDID
|
233
|
+
# end
|
234
|
+
doc = doc.first["doc"]
|
235
|
+
term = doc["log"]
|
236
|
+
log_location = term.split(LOCATION_PREFIX)[1] rescue ""
|
237
|
+
if log_location.to_s == ""
|
238
|
+
log_location = DEFAULT_LOCATION
|
239
|
+
end
|
240
|
+
term = term.split(LOCATION_PREFIX).first
|
241
|
+
if hash(canonical(el)) != term
|
242
|
+
currentDID["error"] = 1
|
243
|
+
currentDID["message"] = "Log reference and record don't match"
|
244
|
+
if verification_output
|
245
|
+
currentDID["verification"] += "'log' reference in DID Document: " + term.to_s + "\n"
|
246
|
+
currentDID["verification"] += "⛔ does not match TERMINATE log record:" + "\n"
|
247
|
+
currentDID["verification"] += JSON.pretty_generate(el) + "\n"
|
248
|
+
currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
249
|
+
end
|
250
|
+
return currentDID
|
251
|
+
end
|
252
|
+
if verification_output
|
253
|
+
currentDID["verification"] += "'log' reference in DID Document: " + term.to_s + "\n"
|
254
|
+
currentDID["verification"] += "✅ is hash of TERMINATE log record:" + "\n"
|
255
|
+
currentDID["verification"] += JSON.pretty_generate(el) + "\n"
|
256
|
+
currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
257
|
+
end
|
258
|
+
|
259
|
+
# check if there is a revocation entry
|
260
|
+
revocation_record = {}
|
261
|
+
revoc_term = el["doc"]
|
262
|
+
revoc_term = revoc_term.split(LOCATION_PREFIX).first
|
263
|
+
revoc_term_found = false
|
264
|
+
log_array, msg = retrieve_log(did_hash, did10 + ".log", log_location, options)
|
265
|
+
log_array.each do |log_el|
|
266
|
+
log_el_structure = log_el.dup
|
267
|
+
if log_el["op"].to_i == 1 # TERMINATE
|
268
|
+
log_el_structure.delete("previous")
|
269
|
+
end
|
270
|
+
if hash(canonical(log_el_structure)) == revoc_term
|
271
|
+
revoc_term_found = true
|
272
|
+
revocation_record = log_el.dup
|
273
|
+
if verification_output
|
274
|
+
currentDID["verification"] += "'doc' reference in TERMINATE log record: " + revoc_term.to_s + "\n"
|
275
|
+
currentDID["verification"] += "✅ is hash of REVOCATION log record (without 'previous' attribute):" + "\n"
|
276
|
+
currentDID["verification"] += JSON.pretty_generate(log_el) + "\n"
|
277
|
+
currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
278
|
+
end
|
279
|
+
break
|
280
|
+
end
|
281
|
+
end unless log_array.nil?
|
282
|
+
# this should actually be covered by retrieve_log in the block above
|
283
|
+
# (actually I wasn't able to craft a test case covering this part...)
|
284
|
+
# if !options.transform_keys(&:to_s)["log_location"].nil?
|
285
|
+
# log_array, msg = retrieve_log(revoc_term, did10 + ".log", options.transform_keys(&:to_s)["log_location"], options)
|
286
|
+
# log_array.each do |log_el|
|
287
|
+
# if log_el["op"] == 1 # TERMINATE
|
288
|
+
# log_el_structure = log_el.delete("previous")
|
289
|
+
# else
|
290
|
+
# log_el_structure = log_el
|
291
|
+
# end
|
292
|
+
# if hash(canonical(log_el_structure)) == revoc_term
|
293
|
+
# revoc_term_found = true
|
294
|
+
# revocation_record = log_el.dup
|
295
|
+
# if verification_output
|
296
|
+
# currentDID["verification"] += "'doc' reference in TERMINATE log record: " + revoc_term.to_s + "\n"
|
297
|
+
# currentDID["verification"] += "✅ is hash of REVOCATION log record (without 'previous' attribute):" + "\n"
|
298
|
+
# currentDID["verification"] += JSON.pretty_generate(log_el) + "\n"
|
299
|
+
# currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#calculate_hash)" + "\n\n"
|
300
|
+
# end
|
301
|
+
# break
|
302
|
+
# end
|
303
|
+
# end
|
304
|
+
# end
|
305
|
+
|
306
|
+
if revoc_term_found
|
307
|
+
update_term_found = false
|
308
|
+
log_array.each do |log_el|
|
309
|
+
if log_el["op"].to_i == 3
|
310
|
+
if log_el["previous"].include?(hash(canonical(revocation_record)))
|
311
|
+
update_term_found = true
|
312
|
+
message = log_el["doc"].to_s
|
313
|
+
|
314
|
+
signature = log_el["sig"]
|
315
|
+
public_key = current_public_doc_key.to_s
|
316
|
+
signature_verification = verify(message, signature, public_key).first
|
317
|
+
if signature_verification
|
318
|
+
if verification_output
|
319
|
+
currentDID["verification"] += "found UPDATE log record:" + "\n"
|
320
|
+
currentDID["verification"] += JSON.pretty_generate(log_el) + "\n"
|
321
|
+
currentDID["verification"] += "✅ public key from last DID Document: " + current_public_doc_key.to_s + "\n"
|
322
|
+
currentDID["verification"] += "verifies 'doc' reference of new DID Document: " + log_el["doc"].to_s + "\n"
|
323
|
+
currentDID["verification"] += log_el["sig"].to_s + "\n"
|
324
|
+
currentDID["verification"] += "of next DID Document (Details: https://ownyourdata.github.io/ppldid/#verify_signature)" + "\n"
|
325
|
+
|
326
|
+
next_doc_did = log_el["doc"].to_s
|
327
|
+
next_doc_location = doc_location
|
328
|
+
next_did_hash = next_doc_did.delete_prefix("did:ppld:")
|
329
|
+
next_did_hash = next_did_hash.split(LOCATION_PREFIX).first
|
330
|
+
next_did10 = next_did_hash[0,10]
|
331
|
+
next_doc = retrieve_document_raw(next_doc_did, next_did10 + ".doc", next_doc_location, {})
|
332
|
+
if next_doc.first.nil?
|
333
|
+
currentDID["error"] = 2
|
334
|
+
currentDID["message"] = next_doc.last
|
335
|
+
return currentDID
|
336
|
+
end
|
337
|
+
next_doc = next_doc.first["doc"]
|
338
|
+
if public_key == next_doc["key"].split(":").first
|
339
|
+
currentDID["verification"] += "⚠️ no key rotation in updated DID Document" + "\n"
|
340
|
+
end
|
341
|
+
currentDID["verification"] += "\n"
|
342
|
+
end
|
343
|
+
else
|
344
|
+
currentDID["error"] = 1
|
345
|
+
currentDID["message"] = "Signature does not match"
|
346
|
+
if verification_output
|
347
|
+
new_doc_did = log_el["doc"].to_s
|
348
|
+
new_doc_location = doc_location
|
349
|
+
new_did_hash = new_doc_did.delete_prefix("did:ppld:")
|
350
|
+
new_did_hash = new_did_hash.split(LOCATION_PREFIX).first
|
351
|
+
new_did10 = new_did_hash[0,10]
|
352
|
+
new_doc = retrieve_document(new_doc_did, new_did10 + ".doc", new_doc_location, {}).first
|
353
|
+
currentDID["verification"] += "found UPDATE log record:" + "\n"
|
354
|
+
currentDID["verification"] += JSON.pretty_generate(log_el) + "\n"
|
355
|
+
currentDID["verification"] += "⛔ public key from last DID Document: " + current_public_doc_key.to_s + "\n"
|
356
|
+
currentDID["verification"] += "does not verify 'doc' reference of new DID Document: " + log_el["doc"].to_s + "\n"
|
357
|
+
currentDID["verification"] += log_el["sig"].to_s + "\n"
|
358
|
+
currentDID["verification"] += "next DID Document (Details: https://ownyourdata.github.io/ppldid/#verify_signature)" + "\n"
|
359
|
+
currentDID["verification"] += JSON.pretty_generate(new_doc) + "\n\n"
|
360
|
+
end
|
361
|
+
return currentDID
|
362
|
+
end
|
363
|
+
break
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
else
|
369
|
+
if verification_output
|
370
|
+
currentDID["verification"] += "Revocation reference in log record: " + revoc_term.to_s + "\n"
|
371
|
+
currentDID["verification"] += "✅ cannot find revocation record searching at" + "\n"
|
372
|
+
currentDID["verification"] += "- " + log_location + "\n"
|
373
|
+
if !options.transform_keys(&:to_s)["log_location"].nil?
|
374
|
+
currentDID["verification"] += "- " + options.transform_keys(&:to_s)["log_location"].to_s + "\n"
|
375
|
+
end
|
376
|
+
currentDID["verification"] += "(Details: https://ownyourdata.github.io/ppldid/#retrieve_log)" + "\n\n"
|
377
|
+
end
|
378
|
+
break
|
379
|
+
end
|
380
|
+
when 1 # revocation log entry
|
381
|
+
# do nothing
|
382
|
+
else
|
383
|
+
currentDID["error"] = 2
|
384
|
+
currentDID["message"] = "FATAL ERROR: op code '" + el["op"].to_s + "' not implemented"
|
385
|
+
return currentDID
|
386
|
+
|
387
|
+
end
|
388
|
+
i += 1
|
389
|
+
end unless currentDID["log"].nil?
|
390
|
+
|
391
|
+
return currentDID
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|