sidetree 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c2645dbb06ae761fe9e966134e7b824a2d3832f9972cd0808f92d46b3f6056e
4
- data.tar.gz: bce1dce70b331c7b7093ceffa8c1af4e6953914f12aae2543cf6bcc9839ba97e
3
+ metadata.gz: b65f50d961dcfc15f1440ae26225fad38a7b42f43874764005b9d01cc624bb3a
4
+ data.tar.gz: dbe04b5d7072da5b1cbec36b90089d29cb69e6077cc60a501045d0eddff38d92
5
5
  SHA512:
6
- metadata.gz: ff5f5050ec0097e8a6f9a46d7f56c1bf43c08844d0b74a438d9daf07e508b67868537b8ab788658894a9b086673e697cab9aa9d8872c0437a61c169081986719
7
- data.tar.gz: 7252b89b1c99ee2a5cc4bcb15a6f10cf08c556881665b0d5132a2aafbb414d9a51e0aafc8180b4dd3dc2e96efb40f01d9334ae5dcc493043a318002bc4b3e699
6
+ metadata.gz: e7aa774c61569b33aa98de41aa6ab265c58107346704aaebf673e45bc464f250f1073ea70994ae1a884cbd92964dc7e84b1841e2cbfc917601157a2eea1a7854
7
+ data.tar.gz: a68ccd2615046db978b08dcffa585611f2ed44ee59a765e0c53614074892ad83e5f733df493bc8f06a15a4b264c777c52867f486562e13918b5cf4fff236c758
data/lib/sidetree/did.rb CHANGED
@@ -48,8 +48,8 @@ module Sidetree
48
48
  raise Error, "recovery_key must be Sidetree::Key instance."
49
49
  end
50
50
 
51
- patches = [{ action: OP::PatchAction::REPLACE, document: document.to_h }]
52
- delta = Model::Delta.new(patches, update_key.to_commitment)
51
+ delta =
52
+ Model::Delta.new([document.to_replace_patch], update_key.to_commitment)
53
53
  suffix =
54
54
  Sidetree::Model::Suffix.new(delta.to_hash, recovery_key.to_commitment)
55
55
  DID.new(
data/lib/sidetree/key.rb CHANGED
@@ -128,10 +128,11 @@ module Sidetree
128
128
  end
129
129
 
130
130
  # Generate JSON::JWK object.
131
+ # @param [Boolean] include_privkey whether include private key or not.
131
132
  # @return [JSON::JWK]
132
- def to_jwk
133
+ def to_jwk(include_privkey: false)
133
134
  jwk =
134
- JSON::JWK.new(
135
+ Sidetree::Util::JWK.parse(
135
136
  kty: "EC",
136
137
  crv: "secp256k1",
137
138
  x:
@@ -151,18 +152,30 @@ module Sidetree
151
152
  padding: false
152
153
  )
153
154
  )
154
- jwk["d"] = encoded_private_key if private_key
155
+ jwk["d"] = encoded_private_key if include_privkey && private_key
155
156
  jwk
156
157
  end
157
158
 
159
+ # Convert the private key to the format (OpenSSL::PKey::EC) in which it will be signed in JWS.
160
+ # @return [OpenSSL::PKey::EC]
161
+ def jws_sign_key
162
+ return nil unless private_key
163
+ to_jwk(include_privkey: true).to_key
164
+ end
165
+
158
166
  # Generate commitment for this key.
159
167
  # @return [String] Base64 encoded commitment.
160
168
  def to_commitment
161
169
  digest = Digest::SHA256.digest(to_jwk.normalize.to_json_c14n)
162
-
163
170
  Sidetree.to_hash(digest)
164
171
  end
165
172
 
173
+ # Generate reveal value for this key.
174
+ # @return [String] Base64 encoded reveal value.
175
+ def to_reveal_value
176
+ Sidetree.to_hash(to_jwk.normalize.to_json_c14n)
177
+ end
178
+
166
179
  def to_h
167
180
  h = { publicKeyJwk: to_jwk.normalize, purposes: purposes }
168
181
  h[:id] = id if id
@@ -0,0 +1,40 @@
1
+ module Sidetree
2
+ module Model
3
+ class CASFileBase
4
+ include Sidetree::Util::Compressor
5
+
6
+ # Decompress +data+.
7
+ # @param [String] data compressed data.
8
+ # @param [Integer] max_size
9
+ # @return [String] decompressed data.
10
+ # @raise [Sidetree::Error]
11
+ def self.decompress(data, max_size)
12
+ begin
13
+ Sidetree::Util::Compressor.decompress(
14
+ data,
15
+ max_bytes:
16
+ max_size *
17
+ Sidetree::Util::Compressor::ESTIMATE_DECOMPRESSION_MULTIPLIER
18
+ )
19
+ rescue Zlib::GzipFile::Error
20
+ raise Sidetree::Error,
21
+ "#{self.name.split("::").last.split(/(?=[A-Z])/).join(" ")} decompression failure"
22
+ end
23
+ end
24
+
25
+ # Build json string to be stored in CAS.
26
+ # Child classes must implement this method.
27
+ # @return [String]
28
+ def to_json
29
+ raise NotImplementedError,
30
+ "You must implement #{self.class}##{__method__}"
31
+ end
32
+
33
+ # Generate compressed data via to_json to be stored in CAS.
34
+ # @return [String] compressed data.
35
+ def to_compress
36
+ compress(to_json)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,7 +1,7 @@
1
1
  module Sidetree
2
2
  module Model
3
3
  # https://identity.foundation/sidetree/spec/#chunk-files
4
- class ChunkFile
4
+ class ChunkFile < CASFileBase
5
5
  attr_reader :deltas # Array of Sidetree::Model::Delta
6
6
 
7
7
  def initialize(deltas = [])
@@ -19,8 +19,7 @@ module Sidetree
19
19
  # @param [Array[Sidetree::OP::Recover]] recover_ops
20
20
  # @param [Array[Sidetree::OP::Update]] update_ops
21
21
  def self.create_from_ops(create_ops: [], recover_ops: [], update_ops: [])
22
- deltas = create_ops.map(&:delta)
23
- # TODO add update and recover operation delta
22
+ deltas = (create_ops + recover_ops + update_ops).map(&:delta)
24
23
  ChunkFile.new(deltas)
25
24
  end
26
25
 
@@ -30,16 +29,10 @@ module Sidetree
30
29
  # @return [Sidetree::Model::ChunkFile]
31
30
  # @raise [Sidetree::Error]
32
31
  def self.parse(chunk_file, compressed: true)
33
- max_bytes =
34
- Sidetree::Params::MAX_CHUNK_FILE_SIZE *
35
- Sidetree::Util::Compressor::ESTIMATE_DECOMPRESSION_MULTIPLIER
36
32
  decompressed =
37
33
  (
38
34
  if compressed
39
- Sidetree::Util::Compressor.decompress(
40
- chunk_file,
41
- max_bytes: max_bytes
42
- )
35
+ decompress(chunk_file, Sidetree::Params::MAX_CHUNK_FILE_SIZE)
43
36
  else
44
37
  chunk_file
45
38
  end
@@ -62,11 +55,10 @@ module Sidetree
62
55
  )
63
56
  end
64
57
 
65
- # Compress this chunk file
66
- # @return [String] compressed data.
67
- def to_compress
68
- params = { deltas: deltas.map(&:to_h) }
69
- Sidetree::Util::Compressor.compress(params.to_json)
58
+ # Build json string to be stored in CAS.
59
+ # @return [String] json string.
60
+ def to_json
61
+ { deltas: deltas.map(&:to_h) }.to_json
70
62
  end
71
63
 
72
64
  # Check if the +other+ object have the same chunk data.
@@ -1,7 +1,7 @@
1
1
  module Sidetree
2
2
  module Model
3
3
  # https://identity.foundation/sidetree/spec/#core-index-file
4
- class CoreIndexFile
4
+ class CoreIndexFile < CASFileBase
5
5
  attr_reader :core_proof_file_uri
6
6
  attr_reader :provisional_index_file_uri
7
7
  attr_reader :writer_lock_id
@@ -74,14 +74,7 @@ module Sidetree
74
74
  decompressed =
75
75
  (
76
76
  if compressed
77
- begin
78
- Sidetree::Util::Compressor.decompress(
79
- index_data,
80
- max_bytes: Sidetree::Params::MAX_CORE_INDEX_FILE_SIZE
81
- )
82
- rescue Zlib::GzipFile::Error
83
- raise Sidetree::Error, "Core index file decompression failure"
84
- end
77
+ decompress(index_data, Sidetree::Params::MAX_CORE_INDEX_FILE_SIZE)
85
78
  else
86
79
  index_data
87
80
  end
@@ -165,9 +158,9 @@ module Sidetree
165
158
  (recover_ops + deactivate_ops).map { |o| o.did_suffix }
166
159
  end
167
160
 
168
- # Compress this core index file
169
- # @return [String] compressed data.
170
- def to_compress
161
+ # Build json string to be stored in CAS.
162
+ # @return [String] json string.
163
+ def to_json
171
164
  params = {}
172
165
  params[
173
166
  :provisionalIndexFileUri
@@ -197,7 +190,7 @@ module Sidetree
197
190
  params[:operations] = operations
198
191
  params[:coreProofFileUri] = core_proof_file_uri if core_proof_file_uri
199
192
  params[:writerLockId] = writer_lock_id if writer_lock_id
200
- Sidetree::Util::Compressor.compress(params.to_json)
193
+ params.to_json
201
194
  end
202
195
  end
203
196
  end
@@ -0,0 +1,102 @@
1
+ module Sidetree
2
+ module Model
3
+ # https://identity.foundation/sidetree/spec/#core-proof-file
4
+ class CoreProofFile < CASFileBase
5
+ attr_reader :recover_proofs
6
+ attr_reader :deactivate_proofs
7
+
8
+ def initialize(recover_proofs, deactivate_proofs)
9
+ @recover_proofs = recover_proofs
10
+ @deactivate_proofs = deactivate_proofs
11
+ end
12
+
13
+ # Parse core proof file from compressed data.
14
+ # @param [String] proof_file compressed core proof file.
15
+ # @param [Boolean] compressed Whether the proof_file is compressed or not, default: true.
16
+ # @return [Sidetree::Model::CoreProofFile]
17
+ # @raise [Sidetree::Error]
18
+ def self.parse(proof_file, compressed: true)
19
+ decompressed =
20
+ (
21
+ if compressed
22
+ decompress(proof_file, Sidetree::Params::MAX_PROOF_FILE_SIZE)
23
+ else
24
+ proof_file
25
+ end
26
+ )
27
+ begin
28
+ json = JSON.parse(decompressed, symbolize_names: true)
29
+ recover_proofs, deactivate_proofs = [], []
30
+ json.keys.each do |k|
31
+ unless k == :operations
32
+ raise Sidetree::Error,
33
+ "Unexpected property #{k.to_s} in core proof file"
34
+ end
35
+ end
36
+ unless json[:operations]
37
+ raise Sidetree::Error,
38
+ "Core proof file does not have any operation proofs"
39
+ end
40
+ json[:operations].keys.each do |k|
41
+ unless k == :recover || k == :deactivate
42
+ raise Sidetree::Error,
43
+ "Unexpected property #{k.to_s} in core proof file"
44
+ end
45
+ end
46
+ if json[:operations][:recover]
47
+ unless json[:operations][:recover].is_a?(Array)
48
+ raise Sidetree::Error,
49
+ "Core proof file recover property not array"
50
+ end
51
+ recover_proofs =
52
+ json[:operations][:recover].each.map do |update|
53
+ update.keys.each do |k|
54
+ unless k == :signedData
55
+ raise Sidetree::Error,
56
+ "Unexpected property #{k.to_s} in core proof file"
57
+ end
58
+ end
59
+ Sidetree::Util::JWS.parse(update[:signedData])
60
+ end
61
+ end
62
+ if json[:operations][:deactivate]
63
+ unless json[:operations][:deactivate].is_a?(Array)
64
+ raise Sidetree::Error,
65
+ "Core proof file deactivate property not array"
66
+ end
67
+ deactivate_proofs =
68
+ json[:operations][:deactivate].each.map do |update|
69
+ update.keys.each do |k|
70
+ unless k == :signedData
71
+ raise Sidetree::Error,
72
+ "Unexpected property #{k.to_s} in core proof file"
73
+ end
74
+ end
75
+ Sidetree::Util::JWS.parse(update[:signedData])
76
+ end
77
+ end
78
+ if recover_proofs.length + deactivate_proofs.length == 0
79
+ raise Sidetree::Error, "Core proof file has no proof"
80
+ end
81
+ CoreProofFile.new(recover_proofs, deactivate_proofs)
82
+ rescue JSON::ParserError
83
+ raise Sidetree::Error, "Core proof file is not json"
84
+ end
85
+ end
86
+
87
+ # Build json string to be stored in CAS.
88
+ # @return [String] json string.
89
+ def to_json
90
+ operations = {}
91
+ operations[:recover] = recover_proofs.map do |u|
92
+ { signedData: u.to_s }
93
+ end unless recover_proofs.empty?
94
+ operations[:deactivate] = deactivate_proofs.map do |u|
95
+ { signedData: u.to_s }
96
+ end unless deactivate_proofs.empty?
97
+ params = { operations: operations }
98
+ params.to_json
99
+ end
100
+ end
101
+ end
102
+ end
@@ -35,6 +35,12 @@ module Sidetree
35
35
  def to_h
36
36
  { publicKeys: public_keys.map(&:to_h), services: services.map(&:to_h) }
37
37
  end
38
+
39
+ # Generate replace patch.
40
+ # @return [Hash]
41
+ def to_replace_patch
42
+ { action: OP::PatchAction::REPLACE, document: to_h }
43
+ end
38
44
  end
39
45
  end
40
46
  end
@@ -1,7 +1,7 @@
1
1
  module Sidetree
2
2
  module Model
3
3
  # https://identity.foundation/sidetree/spec/#provisional-index-file
4
- class ProvisionalIndexFile
4
+ class ProvisionalIndexFile < CASFileBase
5
5
  attr_reader :provisional_proof_file_uri
6
6
  attr_reader :chunks
7
7
  attr_reader :operations
@@ -44,15 +44,10 @@ module Sidetree
44
44
  decompressed =
45
45
  (
46
46
  if compressed
47
- begin
48
- Sidetree::Util::Compressor.decompress(
49
- index_data,
50
- max_bytes: Sidetree::Params::MAX_PROVISIONAL_INDEX_FILE_SIZE
51
- )
52
- rescue Zlib::GzipFile::Error
53
- raise Sidetree::Error,
54
- "Provisional Index File decompression failure"
55
- end
47
+ decompress(
48
+ index_data,
49
+ Sidetree::Params::MAX_PROVISIONAL_INDEX_FILE_SIZE
50
+ )
56
51
  else
57
52
  index_data
58
53
  end
@@ -111,9 +106,9 @@ module Sidetree
111
106
  end
112
107
  end
113
108
 
114
- # Compress this provisional index file
115
- # @return [String] compressed data.
116
- def to_compress
109
+ # Build json string to be stored in CAS.
110
+ # @return [String] json string.
111
+ def to_json
117
112
  params = { chunks: chunks.map(&:to_h) }
118
113
  unless operations.empty?
119
114
  params[:operations] = {
@@ -127,7 +122,7 @@ module Sidetree
127
122
  }
128
123
  params[:provisionalProofFileUri] = provisional_proof_file_uri
129
124
  end
130
- Sidetree::Util::Compressor.compress(params.to_json)
125
+ params.to_json
131
126
  end
132
127
  end
133
128
  end
@@ -0,0 +1,80 @@
1
+ module Sidetree
2
+ module Model
3
+ # https://identity.foundation/sidetree/spec/#provisional-proof-file
4
+ class ProvisionalProofFile < CASFileBase
5
+ attr_reader :update_proofs
6
+
7
+ # Initialize
8
+ # @param [Array[JSON::JWS]] update_proofs Array of update proof.
9
+ def initialize(update_proofs)
10
+ @update_proofs = update_proofs
11
+ end
12
+
13
+ # Parse provisional proof file from compressed data.
14
+ # @param [String] proof_file compressed provisional proof file.
15
+ # @param [Boolean] compressed Whether the proof_file is compressed or not, default: true.
16
+ # @return [Sidetree::Model::ProvisionalProofFile]
17
+ # @raise [Sidetree::Error]
18
+ def self.parse(proof_file, compressed: true)
19
+ decompressed =
20
+ (
21
+ if compressed
22
+ decompress(proof_file, Sidetree::Params::MAX_PROOF_FILE_SIZE)
23
+ else
24
+ proof_file
25
+ end
26
+ )
27
+ begin
28
+ json = JSON.parse(decompressed, symbolize_names: true)
29
+ json.keys.each do |k|
30
+ unless k == :operations
31
+ raise Sidetree::Error,
32
+ "Unexpected property #{k.to_s} in provisional proof file"
33
+ end
34
+ end
35
+ unless json[:operations]
36
+ raise Sidetree::Error,
37
+ "Provisional proof file does not have any operation proofs"
38
+ end
39
+ json[:operations].keys.each do |k|
40
+ unless k == :update
41
+ raise Sidetree::Error,
42
+ "Unexpected property #{k.to_s} in provisional proof file"
43
+ end
44
+ end
45
+ unless json[:operations][:update].is_a?(Array)
46
+ raise Sidetree::Error,
47
+ "Provisional proof file update property not array"
48
+ end
49
+ update_proofs =
50
+ json[:operations][:update].each.map do |update|
51
+ update.keys.each do |k|
52
+ unless k == :signedData
53
+ raise Sidetree::Error,
54
+ "Unexpected property #{k.to_s} in provisional proof file"
55
+ end
56
+ end
57
+ Sidetree::Util::JWS.parse(update[:signedData])
58
+ end
59
+ if update_proofs.empty?
60
+ raise Sidetree::Error, "Provisional proof file has no proof"
61
+ end
62
+ ProvisionalProofFile.new(update_proofs)
63
+ rescue JSON::ParserError
64
+ raise Sidetree::Error, "Provisional proof file is not json"
65
+ end
66
+ end
67
+
68
+ # Build json string to be stored in CAS.
69
+ # @return [String] json string.
70
+ def to_json
71
+ params = {
72
+ operations: {
73
+ update: update_proofs.map { |u| { signedData: u.to_s } }
74
+ }
75
+ }
76
+ params.to_json
77
+ end
78
+ end
79
+ end
80
+ end
@@ -4,9 +4,12 @@ module Sidetree
4
4
  autoload :Delta, "sidetree/model/delta"
5
5
  autoload :Document, "sidetree/model/document"
6
6
  autoload :Service, "sidetree/model/service"
7
+ autoload :CASFileBase, "sidetree/model/cas_file_base"
7
8
  autoload :CoreIndexFile, "sidetree/model/core_index_file"
8
9
  autoload :ChunkFile, "sidetree/model/chunk_file"
9
10
  autoload :Chunk, "sidetree/model/chunk"
10
11
  autoload :ProvisionalIndexFile, "sidetree/model/provisional_index_file"
12
+ autoload :ProvisionalProofFile, "sidetree/model/provisional_proof_file"
13
+ autoload :CoreProofFile, "sidetree/model/core_proof_file"
11
14
  end
12
15
  end
@@ -44,11 +44,14 @@ module Sidetree
44
44
  when :revealValue
45
45
  revealed_value = v
46
46
  when :signedData
47
- jws = JSON::JWS.decode_compact_serialized(v, :skip_verification)
47
+ jws = Sidetree::Util::JWS.parse(v)
48
48
  unless jws.keys.length == 2
49
49
  raise Sidetree::Error,
50
50
  "Deactivate operation signed data missing or unknown property"
51
51
  end
52
+ Sidetree::Util::JWK.validate!(
53
+ Sidetree::Util::JWK.parse(jws["recoveryKey"])
54
+ )
52
55
  else
53
56
  raise Sidetree::Error,
54
57
  "Unexpected property #{k.to_s} in deactivate operation"
@@ -11,6 +11,7 @@ module Sidetree
11
11
  # @param [Sidetree::Model::Delta] delta
12
12
  # @param [JSON::JWS] signed_data
13
13
  # @param [String] revealed_value
14
+ # @raise [Sidetree::Error]
14
15
  def initialize(did_suffix, delta, signed_data, revealed_value)
15
16
  Sidetree::Validator.validate_encoded_multi_hash!(
16
17
  did_suffix,
@@ -20,6 +21,13 @@ module Sidetree
20
21
  revealed_value,
21
22
  "#{type} revealValue"
22
23
  )
24
+ if signed_data
25
+ Validator.validate_canonicalize_object_hash!(
26
+ signed_data[key_name],
27
+ revealed_value,
28
+ type
29
+ )
30
+ end
23
31
  @did_suffix = did_suffix
24
32
  @delta = delta
25
33
  @signed_data = signed_data
@@ -42,12 +50,23 @@ module Sidetree
42
50
  when :revealValue
43
51
  revealed_value = v
44
52
  when :signedData
45
- jws = JSON::JWS.decode_compact_serialized(v, :skip_verification)
53
+ jws = Sidetree::Util::JWS.parse(v)
46
54
  unless jws.keys.length ==
47
55
  (type == Sidetree::OP::Type::RECOVER ? 3 : 2)
48
56
  raise Sidetree::Error,
49
57
  "#{type.capitalize} operation signed data missing or unknown property"
50
58
  end
59
+ key_name =
60
+ (
61
+ if type == Sidetree::OP::Type::RECOVER
62
+ "recoveryKey"
63
+ else
64
+ "updateKey"
65
+ end
66
+ )
67
+ Sidetree::Util::JWK.validate!(
68
+ Sidetree::Util::JWK.parse(jws[key_name])
69
+ )
51
70
  when :delta
52
71
  delta = Sidetree::Model::Delta.from_object(v)
53
72
  else
@@ -55,15 +74,6 @@ module Sidetree
55
74
  "Unexpected property #{k.to_s} in #{type} operation"
56
75
  end
57
76
  end
58
- if jws
59
- key =
60
- type == Sidetree::OP::Type::UPDATE ? "updateKey" : "recoveryKey"
61
- Validator.validate_canonicalize_object_hash!(
62
- jws[key],
63
- revealed_value,
64
- "#{type.capitalize} key"
65
- )
66
- end
67
77
  unless did_suffix
68
78
  raise Sidetree::Error, "The #{type} didSuffix must be a string"
69
79
  end
@@ -79,6 +89,10 @@ module Sidetree
79
89
  raise Sidetree::Error, "Invalid signedData"
80
90
  end
81
91
  end
92
+
93
+ def key_name
94
+ type == Sidetree::OP::Type::UPDATE ? "updateKey" : "recoveryKey"
95
+ end
82
96
  end
83
97
  end
84
98
  end
@@ -0,0 +1,47 @@
1
+ module Sidetree
2
+ module Util
3
+ module JWK
4
+ module_function
5
+
6
+ # Parse jwk hash object.
7
+ # The returned jwk does not include the kid.
8
+ # @param [Hash] params
9
+ # @return [JSON::JWK]
10
+ def parse(params)
11
+ jwk = JSON::JWK.new(params)
12
+ jwk.delete("kid")
13
+ jwk
14
+ end
15
+
16
+ # Validate jwk object as sidetree jwk.
17
+ # @param [JSON::JWK] jwk
18
+ # @raise [Sidetree::Error]
19
+ def validate!(jwk)
20
+ raise Sidetree::Error unless jwk.is_a?(JSON::JWK)
21
+ jwk.keys.each do |k|
22
+ unless %w[kty crv x y].include?(k)
23
+ raise Sidetree::Error, "JWK Es256k has unknown property"
24
+ end
25
+ end
26
+ unless jwk[:kty] == "EC"
27
+ raise Sidetree::Error, "JWK Es256k missing or invalid kty"
28
+ end
29
+ unless jwk[:crv] == "secp256k1"
30
+ raise Sidetree::Error, "JWK Es256k missing or invalid crv"
31
+ end
32
+ unless jwk[:x].is_a?(String)
33
+ raise Sidetree::Error, "JWK Es256k missing or invalid type x"
34
+ end
35
+ unless jwk[:y].is_a?(String)
36
+ raise Sidetree::Error, "JWK Es256k missing or invalid type y"
37
+ end
38
+ unless jwk[:x].length == 43
39
+ raise Sidetree::Error, "JWK Es256k has incorrect length of x"
40
+ end
41
+ unless jwk[:y].length == 43
42
+ raise Sidetree::Error, "JWK Es256k has incorrect length of y"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,52 @@
1
+ module Sidetree
2
+ module Util
3
+ module JWS
4
+ module_function
5
+
6
+ # Sign to +claim+ by +private_key+.
7
+ # @param [Hash] claim
8
+ # @param [Sidetree::Key] private_key Private key used by sign.
9
+ # @return [JSON::JWS]
10
+ def sign(claim, private_key)
11
+ jwt = JSON::JWT.new(claim)
12
+ jwt.header.delete(:typ)
13
+ jwt.sign(private_key.jws_sign_key, :ES256K)
14
+ end
15
+
16
+ # Parse +jws_string+ to JSON::JWS
17
+ # @param [String] jws_string JWS data string.
18
+ # @return [JSON::JWS]
19
+ # @raise [Sidetree::Error]
20
+ def parse(jws_string)
21
+ jws =
22
+ JSON::JWS.decode_compact_serialized(jws_string, :skip_verification)
23
+ validate!(jws)
24
+ jws
25
+ end
26
+
27
+ # Check whether valid +jws+ or not as sidetree jws.
28
+ # @param [JSON::JWS] jws
29
+ # @return [Boolean]
30
+ def valid?(jws)
31
+ begin
32
+ validate!(jws)
33
+ true
34
+ rescue Sidetree::Error
35
+ false
36
+ end
37
+ end
38
+
39
+ # Validate +jws+ as sidetree jws.
40
+ # @param [JSON::JWS] jws
41
+ # @raise [Sidetree::Error]
42
+ def validate!(jws)
43
+ unless jws.header.length == 1
44
+ raise Sidetree::Error, "jws header missing or unknown property"
45
+ end
46
+ unless jws.header[:alg] == "ES256K"
47
+ raise Sidetree::Error, "jws header missing or incorrect alg"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
data/lib/sidetree/util.rb CHANGED
@@ -2,5 +2,7 @@ module Sidetree
2
2
  module Util
3
3
  autoload :Compressor, "sidetree/util/compressor"
4
4
  autoload :AnchoredDataSerializer, "sidetree/util/anchored_data_serializer"
5
+ autoload :JWS, "sidetree/util/jws"
6
+ autoload :JWK, "sidetree/util/jwk"
5
7
  end
6
8
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidetree
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.3"
5
5
  end
data/lib/sidetree.rb CHANGED
@@ -32,6 +32,8 @@ module Sidetree
32
32
  MAX_CHUNK_FILE_SIZE = 10_000_000
33
33
  # Maximum compressed Provisional Index File size. 1 MB (zipped)
34
34
  MAX_PROVISIONAL_INDEX_FILE_SIZE = 1_000_000
35
+ # Maximum compressed Proof File size. 2.5 MB (zipped)
36
+ MAX_PROOF_FILE_SIZE = 2_500_000
35
37
  # Maximum compressed Core Index File size. 1 MB (zipped)
36
38
  MAX_CORE_INDEX_FILE_SIZE = 1_000_000
37
39
  # Maximum writer lock ID size
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidetree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-07 00:00:00.000000000 Z
11
+ date: 2022-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -136,12 +136,15 @@ files:
136
136
  - lib/sidetree/did.rb
137
137
  - lib/sidetree/key.rb
138
138
  - lib/sidetree/model.rb
139
+ - lib/sidetree/model/cas_file_base.rb
139
140
  - lib/sidetree/model/chunk.rb
140
141
  - lib/sidetree/model/chunk_file.rb
141
142
  - lib/sidetree/model/core_index_file.rb
143
+ - lib/sidetree/model/core_proof_file.rb
142
144
  - lib/sidetree/model/delta.rb
143
145
  - lib/sidetree/model/document.rb
144
146
  - lib/sidetree/model/provisional_index_file.rb
147
+ - lib/sidetree/model/provisional_proof_file.rb
145
148
  - lib/sidetree/model/service.rb
146
149
  - lib/sidetree/model/suffix.rb
147
150
  - lib/sidetree/op.rb
@@ -154,6 +157,8 @@ files:
154
157
  - lib/sidetree/util.rb
155
158
  - lib/sidetree/util/anchored_data_serializer.rb
156
159
  - lib/sidetree/util/compressor.rb
160
+ - lib/sidetree/util/jwk.rb
161
+ - lib/sidetree/util/jws.rb
157
162
  - lib/sidetree/validator.rb
158
163
  - lib/sidetree/version.rb
159
164
  - sidetree.gemspec