ubiq-security 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,154 +13,161 @@
13
13
  #
14
14
  # https://ubiqsecurity.com/legal
15
15
  #
16
+
17
+ # frozen_string_literal: true
18
+
16
19
  require 'rb-readline'
17
20
  require 'byebug'
18
21
  require 'httparty'
19
- require "active_support/all"
22
+ require 'active_support/all'
20
23
  require_relative './auth.rb'
21
24
  require_relative './algo.rb'
22
25
  require 'webrick'
23
26
 
27
+ # Ubiq Security Modules for encrypting / decrypting data
24
28
  module Ubiq
29
+ # Ubiq Encryption object
30
+ # This object represents a single data encryption key and can be used to
31
+ # encrypt several separate plain texts using the same key
32
+ class Encryption
33
+ def initialize(creds, uses)
34
+ raise 'Some of your credentials are missing, please check!' unless validate_creds(creds)
25
35
 
26
- # Ubiq Encryption object
27
- # This object represents a single data encryption key and can be used to encrypt several separate plain texts using the same key
28
- class Encryption
29
- def initialize(creds, uses)
30
-
31
- raise RuntimeError, 'Some of your credentials are missing, please check!' if !validate_creds(creds)
32
-
33
- # Set host, either the default or the one given by caller
34
- @host = creds.host.blank? ? UBIQ_HOST : creds.host
36
+ # Set host, either the default or the one given by caller
37
+ @host = creds.host.blank? ? UBIQ_HOST : creds.host
35
38
 
36
- # Set the credentials in instance varibales to be used among methods
37
- # The client's public API key (used to identify the client to the server
38
- @papi = creds.access_key_id
39
+ # Set the credentials in instance varibales to be used among methods
40
+ # The client's public API key (used to identify the client to the server
41
+ @papi = creds.access_key_id
39
42
 
40
- # The client's secret API key (used to authenticate HTTP requests)
41
- @sapi = creds.secret_signing_key
43
+ # The client's secret API key (used to authenticate HTTP requests)
44
+ @sapi = creds.secret_signing_key
42
45
 
43
- # The client's secret RSA encryption key/password (used to decrypt the client's RSA key from the server). This key is not retained by this object.
44
- @srsa = creds.secret_crypto_access_key
46
+ # The client's secret RSA encryption key/password (used to decrypt the
47
+ # client's RSA key from the server). This key is not retained by this object.
48
+ @srsa = creds.secret_crypto_access_key
45
49
 
46
- # Build the endpoint URL
47
- url = endpoint_base + '/encryption/key'
50
+ # Build the endpoint URL
51
+ url = endpoint_base + '/encryption/key'
48
52
 
49
- # Build the Request Body with the number of uses of key
50
- query = {uses: uses}
53
+ # Build the Request Body with the number of uses of key
54
+ query = { uses: uses }
51
55
 
52
- # Retrieve the necessary headers to make the request using Auth Object
53
- headers = Auth.build_headers(@papi, @sapi, endpoint, query, @host,'post')
56
+ # Retrieve the necessary headers to make the request using Auth Object
57
+ headers = Auth.build_headers(@papi, @sapi, endpoint, query, @host, 'post')
54
58
 
55
- @encryption_started = false
56
- @encryption_ready = true
59
+ @encryption_started = false
60
+ @encryption_ready = true
57
61
 
58
- # Request a new encryption key from the server. if the request
59
- # fails, the function raises a HTTPError indicating
60
- # the status code returned by the server. this exception is
61
- # propagated back to the caller
62
+ # Request a new encryption key from the server. if the request
63
+ # fails, the function raises a HTTPError indicating
64
+ # the status code returned by the server. this exception is
65
+ # propagated back to the caller
62
66
 
63
- begin
64
- response = HTTParty.post(
65
- url,
66
- body: query.to_json,
67
- headers: headers
68
- )
69
- rescue HTTParty::Error
70
- raise RuntimeError, 'Cant reach server'
67
+ begin
68
+ response = HTTParty.post(
69
+ url,
70
+ body: query.to_json,
71
+ headers: headers
72
+ )
73
+ rescue HTTParty::Error
74
+ raise 'Cant reach server'
75
+ end
76
+
77
+ # Response status is 201 Created
78
+ if response.code == WEBrick::HTTPStatus::RC_CREATED
79
+ # The code below largely assumes that the server returns
80
+ # a json object that contains the members and is formatted
81
+ # according to the Ubiq REST specification.
82
+
83
+ # Build the key object
84
+ @key = {}
85
+ @key['id'] = response['key_fingerprint']
86
+ @key['session'] = response['encryption_session']
87
+ @key['security_model'] = response['security_model']
88
+ @key['algorithm'] = response['security_model']['algorithm'].downcase
89
+ @key['max_uses'] = response['max_uses']
90
+ @key['uses'] = 0
91
+ @key['encrypted'] = Base64.strict_decode64(response['encrypted_data_key'])
92
+
93
+ # Get encrypted private key from response body
94
+ encrypted_private_key = response['encrypted_private_key']
95
+ # Get wrapped data key from response body
96
+ wrapped_data_key = response['wrapped_data_key']
97
+ # Decrypt the encryped private key using @srsa supplied
98
+ private_key = OpenSSL::PKey::RSA.new(encrypted_private_key, @srsa)
99
+ # Decode WDK from base64 format
100
+ wdk = Base64.strict_decode64(wrapped_data_key)
101
+ # Use private key to decrypt the wrapped data key
102
+ dk = private_key.private_decrypt(wdk, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
103
+ @key['raw'] = dk
104
+ # Build the algorithm object
105
+ @algo = Algo.new.get_algo(@key['algorithm'])
106
+ else
107
+ # Raise the error if response is not 201
108
+ raise "HTTPError Response: Expected 201, got #{response.code}"
109
+ end
71
110
  end
72
111
 
73
- # Response status is 201 Created
74
- if response.code == WEBrick::HTTPStatus::RC_CREATED
75
- # The code below largely assumes that the server returns
76
- # a json object that contains the members and is formatted
77
- # according to the Ubiq REST specification.
78
-
79
- # Build the key object
80
- @key = {}
81
- @key['id'] = response['key_fingerprint']
82
- @key['session'] = response['encryption_session']
83
- @key['security_model'] = response['security_model']
84
- @key['algorithm'] = response['security_model']['algorithm'].downcase
85
- @key['max_uses'] = response['max_uses']
86
- @key['uses'] = 0
87
- @key['encrypted'] = Base64.strict_decode64(response['encrypted_data_key'])
88
-
89
- # Get encrypted private key from response body
90
- encrypted_private_key = response['encrypted_private_key']
91
- # Get wrapped data key from response body
92
- wrapped_data_key = response['wrapped_data_key']
93
- # Decrypt the encryped private key using @srsa supplied
94
- private_key = OpenSSL::PKey::RSA.new(encrypted_private_key,@srsa)
95
- # Decode WDK from base64 format
96
- wdk = Base64.strict_decode64(wrapped_data_key)
97
- # Use private key to decrypt the wrapped data key
98
- dk = private_key.private_decrypt(wdk,OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
99
- @key['raw'] = dk
100
- # Build the algorithm object
101
- @algo = Algo.new.get_algo(@key['algorithm'])
102
- else
103
- # Raise the error if response is not 201
104
- raise RuntimeError, "HTTPError Response: Expected 201, got #{response.code}"
105
- end
112
+ def begin
113
+ # Begin the encryption process
106
114
 
107
- end
115
+ # When this function is called, the encryption object increments
116
+ # the number of uses of the key and creates a new internal context
117
+ # to be used to encrypt the data.
118
+ # If the encryption object is not yet ready to be used, throw an error
119
+ raise 'Encryption not ready' unless @encryption_ready
108
120
 
109
- def begin
110
- # Begin the encryption process
111
-
112
- # When this function is called, the encryption object increments
113
- # the number of uses of the key and creates a new internal context
114
- # to be used to encrypt the data.
115
- # If the encryption object is not yet ready to be used, throw an error
116
- raise RuntimeError, 'Encryption not ready' if !@encryption_ready
117
-
118
- # if Encryption cipher context already exists
119
- raise RuntimeError, 'Encryption already in progress' if @encryption_started
120
- # If max uses > uses
121
- raise RuntimeError, 'Maximum key uses exceeded' if @key['uses'] >= @key['max_uses']
122
- @key['uses'] += 1
123
- # create a new Encryption context and initialization vector
124
- @enc , @iv = Algo.new.encryptor(@algo, @key['raw'])
125
-
126
- # Pack the result into bytes to get a byte string
127
- struct = [0, 0, @algo[:id], @iv.length, @key['encrypted'].length].pack('CCCCn')
128
- @encryption_started = true
129
- return struct + @iv + @key['encrypted']
130
- end
121
+ # if Encryption cipher context already exists
122
+ raise 'Encryption already in progress' if @encryption_started
123
+ # If max uses > uses
124
+ raise 'Maximum key uses exceeded' if @key['uses'] >= @key['max_uses']
131
125
 
132
- def update(data)
133
- raise RuntimeError, 'Encryption is not Started' if !@encryption_started
134
- # Encryption of some plain text is perfomed here
135
- # Any cipher text produced by the operation is returned
136
- @enc.update(data)
137
- end
126
+ @key['uses'] += 1
127
+ # create a new Encryption context and initialization vector
128
+ @enc, @iv = Algo.new.encryptor(@algo, @key['raw'])
138
129
 
139
- def end
140
- raise RuntimeError, 'Encryption is not Started' if !@encryption_started
141
- # This function finalizes the encryption (producing the final
142
- # cipher text for the encryption, if necessary) and adds any
143
- # authentication information (if required by the algorithm).
144
- # Any data produced is returned by the function.
145
-
146
- # Finalize an encryption
147
- res = @enc.final
148
- if @algo[:tag_length] != 0
149
- # Add the tag to the cipher text
150
- res+= @enc.auth_tag
130
+ # Pack the result into bytes to get a byte string
131
+ struct = [0, 0, @algo[:id], @iv.length, @key['encrypted'].length].pack('CCCCn')
132
+ @encryption_started = true
133
+ return struct + @iv + @key['encrypted']
134
+ end
135
+
136
+ def update(data)
137
+ raise 'Encryption is not Started' unless @encryption_started
138
+
139
+ # Encryption of some plain text is perfomed here
140
+ # Any cipher text produced by the operation is returned
141
+ @enc.update(data)
151
142
  end
152
- @encryption_started = false
153
- # Return the encrypted result
154
- return res
155
- end
156
143
 
157
- def close
158
- raise RuntimeError, 'Encryption currently running' if @encryption_started
159
- # If the key was used less times than was requested, send an update to the server
160
- if @key['uses'] < @key['max_uses']
161
- query_url = "#{endpoint}/#{@key['id']}/#{@key['session']}"
144
+ def end
145
+ raise 'Encryption is not Started' unless @encryption_started
146
+
147
+ # This function finalizes the encryption (producing the final
148
+ # cipher text for the encryption, if necessary) and adds any
149
+ # authentication information (if required by the algorithm).
150
+ # Any data produced is returned by the function.
151
+
152
+ # Finalize an encryption
153
+ res = @enc.final
154
+ if @algo[:tag_length] != 0
155
+ # Add the tag to the cipher text
156
+ res += @enc.auth_tag
157
+ end
158
+ @encryption_started = false
159
+ # Return the encrypted result
160
+ return res
161
+ end
162
+
163
+ def close
164
+ raise 'Encryption currently running' if @encryption_started
165
+
166
+ # If the key was used less times than was requested, send an update to the server
167
+ if @key['uses'] < @key['max_uses']
168
+ query_url = "#{endpoint}/#{@key['id']}/#{@key['session']}"
162
169
  url = "#{endpoint_base}/encryption/key/#{@key['id']}/#{@key['session']}"
163
- query = {actual: @key['uses'], requested: @key['max_uses']}
170
+ query = { actual: @key['uses'], requested: @key['max_uses'] }
164
171
  headers = Auth.build_headers(@papi, @sapi, query_url, query, @host, 'patch')
165
172
  response = HTTParty.patch(
166
173
  url,
@@ -168,40 +175,43 @@ class Encryption
168
175
  headers: headers
169
176
  )
170
177
  remove_instance_variable(:@key)
171
- @encryption_ready = false;
178
+ @encryption_ready = false
179
+ end
172
180
  end
173
- end
174
181
 
175
- def endpoint_base
176
- @host + '/api/v0'
177
- end
182
+ def endpoint_base
183
+ @host + '/api/v0'
184
+ end
185
+
186
+ def endpoint
187
+ '/api/v0/encryption/key'
188
+ end
178
189
 
179
- def endpoint
180
- '/api/v0/encryption/key'
190
+ def validate_creds(credentials)
191
+ # This method checks for the presence of the credentials
192
+ !credentials.access_key_id.blank? &&
193
+ !credentials.secret_signing_key.blank? &&
194
+ !credentials.secret_crypto_access_key.blank?
195
+ end
181
196
  end
182
197
 
183
198
  def validate_creds(credentials)
184
199
  # This method checks for the presence of the credentials
185
- !credentials.access_key_id.blank? and !credentials.secret_signing_key.blank? and !credentials.secret_crypto_access_key.blank?
200
+ !credentials.access_key_id.blank? &&
201
+ !credentials.secret_signing_key.blank? &&
202
+ !credentials.secret_crypto_access_key.blank?
186
203
  end
187
204
 
188
- end
189
-
190
- def validate_creds(credentials)
191
- # This method checks for the presence of the credentials
192
- !credentials.access_key_id.blank? and !credentials.secret_signing_key.blank? and !credentials.secret_crypto_access_key.blank?
193
- end
194
-
195
- def encrypt(creds, data)
196
- begin
197
- enc = Encryption.new(creds, 1)
198
- res = enc.begin() + enc.update(data) + enc.end()
199
- enc.close()
200
- rescue
201
- enc.close() if enc
202
- raise
205
+ def encrypt(creds, data)
206
+ begin
207
+ enc = Encryption.new(creds, 1)
208
+ res = enc.begin + enc.update(data) + enc.end
209
+ enc.close
210
+ rescue StandardError
211
+ enc&.close
212
+ raise
213
+ end
214
+ return res
203
215
  end
204
- return res
205
216
  end
206
217
 
207
- end
@@ -14,5 +14,5 @@
14
14
  # https://ubiqsecurity.com/legal
15
15
  #
16
16
  module Ubiq
17
- UBIQ_HOST = 'api.ubiqsecurity.com:8811'
17
+ UBIQ_HOST = 'api.ubiqsecurity.com:8811'
18
18
  end
@@ -17,6 +17,5 @@
17
17
  # frozen_string_literal: true
18
18
 
19
19
  module Ubiq
20
- VERSION = "1.0.0"
20
+ VERSION = '1.0.1'
21
21
  end
22
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ubiq-security
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ubiq Security, Inc.