class StraightServer::GatewayOnDB
Uses database to load and save attributes
Attributes
This virtual attribute is important because it's difficult to detect whether secret was actually updated or not. Sequel's changed_columns may mistakenly say :secret attr was changed, while it hasn't. Thus we provide a manual way of ensuring this. It's also better and works as safety switch: we don't want somebody accidentally updating a secret.
Public Class Methods
# File lib/straight-server/gateway.rb, line 366 def self.find_by_hashed_id(s) self.where(hashed_id: s).first end
# File lib/straight-server/gateway.rb, line 421 def self.find_by_id(id) self[id] end
Public Instance Methods
# File lib/straight-server/gateway.rb, line 450 def address_provider Kernel.const_get("Straight::AddressProvider::#{address_provider_type}").new(self) end
# File lib/straight-server/gateway.rb, line 446 def address_provider_type self[:address_provider] ? self[:address_provider].to_sym : :Bip32 end
# File lib/straight-server/gateway.rb, line 389 def after_create @@websockets[self.id] = {} update(hashed_id: OpenSSL::HMAC.digest('sha256', Config.server_secret, self.id.to_s).unpack("H*").first) end
# File lib/straight-server/gateway.rb, line 394 def after_initialize @status_check_schedule = Straight::GatewayModule::DEFAULT_STATUS_CHECK_SCHEDULE @@websockets[self.id] ||= {} if self.id initialize_callbacks initialize_exchange_rate_adapters initialize_blockchain_adapters initialize_status_check_schedule initialize_network end
# File lib/straight-server/gateway.rb, line 376 def before_create super encrypt_secret self.test_mode ||= false self.test_last_keychain_id ||= 0 end
# File lib/straight-server/gateway.rb, line 383 def before_update encrypt_secret if @update_secret @update_secret = false super end
# File lib/straight-server/gateway.rb, line 454 def disable_test_mode! self[:test_mode] = false save(columns: 'test_mode') end
# File lib/straight-server/gateway.rb, line 459 def enable_test_mode! self[:test_mode] = true save(columns: 'test_mode') end
# File lib/straight-server/gateway.rb, line 425 def encrypt_secret cipher = OpenSSL::Cipher::AES.new(128, :CBC) cipher.encrypt cipher.key = OpenSSL::HMAC.digest('sha256', 'nonce', Config.server_secret).unpack("H*").first[0,16] cipher.iv = iv = OpenSSL::HMAC.digest('sha256', 'nonce', "#{self.class.max(:id)}#{Config.server_secret}").unpack("H*").first[0,16] raise "cipher.iv cannot be nil" unless iv encrypted = cipher.update(self[:secret]) << cipher.final() base64_encrypted = Base64.strict_encode64(encrypted).encode('utf-8') result = "#{iv}:#{base64_encrypted}" # Check whether we can decrypt. It should not be possible to encrypt the # gateway secret unless we are sure we can decrypt it. if decrypt_secret(result) == self[:secret] self.secret = result else raise "Decrypted and original secrets don't match! Cannot proceed with writing the encrypted gateway secret." end end
We cannot allow to store gateway secret in a DB plaintext, this would be completetly unsecure. Althougth we use symmetrical encryption here and store the encryption key in the server's in a special file (~/.straight/server_secret), which in turn can also be stolen, this is still marginally better than doing nothing.
Also, server admnistrators now have the freedom of developing their own strategy of storing that secret - it doesn't have to be stored on the same machine.
# File lib/straight-server/gateway.rb, line 417 def secret decrypt_secret end
# File lib/straight-server/gateway.rb, line 404 def validate super errors.add(:pubkey, "Please provide public key") if pubkey_missing? errors.add(:test_pubkey, "Please provide test public key if you activate test mode") if test_pubkey_missing? end
Private Instance Methods
# File lib/straight-server/gateway.rb, line 466 def decrypt_secret(encrypted_field=self[:secret]) decipher = OpenSSL::Cipher::AES.new(128, :CBC) iv, encrypted = encrypted_field.split(':') decipher.decrypt decipher.key = OpenSSL::HMAC.digest('sha256', 'nonce', Config.server_secret).unpack("H*").first[0,16] decipher.iv = iv decipher.update(Base64.decode64(encrypted)) + decipher.final end