oydid 0.4.4 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/oydid/basic.rb +149 -33
  4. data/lib/oydid/didcomm.rb +9 -9
  5. data/lib/oydid/log.rb +14 -7
  6. data/lib/oydid/vc.rb +264 -0
  7. data/lib/oydid.rb +283 -113
  8. data/spec/input/basic/sample_b16_dec.doc +1 -0
  9. data/spec/input/basic/{sample_enc.doc → sample_b16_enc.doc} +0 -0
  10. data/spec/input/basic/sample_b17_edec.doc +1 -0
  11. data/spec/input/basic/{sample_hash.doc → sample_b17_enc.doc} +0 -0
  12. data/spec/input/basic/sample_b32_dec.doc +1 -0
  13. data/spec/{output/basic/sample_dec.doc → input/basic/sample_b32_enc.doc} +0 -0
  14. data/spec/input/basic/{sample_dec.doc → sample_b58_dec.doc} +0 -0
  15. data/spec/input/basic/sample_b58_enc.doc +1 -0
  16. data/spec/input/basic/sample_b64_dec.doc +1 -0
  17. data/spec/input/basic/sample_b64_enc.doc +1 -0
  18. data/spec/input/basic/sample_blake2b-16_b16_hash.doc +1 -0
  19. data/spec/input/basic/sample_blake2b-32_b32_hash.doc +1 -0
  20. data/spec/input/basic/sample_blake2b-64_b58_hash.doc +1 -0
  21. data/spec/input/basic/sample_invalid2_readkey.doc +1 -1
  22. data/spec/input/basic/sample_invalid3_readkey.doc +1 -1
  23. data/spec/input/basic/sample_readkey.doc +1 -1
  24. data/spec/input/basic/sample_sha2-256_b58_hash.doc +1 -0
  25. data/spec/input/basic/sample_sha2-512_b58_hash.doc +1 -0
  26. data/spec/input/basic/sample_sha3-224_b64_hash.doc +1 -0
  27. data/spec/output/basic/sample_b16_dec.doc +1 -0
  28. data/spec/output/basic/sample_b16_enc.doc +1 -0
  29. data/spec/output/basic/sample_b17_edec.doc +2 -0
  30. data/spec/output/basic/sample_b17_enc.doc +1 -0
  31. data/spec/output/basic/sample_b32_dec.doc +1 -0
  32. data/spec/output/basic/sample_b32_enc.doc +1 -0
  33. data/spec/output/basic/sample_b58_dec.doc +1 -0
  34. data/spec/output/basic/{sample_enc.doc → sample_b58_enc.doc} +0 -0
  35. data/spec/output/basic/sample_b64_dec.doc +1 -0
  36. data/spec/output/basic/sample_b64_enc.doc +1 -0
  37. data/spec/output/basic/sample_blake2b-16_b16_hash.doc +1 -0
  38. data/spec/output/basic/sample_blake2b-32_b32_hash.doc +1 -0
  39. data/spec/output/basic/sample_blake2b-64_b58_hash.doc +1 -0
  40. data/spec/output/basic/{sample_hash.doc → sample_sha2-256_b58_hash.doc} +0 -0
  41. data/spec/output/basic/sample_sha2-512_b58_hash.doc +1 -0
  42. data/spec/output/basic/sample_sha3-224_b64_hash.doc +1 -0
  43. data/spec/oydid_spec.rb +95 -13
  44. metadata +72 -19
data/lib/oydid/vc.rb ADDED
@@ -0,0 +1,264 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ class Oydid
5
+ def self.read_vc(identifier, options)
6
+ vc_location = ""
7
+ if !options[:location].nil?
8
+ vc_location = options[:location]
9
+ end
10
+ if vc_location.to_s == ""
11
+ vc_location = DEFAULT_LOCATION
12
+ end
13
+ vc_url = vc_location.sub(/(\/)+$/,'') + "/credentials/" + identifier
14
+
15
+ holder = options[:holder].to_s rescue nil
16
+ if holder.to_s == ""
17
+ msg = "missing holder information"
18
+ return [nil, msg]
19
+ exit
20
+ end
21
+
22
+ private_key = options[:doc_enc].to_s rescue nil
23
+ if private_key.to_s == ""
24
+ msg = "missing private document key information"
25
+ return [nil, msg]
26
+ exit
27
+ end
28
+
29
+ # authenticate against repository
30
+ init_url = vc_location + "/oydid/init"
31
+ sid = SecureRandom.hex(20).to_s
32
+ response = HTTParty.post(init_url,
33
+ headers: { 'Content-Type' => 'application/json' },
34
+ body: { "session_id": sid,
35
+ "public_key": Oydid.public_key(private_key, options).first }.to_json ).parsed_response rescue {}
36
+ if response["challenge"].nil?
37
+ msg = "missing challenge for repository authentication"
38
+ return [nil, msg]
39
+ exit
40
+ end
41
+ challenge = response["challenge"].to_s
42
+
43
+ # sign challenge and request token
44
+ token_url = vc_location + "/oydid/token"
45
+ response = HTTParty.post(token_url,
46
+ headers: { 'Content-Type' => 'application/json' },
47
+ body: { "session_id": sid,
48
+ "signed_challenge": Oydid.sign(challenge, private_key, options).first }.to_json).parsed_response rescue {}
49
+ access_token = response["access_token"].to_s rescue nil
50
+ if access_token.nil?
51
+ msg = "invalid repository authentication (access_token)"
52
+ return [nil, msg]
53
+ exit
54
+ end
55
+
56
+ retVal = HTTParty.get(vc_url,
57
+ headers: {'Authorization' => 'Bearer ' + access_token})
58
+ if retVal.code != 200
59
+ if retVal.code == 401
60
+ msg = "unauthorized (valid Bearer token required)"
61
+ else
62
+ msg = retVal.parsed_response("error").to_s rescue "invalid response from " + vc_url.to_s
63
+ end
64
+ return [nil, msg]
65
+ end
66
+ return [retVal.parsed_response, ""]
67
+ end
68
+
69
+ def self.create_vc(content, options)
70
+ vercred = {}
71
+ # set the context, which establishes the special terms used
72
+ vercred["@context"] = ["https://www.w3.org/2018/credentials/v1"]
73
+ vercred["type"] = ["VerifiableCredential"]
74
+ vercred["issuer"] = options[:issuer]
75
+ if options[:ts].nil?
76
+ vercred["issuanceDate"] = Time.now.utc.iso8601
77
+ else
78
+ vercred["issuanceDate"] = Time.at(options[:ts]).utc.iso8601
79
+ end
80
+ vercred["credentialSubject"] = {"id": options[:holder]}.merge(content)
81
+
82
+ proof = {}
83
+ proof["type"] = "Ed25519Signature2020"
84
+ proof["verificationMethod"] = options[:issuer].to_s
85
+ proof["proofPurpose"] = "assertionMethod"
86
+
87
+ # private_key = generate_private_key(options[:issuer_privateKey], "ed25519-priv", []).first
88
+ proof["proofValue"] = sign(content.to_json_c14n, options[:issuer_privateKey], []).first
89
+
90
+ vercred["proof"] = proof
91
+
92
+ # specify the identifier of the credential
93
+ vercred["identifier"] = hash(vercred.to_json)
94
+ return [vercred, ""]
95
+ end
96
+
97
+ def self.publish_vc(vc, options)
98
+ vc = vc.transform_keys(&:to_s)
99
+ identifier = vc["identifier"] rescue nil
100
+ if identifier.nil?
101
+ return [nil, "invalid format (missing identifier"]
102
+ exit
103
+ end
104
+
105
+ cs = vc["credentialSubject"].transform_keys(&:to_s) rescue nil
106
+ holder = cs["id"] rescue nil
107
+ if holder.nil?
108
+ return [nil, "invalid format (missing holder)"]
109
+ exit
110
+ end
111
+
112
+ vc_location = ""
113
+ if !options[:location].nil?
114
+ vc_location = options[:location]
115
+ end
116
+ if vc_location.to_s == ""
117
+ vc_location = DEFAULT_LOCATION
118
+ end
119
+ vc["identifier"] = vc_location.sub(/(\/)+$/,'') + "/credentials/" + identifier
120
+
121
+ # build object to post
122
+ vc_data = {
123
+ "identifier": identifier,
124
+ "vc": vc,
125
+ "holder": holder
126
+ }
127
+ vc_url = vc_location.sub(/(\/)+$/,'') + "/credentials"
128
+ retVal = HTTParty.post(vc_url,
129
+ headers: { 'Content-Type' => 'application/json' },
130
+ body: vc_data.to_json )
131
+ if retVal.code != 200
132
+ err_msg = retVal.parsed_response("error").to_s rescue "invalid response from " + vc_url.to_s
133
+ return [nil, err_msg]
134
+ end
135
+ return [vc["identifier"], ""]
136
+ end
137
+
138
+ def self.read_vp(identifier, options)
139
+ vp_location = ""
140
+ if !options[:location].nil?
141
+ vp_location = options[:location]
142
+ end
143
+ if vp_location.to_s == ""
144
+ vp_location = DEFAULT_LOCATION
145
+ end
146
+ vp_url = vp_location.sub(/(\/)+$/,'') + "/presentations/" + identifier
147
+ retVal = HTTParty.get(vp_url)
148
+ if retVal.code != 200
149
+ msg = retVal.parsed_response("error").to_s rescue "invalid response from " + vp_url.to_s
150
+ return [nil, msg]
151
+ end
152
+ return [retVal.parsed_response, ""]
153
+ end
154
+
155
+ def self.create_vp(content, options)
156
+ verpres = {}
157
+ # set the context, which establishes the special terms used
158
+ verpres["@context"] = ["https://www.w3.org/2018/credentials/v1"]
159
+ verpres["type"] = ["VerifiablePresentation"]
160
+ verpres["verifiableCredential"] = [content].flatten
161
+
162
+ proof = {}
163
+ proof["type"] = "Ed25519Signature2020"
164
+ if options[:ts].nil?
165
+ proof["created"] = Time.now.utc.iso8601
166
+ else
167
+ proof["created"] = Time.at(options[:ts]).utc.iso8601
168
+ end
169
+ proof["verificationMethod"] = options[:holder].to_s
170
+ proof["proofPurpose"] = "authentication"
171
+
172
+ # private_key = generate_private_key(options[:issuer_privateKey], "ed25519-priv", []).first
173
+ proof["proofValue"] = sign([content].flatten.to_json_c14n, options[:holder_privateKey], []).first
174
+ verpres["proof"] = proof
175
+
176
+ # specify the identifier of the credential
177
+ verpres["identifier"] = hash(verpres.to_json)
178
+ return [verpres, ""]
179
+ end
180
+
181
+ def self.publish_vp(vp, options)
182
+ vc = vp.transform_keys(&:to_s)
183
+ identifier = vp["identifier"] rescue nil
184
+ if identifier.nil?
185
+ return [nil, "invalid format (missing identifier"]
186
+ exit
187
+ end
188
+
189
+ proof = vp["proof"].transform_keys(&:to_s) rescue nil
190
+ holder = proof["verificationMethod"] rescue nil
191
+ if holder.nil?
192
+ return [nil, "invalid format (missing holder)"]
193
+ exit
194
+ end
195
+
196
+ vp_location = ""
197
+ if !options[:location].nil?
198
+ vp_location = options[:location]
199
+ end
200
+ if vp_location.to_s == ""
201
+ vp_location = DEFAULT_LOCATION
202
+ end
203
+ vp["identifier"] = vp_location.sub(/(\/)+$/,'') + "/presentations/" + identifier
204
+
205
+ # build object to post
206
+ vp_data = {
207
+ "identifier": identifier,
208
+ "vp": vp,
209
+ "holder": holder
210
+ }
211
+ vp_url = vp_location.sub(/(\/)+$/,'') + "/presentations"
212
+ retVal = HTTParty.post(vp_url,
213
+ headers: { 'Content-Type' => 'application/json' },
214
+ body: vp_data.to_json )
215
+ if retVal.code != 200
216
+ err_msg = retVal.parsed_response("error").to_s rescue "invalid response from " + vp_url.to_s
217
+ return [nil, err_msg]
218
+ end
219
+ return [vp["identifier"], ""]
220
+ end
221
+
222
+ def self.verify_vp(content, options)
223
+ retVal = {}
224
+ if content["identifier"].nil?
225
+ return [nil, "invalid VP (unknown identifier"]
226
+ exit
227
+ end
228
+ retVal[:identifier] = content["identifier"].to_s
229
+
230
+ proofValue = content["proof"]["proofValue"].to_s rescue nil
231
+ if proofValue.nil?
232
+ return [nil, "invalid VP (unknown proofValue"]
233
+ exit
234
+ end
235
+
236
+ vercred = content["verifiableCredential"].to_json_c14n rescue nil
237
+ if vercred.nil?
238
+ return [nil, "invalid VP (unknown verifiableCredential"]
239
+ exit
240
+ end
241
+
242
+ holder = content["proof"]["verificationMethod"].to_s rescue nil
243
+ if holder.nil?
244
+ return [nil, "invalid VP (unknown holder"]
245
+ exit
246
+ end
247
+ pubKey, msg = getPubKeyFromDID(holder)
248
+ if pubKey.nil?
249
+ return [nil, "cannot verify public key"]
250
+ exit
251
+ end
252
+ result, msg = verify(vercred, proofValue, pubKey)
253
+ if result.to_s == ""
254
+ return [nil, msg]
255
+ exit
256
+ end
257
+ if result
258
+ return [retVal, ""]
259
+ else
260
+ return [nil, "signature verification failed"]
261
+ end
262
+ end
263
+
264
+ end