credify 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2d00a170decb583685246f229dced080b4eb29399773680f0e8599ee8873af7
4
- data.tar.gz: 12d6f970b75bd07c67cfa444e2c8ae7e7a2a5c70ed014cb52b375fb81a21cf20
3
+ metadata.gz: 22b70b4ef4e0b030632a418609e96ff5f84002c57c2ab03f0b8dfa96c2269079
4
+ data.tar.gz: 27e4c5183a0ddd41131a00ba8ef76ceab4a335c13047a8285ad4c11f3855cd82
5
5
  SHA512:
6
- metadata.gz: 8a7b1682b30baffd0ef0c413ae6b26e9a24203323da32be9e59fc63f8a37c25c95b2dbc9ce4423ff9fb917429431693680d47a70275e9c12cb2cea41e70be470
7
- data.tar.gz: '058461c70f4d213b42216407bd996237cfe207883e732bfb19d1cd1dd7b53bc35efc081c439312491c0e2780ea52277cace79e42a61e0c697546890baa77a0c5'
6
+ metadata.gz: cd20625b4eaecd91a65127d140d5fb746076ae15b064dac3a27d88f5802049f14129543ef810a166838ba71352ade6cb58b051abb4a6e6b17565d8cc0cd03d60
7
+ data.tar.gz: 3bfc34738682cab00664f8264e0a9f19118964b7ce4b218e47c14a507f4152711178425caf7235a9a5d869bda59badfd2fbb4f2b6ff6c5cf17795fb095fa79f3
data/README.md CHANGED
@@ -40,6 +40,27 @@ def existing_key_is_used
40
40
  valid = signing.verify "message", signature
41
41
  puts valid
42
42
  end
43
+
44
+ def generate_approval_token
45
+ signing = Signing.new
46
+ signing.generate_key_pair
47
+ token = signing.generate_approval_token 'client_id', 'entity_id', ['openid', 'email', 'phone'], 'offer-code'
48
+ puts token
49
+ end
50
+
51
+ def generate_request_token
52
+ signing = Signing.new
53
+ signing.generate_key_pair
54
+ token = signing.generate_request_token 'client_id', 'encryption_public_key', ['openid', 'email', 'phone'], 'offer-code'
55
+ puts token
56
+ end
57
+
58
+ def generate_claim_token
59
+ signing = Signing.new
60
+ signing.generate_key_pair
61
+ result = signing.generate_claim_token 'provider_id', 'entity_id', 'credify-score', { score: 100 }
62
+ puts result
63
+ end
43
64
  ```
44
65
 
45
66
  ### Encryption
@@ -54,6 +75,8 @@ def new_key_is_generated
54
75
  encryption.generate_key_pair
55
76
  cipher_text = encryption.encrypt "secret message"
56
77
  plain_text = encryption.decrypt cipher_text
78
+ pem = encryption.export_private_key
79
+ puts pem
57
80
  end
58
81
 
59
82
  def existing_key_is_used
data/lib/credify.rb CHANGED
@@ -1,6 +1,36 @@
1
1
  require "credify/version"
2
+ require 'base64'
3
+ require 'securerandom'
2
4
 
3
5
  module Credify
4
6
  class Error < StandardError; end
5
- # Your code goes here...
7
+
8
+ class Helpers
9
+ def self.sha256(message)
10
+ base64 = Digest::SHA256.base64digest(message)
11
+ Helpers.short_urlsafe_encode64(Base64.decode64(base64))
12
+ end
13
+
14
+ #
15
+ # short_urlsafe_encode64
16
+ # @param [Binary] - str
17
+ # @return [String] - Base64 URL encoded string without padding
18
+ def self.short_urlsafe_encode64(bytes)
19
+ Base64.urlsafe_encode64(bytes).delete('=')
20
+ end
21
+
22
+ #
23
+ # short_urlsafe_decode64
24
+ # @return [Binary]
25
+ def self.short_urlsafe_decode64(str)
26
+ Base64.urlsafe_decode64(str + '=' * (-1 * str.size & 3))
27
+ end
28
+
29
+ def self.generate_commitment(bytes = 32)
30
+ random_bytes = SecureRandom.random_bytes(bytes)
31
+ short_urlsafe_encode64(random_bytes)
32
+ end
33
+
34
+ end
35
+
6
36
  end
@@ -2,6 +2,7 @@ require 'openssl'
2
2
  require 'openssl/oaep'
3
3
  require "base64"
4
4
  require 'openssl_pkcs8_pure'
5
+ require 'credify'
5
6
 
6
7
  class Encryption
7
8
  attr_reader :private_key, :public_key
@@ -43,7 +44,7 @@ class Encryption
43
44
  # @param [String] payload - Base64 URL encoded string
44
45
  # @return [Boolean]
45
46
  def import_private_key_base64_url(payload)
46
- bytes = short_urlsafe_decode64(payload)
47
+ bytes = Credify::Helpers.short_urlsafe_decode64(payload)
47
48
  base64 = Base64.encode64(bytes)
48
49
  formatted = base64.scan(/.{1,64}/).join("\n")
49
50
  pem = add_box('PRIVATE KEY', formatted)
@@ -55,7 +56,7 @@ class Encryption
55
56
  # @param [String] payload - Base64 URL encoded string
56
57
  # @return [Boolean]
57
58
  def import_public_key_base64_url(payload)
58
- bytes = short_urlsafe_decode64(payload)
59
+ bytes = Credify::Helpers.short_urlsafe_decode64(payload)
59
60
  base64 = Base64.encode64(bytes)
60
61
  formatted = base64.scan(/.{1,64}/).join("\n")
61
62
  pem = add_box('PUBLIC KEY', formatted)
@@ -73,7 +74,7 @@ class Encryption
73
74
  label = ''
74
75
  md = OpenSSL::Digest::SHA256
75
76
  cipher_text = @public_key.public_encrypt_oaep(message, label, md)
76
- short_urlsafe_encode64(cipher_text)
77
+ Credify::Helpers.short_urlsafe_encode64(cipher_text)
77
78
  end
78
79
 
79
80
  #
@@ -86,7 +87,7 @@ class Encryption
86
87
  end
87
88
  label = ''
88
89
  md = OpenSSL::Digest::SHA256
89
- raw_cipher = short_urlsafe_decode64(cipher)
90
+ raw_cipher = Credify::Helpers.short_urlsafe_decode64(cipher)
90
91
  raw_text = @private_key.private_decrypt_oaep(raw_cipher, label, md)
91
92
  raw_text
92
93
  end
@@ -94,7 +95,7 @@ class Encryption
94
95
  #
95
96
  # export_private_key
96
97
  # @param [Boolean] in_base64_url
97
- # @return [Signing] - PCKS8 PEM or Base64 URL encoded string
98
+ # @return [Signing | String] - PCKS8 PEM or Base64 URL encoded string
98
99
  def export_private_key(in_base64_url = false)
99
100
  if @private_key.nil?
100
101
  raise Exception.new 'Please pass private key'
@@ -103,7 +104,7 @@ class Encryption
103
104
 
104
105
  if in_base64_url
105
106
  formatted = remove_box('PRIVATE KEY', pem)
106
- short_urlsafe_encode64(Base64.decode64(formatted))
107
+ Credify::Helpers.short_urlsafe_encode64(Base64.decode64(formatted))
107
108
  else
108
109
  pem
109
110
  end
@@ -112,7 +113,7 @@ class Encryption
112
113
  #
113
114
  # export_public_key
114
115
  # @param [Boolean] in_base64_url
115
- # @return [Signing] - PCKS8 PEM or Base64 URL encoded string
116
+ # @return [Signing | String] - PCKS8 PEM or Base64 URL encoded string
116
117
  def export_public_key(in_base64_url = false)
117
118
  if @public_key.nil?
118
119
  raise Exception.new 'Please pass public key'
@@ -122,7 +123,7 @@ class Encryption
122
123
 
123
124
  if in_base64_url
124
125
  formatted = remove_box('PUBLIC KEY', pem)
125
- short_urlsafe_encode64(Base64.decode64(formatted))
126
+ Credify::Helpers.short_urlsafe_encode64(Base64.decode64(formatted))
126
127
  else
127
128
  pem
128
129
  end
@@ -131,7 +132,7 @@ class Encryption
131
132
 
132
133
  protected
133
134
 
134
-
135
+ #
135
136
  # remove_box
136
137
  # @param [String] tag - Either 'PUBLIC KEY' or 'PRIVATE KEY'
137
138
  # @param [String] pem - String value loaded from a PEM file
@@ -152,18 +153,4 @@ class Encryption
152
153
  "-----BEGIN #{tag}-----\n" << payload << "\n-----END #{tag}-----"
153
154
  end
154
155
 
155
- #
156
- # short_urlsafe_encode64
157
- # @param [Binary] - str
158
- # @return [String] - Base64 URL encoded string without padding
159
- def short_urlsafe_encode64(bytes)
160
- Base64.urlsafe_encode64(bytes).delete('=')
161
- end
162
-
163
- #
164
- # short_urlsafe_decode64
165
- # @return [Binary]
166
- def short_urlsafe_decode64(str)
167
- Base64.urlsafe_decode64(str + '=' * (-1 * str.size & 3))
168
- end
169
156
  end
@@ -1,6 +1,8 @@
1
1
  require "ed25519"
2
2
  require "base64"
3
+ require 'json'
3
4
  require 'openssl_pkcs8_pure'
5
+ require 'credify'
4
6
 
5
7
  class Signing
6
8
  attr_reader :signing_key
@@ -31,7 +33,7 @@ class Signing
31
33
  raise Exception.new 'Please pass signing key'
32
34
  end
33
35
  signature = @signing_key.sign(message)
34
- short_urlsafe_encode64(signature)
36
+ Credify::Helpers.short_urlsafe_encode64(signature)
35
37
  end
36
38
 
37
39
  #
@@ -43,7 +45,7 @@ class Signing
43
45
  if @signing_key.nil?
44
46
  raise Exception.new 'Please pass signing key'
45
47
  end
46
- raw_sign = short_urlsafe_decode64(signature)
48
+ raw_sign = Credify::Helpers.short_urlsafe_decode64(signature)
47
49
  @signing_key.verify_key.verify raw_sign, message
48
50
  end
49
51
 
@@ -57,21 +59,134 @@ class Signing
57
59
  Base64.encode64(@signing_key.seed)
58
60
  end
59
61
 
60
- protected
62
+ #
63
+ # generate_jwt
64
+ # @param [Hash] payload
65
+ # @return [String]
66
+ def generate_jwt(payload)
67
+ if payload.empty?
68
+ raise Exception.new 'Invalid payload'
69
+ end
70
+ header = {
71
+ alg: 'EdDSA',
72
+ typ: 'JWT'
73
+ }
74
+ message = compose_message(header, payload)
75
+ signature = sign(message)
76
+ message << '.' << signature
77
+ end
78
+
79
+ #
80
+ # parse_jwt
81
+ # @param [String] jwt
82
+ # @return [Hash] - { header: '', payload: {}, signature: '' }
83
+ def parse_jwt(jwt)
84
+ components = jwt.split('.')
85
+ unless components.length == 3
86
+ raise Exception 'JST is invalid'
87
+ end
88
+
89
+ header = JSON.parse(Credify::Helpers.short_urlsafe_decode64(components[0]))
90
+ payload = JSON.parse(Credify::Helpers.short_urlsafe_decode64(components[1]))
91
+ { header: header, payload: payload, signature: components[2] }
92
+ end
93
+
94
+ #
95
+ # verify_jwt
96
+ # @param [Hash] jwt - { header: '', payload: {}, signature: '' }
97
+ # @return [Boolean]
98
+ def verify_jwt(jwt)
99
+ message = compose_message(jwt[:header], jwt[:payload])
100
+ verify(jwt[:signature], message)
101
+ end
61
102
 
62
103
  #
63
- # short_urlsafe_encode64
64
- # @param [Binary] - str
65
- # @return [String] - Base64 URL encoded string without padding
66
- def short_urlsafe_encode64(bytes)
67
- Base64.urlsafe_encode64(bytes).delete('=')
104
+ # generate_approval_token
105
+ # @param [String] client_id
106
+ # @param [String] entity_id
107
+ # @param [String[]] approved_scopes
108
+ # @param [String | nil] offer_code
109
+ # @return [String]
110
+ def generate_approval_token(client_id, entity_id, approved_scopes, offer_code = nil)
111
+ # minus 60 just in case this timestamp could collide one in the server side.
112
+ now = Time.now.to_i - 60
113
+ payload = {
114
+ client_id: client_id,
115
+ iat: now,
116
+ iss: entity_id,
117
+ scopes: approved_scopes.join(' ')
118
+ }
119
+ unless offer_code.nil?
120
+ payload[:offer_code] = offer_code
121
+ end
122
+ generate_jwt(payload)
123
+ end
124
+
125
+ #
126
+ # generate_claim_token
127
+ # @param [String] provider_id
128
+ # @param [String] entity_id
129
+ # @param [String] scope_name
130
+ # @param [Hash] claim
131
+ # @return [Hash]
132
+ def generate_claim_token(provider_id, entity_id, scope_name, claim)
133
+ # minus 60 just in case this timestamp could collide one in the server side.
134
+ now = Time.now.to_i - 60
135
+ commitment = Credify::Helpers.generate_commitment
136
+ data = claim[:"#{scope_name}:commitment"] = commitment
137
+ scope_hash = Credify::Helpers.sha256(data)
138
+ puts scope_hash
139
+ payload = {
140
+ iat: now,
141
+ iss: provider_id,
142
+ user_id: entity_id,
143
+ scope_name: scope_name,
144
+ scope_hash: scope_hash
145
+ }
146
+ token = generate_jwt(payload)
147
+ { token: token, commitment: commitment }
68
148
  end
69
149
 
70
150
  #
71
- # short_urlsafe_decode64
72
- # @return [Binary]
73
- def short_urlsafe_decode64(str)
74
- Base64.urlsafe_decode64(str + '=' * (-1 * str.size & 3))
151
+ # generate_request_token
152
+ # @param [String] client_id
153
+ # @param [String] encryption_public_key - Encryption public key in Base64 URL
154
+ # @param [String[]] scopes
155
+ # @param [String | nil] offer_code
156
+ # @return [String]
157
+ def generate_request_token(client_id, encryption_public_key, scopes, offer_code = nil)
158
+ unless scopes.include?('openid')
159
+ raise Exception 'scopes need to contain openid'
160
+ end
161
+ # minus 60 just in case this timestamp could collide one in the server side.
162
+ now = Time.now.to_i - 60
163
+ payload = {
164
+ iat: now,
165
+ iss: client_id,
166
+ encryption_public_key: encryption_public_key,
167
+ scopes: scopes.join(' ')
168
+ }
169
+ unless offer_code.nil?
170
+ payload[:offer_code] = offer_code
171
+ end
172
+ generate_jwt(payload)
173
+ end
174
+
175
+ protected
176
+
177
+
178
+ # compose_message
179
+ # @param [Hash] header
180
+ # @param [Hash] payload
181
+ # @return [String]
182
+ def compose_message(header, payload)
183
+ encoded_header = header.to_json
184
+ h = Credify::Helpers.short_urlsafe_encode64(encoded_header)
185
+
186
+ encoded_payload = payload.to_json
187
+ p = Credify::Helpers.short_urlsafe_encode64(encoded_payload)
188
+
189
+ h << '.' << p
75
190
  end
76
191
 
77
192
  end
@@ -1,3 +1,3 @@
1
1
  module Credify
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: credify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - credify-pte-ltd