Class: SecurityClient::Encryption
- Inherits:
-
Object
- Object
- SecurityClient::Encryption
- Defined in:
- lib/security_client.rb
Instance Method Summary collapse
- #begin ⇒ Object
- #close ⇒ Object
- #end ⇒ Object
- #endpoint ⇒ Object
- #endpoint_base ⇒ Object
-
#initialize(creds, uses) ⇒ Encryption
constructor
A new instance of Encryption.
- #update(data) ⇒ Object
- #validate_creds(credentials) ⇒ Object
Constructor Details
#initialize(creds, uses) ⇒ Encryption
Returns a new instance of Encryption.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/security_client.rb', line 51 def initialize(creds, uses) raise RuntimeError, 'Some of your credentials are missing, please check!' if !validate_creds(creds) # Set host, either the default or the one given by caller @host = creds.host.blank? ? VOLTRON_HOST : creds.host # Set the credentials in instance varibales to be used among methods # The client's public API key (used to identify the client to the server @papi = creds.access_key_id # The client's secret API key (used to authenticate HTTP requests) @sapi = creds.secret_signing_key # 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. @srsa = creds.secret_crypto_access_key # Build the endpoint URL url = endpoint_base + '/encryption/key' # Build the Request Body with the number of uses of key query = {uses: uses} # Retrieve the necessary headers to make the request using Auth Object headers = SecurityClient::Auth.build_headers(@papi, @sapi, endpoint, query, @host,'post') @encryption_started = false @encryption_ready = true # Request a new encryption key from the server. if the request # fails, the function raises a HTTPError indicating # the status code returned by the server. this exception is # propagated back to the caller begin response = HTTParty.post( url, body: query.to_json, headers: headers ) rescue HTTParty::Error raise RuntimeError, 'Cant reach server' end # Response status is 201 Created if response.code == WEBrick::HTTPStatus::RC_CREATED # The code below largely assumes that the server returns # a json object that contains the members and is formatted # according to the Voltron REST specification. # Build the key object @key = {} @key['id'] = response['key_fingerprint'] @key['session'] = response['encryption_session'] @key['security_model'] = response['security_model'] @key['algorithm'] = response['security_model']['algorithm'].downcase @key['max_uses'] = response['max_uses'] @key['uses'] = 0 @key['encrypted'] = Base64.strict_decode64(response['encrypted_data_key']) # Get encrypted private key from response body encrypted_private_key = response['encrypted_private_key'] # Get wrapped data key from response body wrapped_data_key = response['wrapped_data_key'] # Decrypt the encryped private key using @srsa supplied private_key = OpenSSL::PKey::RSA.new(encrypted_private_key,@srsa) # Decode WDK from base64 format wdk = Base64.strict_decode64(wrapped_data_key) # Use private key to decrypt the wrapped data key dk = private_key.private_decrypt(wdk,OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) @key['raw'] = dk # Build the algorithm object @algo = SecurityClient::Algo.new.get_algo(@key['algorithm']) else # Raise the error if response is not 201 raise RuntimeError, "HTTPError Response: Expected 201, got #{response.code}" end end |
Instance Method Details
#begin ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/security_client.rb', line 131 def begin # Begin the encryption process # When this function is called, the encryption object increments # the number of uses of the key and creates a new internal context # to be used to encrypt the data. # If the encryption object is not yet ready to be used, throw an error raise RuntimeError, 'Encryption not ready' if !@encryption_ready # if Encryption cipher context already exists raise RuntimeError, 'Encryption already in progress' if @encryption_started # If max uses > uses raise RuntimeError, 'Maximum key uses exceeded' if @key['uses'] >= @key['max_uses'] @key['uses'] += 1 # create a new Encryption context and initialization vector @enc , @iv = SecurityClient::Algo.new.encryptor(@algo, @key['raw']) # Pack the result into bytes to get a byte string struct = [0, 0, @algo[:id], @iv.length, @key['encrypted'].length].pack('CCCCn') @encryption_started = true return struct + @iv + @key['encrypted'] end |
#close ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/security_client.rb', line 179 def close raise RuntimeError, 'Encryption currently running' if @encryption_started # If the key was used less times than was requested, send an update to the server if @key['uses'] < @key['max_uses'] query_url = "#{endpoint}/#{@key['id']}/#{@key['session']}" url = "#{endpoint_base}/encryption/key/#{@key['id']}/#{@key['session']}" query = {actual: @key['uses'], requested: @key['max_uses']} headers = Auth.build_headers(@papi, @sapi, query_url, query, @host, 'patch') response = HTTParty.patch( url, body: query.to_json, headers: headers ) remove_instance_variable(:@key) @encryption_ready = false; end end |
#end ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/security_client.rb', line 161 def end raise RuntimeError, 'Encryption is not Started' if !@encryption_started # This function finalizes the encryption (producing the final # cipher text for the encryption, if necessary) and adds any # authentication information (if required by the algorithm). # Any data produced is returned by the function. # Finalize an encryption res = @enc.final if @algo[:tag_length] != 0 # Add the tag to the cipher text res+= @enc.auth_tag end @encryption_started = false # Return the encrypted result return res end |
#endpoint ⇒ Object
201 202 203 |
# File 'lib/security_client.rb', line 201 def endpoint '/api/v0/encryption/key' end |
#endpoint_base ⇒ Object
197 198 199 |
# File 'lib/security_client.rb', line 197 def endpoint_base @host + '/api/v0' end |
#update(data) ⇒ Object
154 155 156 157 158 159 |
# File 'lib/security_client.rb', line 154 def update(data) raise RuntimeError, 'Encryption is not Started' if !@encryption_started # Encryption of some plain text is perfomed here # Any cipher text produced by the operation is returned @enc.update(data) end |
#validate_creds(credentials) ⇒ Object
205 206 207 208 |
# File 'lib/security_client.rb', line 205 def validate_creds(credentials) # This method checks for the presence of the credentials !credentials.access_key_id.blank? and !credentials.secret_signing_key.blank? and !credentials.secret_crypto_access_key.blank? end |