Class: Sia::Lock

Inherits:
Object
  • Object
show all
Defined in:
lib/sia/lock.rb

Overview

Every good safe needs a safe lock

Used by Sia::Safe to do the heavy cryptographical lifting

  • Securely derives its symmetric key from a user's password using OpenSSL::PKCS5
  • Uses an OpenSSL::Cipher for encryption

Ex:

lock = Sia::Lock.new('pass', 'salt', 1_000, 1_000_000)
lock.encrypt_to_file('Hello World!', '/path/to/secure/file')
File.read('/path/to/secure/file')
# => "\u0016\x8A\x88/%\x90\xDF\u007F\xFC@\xCB\t\u001FTp`(\xBF\x8DR\x9E\x91\x8F\xC1FX\x8F7\xF6-+2"
lock.decrypt_from_file('/path/to/secure/file')
# => "Hello World!"

Constant Summary collapse

DIGEST =

The digest to use. Safes use the length of the digest to make the salt.

OpenSSL::Digest::SHA256

Instance Method Summary collapse

Constructor Details

#initialize(password, salt, buffer_bytes, digest_iterations) ⇒ Lock

Parameters:

  • password (String)
  • salt (String)
  • buffer_bytes (Integer)

    The buffer size for reading/writing to file.

  • digest_iterations (Integer)

    Increase this to increase hashing time.



30
31
32
33
34
35
36
37
38
39
# File 'lib/sia/lock.rb', line 30

def initialize(password, salt, buffer_bytes, digest_iterations)
  @buffer_bytes = buffer_bytes

  # Don't let the symmetric_key accidentally show up in logs or in the
  # console. Instead of storing it in an instance variable store it in a
  # private method.
  key = digest_password(password, salt, digest_iterations)
  define_singleton_method(:symmetric_key) { key }
  self.singleton_class.send(:private, :symmetric_key)
end

Instance Method Details

#decrypt(clear, secure) ⇒ Object

Decrypt a secure file into a clear file, removing the secure file.

This is better set up to handle large amounts of data than #decrypt_from_file, which has to hold the entire clear string in memory.

Parameters:

  • clear (Pathname)

    Absolute path to the clear file.

  • secure (Pathname)

    Absolute path to the secure file.



80
81
82
83
# File 'lib/sia/lock.rb', line 80

def decrypt(clear, secure)
  clear.open('wb') { |c| secure.open('rb') { |s| basic_decrypt(c, s) } }
  secure.delete
end

#decrypt_from_file(secure) ⇒ String

Used for decrypting the index file into memory

Parameters:

  • secure (Pathname)

    Absolute path to the secure file

Returns:

  • (String)


55
56
57
# File 'lib/sia/lock.rb', line 55

def decrypt_from_file(secure)
  secure.open('rb') { |s| basic_decrypt(StringIO.new, s).string }
end

#encrypt(clear, secure) ⇒ Object

Encrypt a clear file into a secure file, removing the clear file.

This is better set up to handle large amounts of data than #encrypt_to_file, which has to hold the entire clear string in memory.

Parameters:

  • clear (Pathname)

    Absolute path to the clear file.

  • secure (Pathname)

    Absolute path to the secure file.



67
68
69
70
# File 'lib/sia/lock.rb', line 67

def encrypt(clear, secure)
  clear.open('rb') { |c| secure.open('wb') { |s| basic_encrypt(c, s) } }
  clear.delete
end

#encrypt_to_file(string, secure) ⇒ Object

Used for encrypting the index file from memory

Parameters:

  • string (Pathname)

    The string to encrypt

  • secure (Pathname)

    Absolute path to the secure file



46
47
48
# File 'lib/sia/lock.rb', line 46

def encrypt_to_file(string, secure)
  secure.open('wb') { |s| basic_encrypt(StringIO.new(string), s) }
end