sidetree 0.1.2 → 0.1.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 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