silkey-sdk 0.0.1 → 0.1.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -1
  4. data/.yardopts +14 -0
  5. data/CHANGELOG.md +46 -1
  6. data/DEVELOPMENT.md +2 -5
  7. data/Gemfile +1 -9
  8. data/Gemfile.lock +3 -1
  9. data/README.md +37 -14
  10. data/lib/silkey-sdk.rb +3 -4
  11. data/lib/silkey/models/jwt_payload.rb +57 -53
  12. data/lib/silkey/models/settings.rb +34 -0
  13. data/lib/silkey/models/sso_params.rb +42 -0
  14. data/lib/silkey/registry_contract/registry_contract.rb +1 -1
  15. data/lib/silkey/sdk.rb +63 -126
  16. data/lib/silkey/services/logger_service.rb +1 -1
  17. data/lib/silkey/services/verifier.rb +190 -0
  18. data/lib/silkey/utils.rb +7 -1
  19. data/lib/silkey/version.rb +1 -1
  20. data/silkey-sdk.gemspec +16 -3
  21. metadata +56 -93
  22. data/doc/CHANGELOG_md.html +0 -112
  23. data/doc/LICENSE_txt.html +0 -99
  24. data/doc/Object.html +0 -117
  25. data/doc/README_md.html +0 -144
  26. data/doc/Silkey.html +0 -269
  27. data/doc/Silkey/ClientFactory.html +0 -106
  28. data/doc/Silkey/Configuration.html +0 -217
  29. data/doc/Silkey/Contract.html +0 -106
  30. data/doc/Silkey/Contract/FrozenArray.html +0 -106
  31. data/doc/Silkey/ContractFactory.html +0 -106
  32. data/doc/Silkey/LoggerService.html +0 -106
  33. data/doc/Silkey/Models.html +0 -99
  34. data/doc/Silkey/Models/JwtPayload.html +0 -622
  35. data/doc/Silkey/RegistryContract.html +0 -106
  36. data/doc/Silkey/SDK.html +0 -356
  37. data/doc/Silkey/Utils.html +0 -709
  38. data/doc/created.rid +0 -23
  39. data/doc/css/fonts.css +0 -167
  40. data/doc/css/rdoc.css +0 -619
  41. data/doc/fonts/Lato-Light.ttf +0 -0
  42. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  43. data/doc/fonts/Lato-Regular.ttf +0 -0
  44. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  45. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  46. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  47. data/doc/images/add.png +0 -0
  48. data/doc/images/arrow_up.png +0 -0
  49. data/doc/images/brick.png +0 -0
  50. data/doc/images/brick_link.png +0 -0
  51. data/doc/images/bug.png +0 -0
  52. data/doc/images/bullet_black.png +0 -0
  53. data/doc/images/bullet_toggle_minus.png +0 -0
  54. data/doc/images/bullet_toggle_plus.png +0 -0
  55. data/doc/images/date.png +0 -0
  56. data/doc/images/delete.png +0 -0
  57. data/doc/images/find.png +0 -0
  58. data/doc/images/loadingAnimation.gif +0 -0
  59. data/doc/images/macFFBgHack.png +0 -0
  60. data/doc/images/package.png +0 -0
  61. data/doc/images/page_green.png +0 -0
  62. data/doc/images/page_white_text.png +0 -0
  63. data/doc/images/page_white_width.png +0 -0
  64. data/doc/images/plugin.png +0 -0
  65. data/doc/images/ruby.png +0 -0
  66. data/doc/images/tag_blue.png +0 -0
  67. data/doc/images/tag_green.png +0 -0
  68. data/doc/images/transparent.png +0 -0
  69. data/doc/images/wrench.png +0 -0
  70. data/doc/images/wrench_orange.png +0 -0
  71. data/doc/images/zoom.png +0 -0
  72. data/doc/index.html +0 -112
  73. data/doc/js/darkfish.js +0 -84
  74. data/doc/js/navigation.js +0 -105
  75. data/doc/js/navigation.js.gz +0 -0
  76. data/doc/js/search.js +0 -110
  77. data/doc/js/search_index.js +0 -1
  78. data/doc/js/search_index.js.gz +0 -0
  79. data/doc/js/searcher.js +0 -229
  80. data/doc/js/searcher.js.gz +0 -0
  81. data/doc/table_of_contents.html +0 -318
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 151c068dbbeccc6d242140bbf755dbc2d7ac783de3c0fa9f8bed08828c875011
4
- data.tar.gz: '09c21b562b50c1a66c9d72d2fd0042e6a30549941017e1e7fff4e4644bbdcfef'
3
+ metadata.gz: ac39da25efe706b56abfda8f580295dc0d0c7734ce83ccc13130b85cce5a1e22
4
+ data.tar.gz: 86744220f6d4e5ee274c1c451cc5be9591a60f240a5a2fc871d5fc3794d71988
5
5
  SHA512:
6
- metadata.gz: f7505da37a916d4e26d7ebd896a432ff901ae3ee805707e924e34a832643d52fe6ddb7a52f3a0676d7170976a6cdfeb469327b8c99fd8292136313324cbfba08
7
- data.tar.gz: 1f346357fc4623f9cfb54c93cbd68e000a2a4597374a3f5c39f037907da4aa1d4003611e09a6b52386816a27d481bd200b644472416e6db9adb48fcc96e01c92
6
+ metadata.gz: b634f6d573b002484a32a02059b730b5cd9184d93de5aaa67d9df981d833269845df561394444d239ea327ac653e68d2ffda4fa36a05e680b73e34d67384a065
7
+ data.tar.gz: 4024009b029a6d8aa45b7beb9d79a2d61c677d761d94ba79234539dc1aac9fe43e729735bd2df58b86cdfdcb8085c2fbbf70018624fbbb5504d9c85132c0ed22
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /tmp/
8
8
  .idea/
9
9
  pkg/
10
+ doc/
10
11
 
11
12
  *.gem
12
13
  # rspec failure tracking
@@ -32,7 +32,7 @@ Metrics/BlockLength:
32
32
  ExcludedMethods: ['describe', 'context', 'let']
33
33
 
34
34
  Layout/LineLength:
35
- Max: 100
35
+ Max: 120
36
36
 
37
37
  Metrics/ClassLength:
38
38
  Max: 150
@@ -0,0 +1,14 @@
1
+ --no-private
2
+ --title "Silkey SDK for Ruby"
3
+ --exclude Gemfile
4
+ --exclude Gemfile.lock
5
+ --exclude registry_contract_abi.json
6
+ --exclude setup
7
+ --exclude Rakefile
8
+ --exclude DEVELOPMENT.md
9
+ --exclude lib/silkey/factories/*
10
+ --exclude lib/silkey/registry_contract/*
11
+ --exclude lib/silkey/services/*
12
+ --exclude lib/silkey/contract.rb
13
+ --exclude lib/silkey/utils.rb
14
+ --exclude lib/silkey/version.rb
@@ -4,6 +4,51 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [Unreleased]
7
+ ## [0.1.0] - 2021-01-03
8
+ ### Added
9
+ - additional verification for token:
10
+ - verify token age
11
+ - verify sso params
12
+ - website signature
13
+ - support for migration
14
+ - settings model for jwt and sso params
15
+
16
+ ### Changed
17
+ - all SSO params have prefix `sso`
18
+
19
+ ### Removed
20
+ - `refId` is not longer part of token
21
+
22
+ ## [0.0.5] - 2020-12-15
23
+ ### Changed
24
+ - add `0x` to signature to be compatible with JS and not throw `signature missing v and recoveryParam` error
25
+
26
+ ## [0.0.4] - 2020-11-26
27
+ ### Added
28
+ - `generate_sso_request_params` throws on empty PK
29
+
30
+ ### Changed
31
+ - join operator for `message_to_sign` is now `&`
32
+ - `message_to_sign` ignores data that are not set
33
+
34
+ ### Fixed
35
+ - ensure testing `throws` is working correctly
36
+ - rubocop offences
37
+
38
+ ## [0.0.3] - 2020-11-25
39
+ ### Added
40
+ - Logo and badges to README
41
+
42
+ ## [0.0.2] 2020-11-23
43
+ ### Added
44
+ - add support for `redirectMethod`
45
+
46
+ ### Changed
47
+ - `generate_sso_request_params` raises error when missing required params
48
+
49
+ ### Removed
50
+ - html doc files from repo
51
+
52
+ ## [0.0.1] 2020-11-20
8
53
  ### Added:
9
54
  - initial version
@@ -1,9 +1,5 @@
1
1
  # Silkey-SDK for Ruby
2
2
 
3
- [logo]
4
-
5
- [slogan]
6
-
7
3
  ## Development
8
4
 
9
5
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -13,7 +9,7 @@ You can also run `bin/console` for an interactive prompt that will allow you to
13
9
 
14
10
  ```
15
11
  rm -rf doc/
16
- bundle exec rdoc --main README.rdoc -x Gemfile -x Gemfile.lock -x registry_contract_abi.json -x setup -x Rakefile -x DEVELOPMENT.md
12
+ bundle exec yardoc
17
13
 
18
14
  bundle exec gem build
19
15
 
@@ -51,6 +47,7 @@ Silkey::RegistryContract.get_address('Name')
51
47
  ```bash
52
48
  bundle exec rspec
53
49
  bundle exec rubocop --fix
50
+ bundle exec rubocop --auto-correct-all
54
51
  ```
55
52
 
56
53
  #### Init setup environment
data/Gemfile CHANGED
@@ -1,13 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in andromeda.gemspec
6
-
7
- #source 'https://hwGZD769AGZu5Wyzp87F@repo.fury.io/silkey/' do
8
- # gem 'ethereum.rb', '~> 2.2.3'
9
- #end
10
-
11
3
  gemspec
12
4
 
13
- gem "rspec"
5
+ gem "rspec"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- silkey-sdk (0.0.1)
4
+ silkey-sdk (0.1.0)
5
5
  activesupport (~> 6.0)
6
6
  eth (~> 0.4.12)
7
7
  ethereum.rb (~> 2.5)
@@ -108,6 +108,7 @@ GEM
108
108
  descendants_tracker (~> 0.0, >= 0.0.3)
109
109
  equalizer (~> 0.0, >= 0.0.9)
110
110
  virtus_convert (0.1.0)
111
+ yard (0.9.25)
111
112
  zeitwerk (2.4.1)
112
113
 
113
114
  PLATFORMS
@@ -123,6 +124,7 @@ DEPENDENCIES
123
124
  rubocop (~> 1.3)
124
125
  rubocop-performance (~> 1.8)
125
126
  silkey-sdk!
127
+ yard (~> 0.9.25)
126
128
 
127
129
  BUNDLED WITH
128
130
  2.1.4
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # Silkey-SDK for Ruby
1
+ # Silkey SDK for Ruby
2
2
 
3
- [logo]
4
-
5
- [slogan]
3
+ ![Silkey Logo](https://raw.githubusercontent.com/Silkey-Team/brand/master/silkey-word-black.png)
6
4
 
5
+ [![GitHub version](https://badge.fury.io/gh/Silkey-Team%2Fsilkey-sdk.svg)](https://badge.fury.io/gh/Silkey-Team%2Fsilkey-sdk)
6
+ [![Gem Version](https://badge.fury.io/rb/silkey-sdk.svg)](https://badge.fury.io/rb/silkey-sdk)
7
7
 
8
8
  ## Integration
9
9
 
@@ -11,36 +11,59 @@
11
11
 
12
12
  ```rb
13
13
  Silkey::Configuration.setup do |config|
14
- config.client_url = 'http://localhost:8545' # for local development
15
- config.client_url = 'https://kovan.infura.io/v3/:id' # for real
16
- config.registry_contract_address = '--silky-registry-contrract-address--'
14
+ # for local development, use local provider url eg 'http://localhost:8545'
15
+ # for testing, we recommend using infura.io:
16
+ # - for sandbox: https://rinkeby.infura.io/v3/:id
17
+ # - for production: https://mainnet.infura.io/v3/:id
18
+ config.client_url = 'http://localhost:8545'
19
+ config.registry_contract_address = '--silky-registry-contract-address--'
17
20
  config.enable_logs = false
18
21
  end
19
22
  ```
20
23
 
21
- [List of Silkey contract address.](https://github.com/Silkey-Team/silkey-sdk#silkey-sdk)
24
+ [List of Silkey smart contract addresses.](https://github.com/Silkey-Team/silkey-sdk#smart-contracts)
22
25
 
23
26
  ### Sign In with Silkey
24
27
 
25
28
  #### Making request
26
29
 
27
- [List of request parameters.](https://github.com/Silkey-Team/silkey-sdk#silkey-sdk)
30
+ | Parameter | Required | Type | Desc
31
+ | ----------------- |:---------:| -------- | -----
32
+ | ssoSignature | yes | string | Domain owner signature
33
+ | ssoTimestamp | yes | number | Time of signing SSO request
34
+ | ssoRedirectUrl | yes | string | Where to redirect user with token after sign in
35
+ | ssoCancelUrl | yes | string | Where to redirect user on error
36
+ | ssoRedirectMethod | no | GET/POST | How to redirect user after sign in, default is POST
37
+ | ssoRefId | no | string | Any value, you may use it to identify request
38
+ | ssoScope | no | string | Scope of data to return in a token payload: `id` (default) returns only user address, `email` returns address + email
28
39
 
29
40
 
30
41
  ```rb
31
- - Silkey::SDK.message_to_sign({params})
32
- - Silkey::SDK.generate_sso_request_params(private_key, hash)
42
+ params = { ssoRedirectUrl: 'https://your-website', ssoRefId: '12ab' }
43
+ sso_params = Silkey::SDK.generate_sso_request_params(private_key, params)
33
44
  ```
34
45
 
35
46
  #### On request callback page
36
47
 
37
- `token` - get if from request params (it can be send either via POST or GET)
48
+ Callback will be done via POST (default) or GET, based on `ssoRedirectMethod`.
49
+
50
+ Callback params contains:
51
+ - sso parameters that were used to make SSO call
52
+ - `token`.
53
+
54
+ `token` - get if from request params
55
+
56
+ `ssoRequestParams` - get if from request params (it can be send via POST or GET, based on `ssoRedirectMethod`)
38
57
 
39
58
  ```rb
40
- silkey_public_key = Silkey::SDK.fetch_silkey_public_key
41
- Silkey::SDK.token_payload_verifier(token, silkey_public_key)
59
+ silkey_eth_address = Silkey::SDK.fetch_silkey_eth_address
60
+ Silkey::SDK.token_payload_verifier(token, silkey_eth_address)
42
61
  ```
43
62
 
63
+ ## Recommendations and Migration
64
+
65
+ See [recommendation and migration](https://github.com/Silkey-Team/silkey-sdk#recommendations) sections on main SDK package.
66
+
44
67
  ## License
45
68
 
46
69
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,14 +1,10 @@
1
1
  require 'eth'
2
2
  require 'ethereum.rb'
3
- # require 'json'
4
3
  require 'jwt'
5
4
  require 'logger'
6
5
  require 'pry'
7
- #require 'active_support'
8
- #require 'active_support/core_ext/module'
9
6
  require 'virtus_convert'
10
7
  require 'virtus'
11
- # require 'retriable'
12
8
  require 'silkey'
13
9
 
14
10
  require_relative 'silkey/contract'
@@ -16,7 +12,10 @@ require_relative 'silkey/configuration'
16
12
  require_relative 'silkey/factories/client_factory'
17
13
  require_relative 'silkey/factories/contract_factory'
18
14
  require_relative 'silkey/models/jwt_payload'
15
+ require_relative 'silkey/models/settings'
16
+ require_relative 'silkey/models/sso_params'
19
17
  require_relative 'silkey/services/logger_service'
18
+ require_relative 'silkey/services/verifier'
20
19
  require_relative 'silkey/sdk'
21
20
  require_relative 'silkey/utils'
22
21
 
@@ -2,28 +2,36 @@
2
2
 
3
3
  module Silkey
4
4
  module Models
5
+ ##
6
+ # Generates message to sign based on plain object data (keys => values)
7
+ #
8
+ # @param email [string] verified email of the user
9
+ # IMPORTANT: if email in user profile is different, you should always update it with this one.
10
+ #
11
+ # @param scope [string]
12
+ # @param address [string] ID of the user, this is also valid ethereum address, use this to identify user
13
+ # @param userSignature [string] proof that request came from the user
14
+ # @param userSignatureTimestamp [number] time when signature was crated
15
+ # @param silkeySignature [string] proof that Silkey verified the email
16
+ # @param silkeySignatureTimestamp [number] time when signature was crated
17
+ # @param migration [boolean] true if user started migration to Silkey
18
+ #
5
19
  class JwtPayload
6
20
  include Virtus.model
7
21
 
8
- SCOPE_DIVIDER = ','
9
-
10
22
  # rubocop:disable Style/HashSyntax
11
- attribute :address, String, :writer => :private
12
23
  attribute :email, String, :writer => :private
24
+ attribute :_scope, {}, :writer => :private, :reader => :private
25
+ attribute :address, String, :writer => :private
13
26
  attribute :silkey_signature, String, :writer => :private
14
- attribute :silkey_signature_timestamp, Integer
27
+ attribute :silkey_signature_timestamp, Integer, :default => 0
15
28
  attribute :user_signature, String, :writer => :private
16
- attribute :user_signature_timestamp, Integer
17
- attribute :ref_id, String, :writer => :private
18
- attribute :_scope, {}, :writer => :private, :reader => :private
29
+ attribute :user_signature_timestamp, Integer, :default => 0
30
+ attribute :migration, Boolean, :writer => :private, :default => false
19
31
  # rubocop:enable Style/HashSyntax
20
32
 
21
33
  def scope
22
- _scope.keys.sort.join(SCOPE_DIVIDER)
23
- end
24
-
25
- def scope_divider
26
- SCOPE_DIVIDER
34
+ _scope.keys.sort.join(Silkey::Settings.SCOPE_DIVIDER)
27
35
  end
28
36
 
29
37
  # rubocop:disable Naming/AccessorMethodName
@@ -46,8 +54,8 @@ module Silkey
46
54
  self
47
55
  end
48
56
 
49
- def set_ref_id(ref_id)
50
- self.ref_id = ref_id
57
+ def set_migrations(migrating)
58
+ self.migration = migrating
51
59
  self
52
60
  end
53
61
 
@@ -68,31 +76,24 @@ module Silkey
68
76
  self.silkey_signature_timestamp = timestamp
69
77
  self
70
78
  end
71
-
72
79
  # rubocop:enable Naming/AccessorMethodName
73
80
 
81
+ # rubocop:disable Metrics/AbcSize
82
+ #
74
83
  ##
75
84
  # Creates message that's need to be sign by user
76
85
  def message_to_sign_by_user
77
- if !Silkey::Utils.empty?(address) && Silkey::Utils.empty?(user_signature_timestamp)
78
- self.user_signature_timestamp = Silkey::Utils.current_timestamp
79
- end
80
-
81
- str1_hex = 'address'.unpack('H*')[0]
82
- adr_hex = Silkey::Utils.remove0x(address).downcase
83
-
84
- str2_hex = [
85
- 'refId', ref_id.to_s,
86
- 'scope', scope,
87
- 'userSignatureTimestamp'
88
- ].map { |str| str.to_s.unpack('H*') }.join('')
89
-
90
- str_hex = "#{str1_hex}#{adr_hex}#{str2_hex}"
91
-
92
- return str_hex if Silkey::Utils.empty?(user_signature_timestamp)
93
-
94
- "#{str_hex}#{Silkey::Utils.int_to_hex(user_signature_timestamp.to_s)}"
86
+ data = {
87
+ address: Silkey::Utils.strings_to_hex(['address']) + Silkey::Utils.remove0x(address).downcase,
88
+ migration: Silkey::Utils.strings_to_hex(['migration']) + (migration ? '01' : '00'),
89
+ scope: Silkey::Utils.strings_to_hex(['scope', scope]),
90
+ userSignatureTimestamp: Silkey::Utils.strings_to_hex(['userSignatureTimestamp']) +
91
+ Silkey::Utils.int_to_hex(user_signature_timestamp)
92
+ }
93
+
94
+ data.keys.sort.map { |k| data[k] }.join('')
95
95
  end
96
+ # rubocop:enable Metrics/AbcSize
96
97
 
97
98
  def message_to_sign_by_silkey
98
99
  return '' if Silkey::Utils.empty?(email)
@@ -101,36 +102,31 @@ module Silkey
101
102
  self.silkey_signature_timestamp = Silkey::Utils.current_timestamp
102
103
  end
103
104
 
104
- str_hex = [
105
- 'email', email,
106
- 'silkeySignatureTimestamp'
107
- ].map { |str| str.to_s.unpack('H*') }.join('')
108
-
109
- "#{str_hex}#{Silkey::Utils.int_to_hex(silkey_signature_timestamp.to_s)}"
105
+ "#{email.to_s.unpack('H*')[0]}#{Silkey::Utils.int_to_hex(silkey_signature_timestamp)}"
110
106
  end
111
107
 
112
108
  def validate
113
109
  raise "address is invalid: #{address}" unless Silkey::Utils.ethereum_address?(address)
114
110
 
115
- unless Silkey::Utils.signature?(user_signature)
116
- raise "user_signature is invalid: #{user_signature}"
117
- end
111
+ raise "user_signature is invalid: #{user_signature}" unless Silkey::Utils.signature?(user_signature)
118
112
 
119
- raise 'user_signature_timestamp is empty' if Silkey::Utils.empty?(user_signature_timestamp)
113
+ raise 'user_signature_timestamp is invalid' unless Silkey::Utils.timestamp?(user_signature_timestamp)
120
114
 
121
115
  return self if Silkey::Utils.empty?(scope) || scope == 'id'
122
116
 
123
117
  validate_scope_email
124
118
  end
125
119
 
126
- def import(hash)
127
- hash.each do |k, v|
120
+ def import(data = {})
121
+ return data if data.is_a?(Silkey::Models::JwtPayload)
122
+
123
+ data.each do |k, v|
128
124
  var = k.to_s.underscore
129
125
 
130
- if k == 'scope'
126
+ if var == 'scope'
131
127
  set_scope(v)
132
128
  else
133
- self.instance_variable_set("@#{var}", v)
129
+ instance_variable_set("@#{var}", v)
134
130
  end
135
131
  end
136
132
 
@@ -139,16 +135,24 @@ module Silkey
139
135
 
140
136
  private
141
137
 
138
+ def pack_payload_to_hex
139
+ str1_hex = 'address'.unpack('H*')[0]
140
+ adr_hex = Silkey::Utils.remove0x(address).downcase
141
+
142
+ str2_hex = [
143
+ 'scope', scope,
144
+ 'userSignatureTimestamp'
145
+ ].map { |str| str.to_s.unpack('H*') }.join('')
146
+
147
+ "#{str1_hex}#{adr_hex}#{str2_hex}"
148
+ end
149
+
142
150
  def validate_scope_email
143
151
  raise 'email is empty' if Silkey::Utils.empty?(email)
144
152
 
145
- unless Silkey::Utils.signature?(silkey_signature)
146
- raise "silkey_signature is invalid: #{silkey_signature}"
147
- end
153
+ raise "silkey_signature is invalid: #{silkey_signature}" unless Silkey::Utils.signature?(silkey_signature)
148
154
 
149
- if Silkey::Utils.empty?(silkey_signature_timestamp)
150
- raise 'silkey_signature_timestamp is empty'
151
- end
155
+ raise 'silkey_signature_timestamp is invalid' unless Silkey::Utils.timestamp?(silkey_signature_timestamp)
152
156
 
153
157
  self
154
158
  end