Module: Lich::Common::GUI::PasswordCipher

Defined in:
documented/common/gui/password_cipher.rb

Defined Under Namespace

Classes: DecryptionError

Constant Summary collapse

CIPHER_ALGORITHM =

AES cipher algorithm

'AES-256-CBC'
KEY_ITERATIONS =

PBKDF2 iteration count for key derivation

10_000
KEY_LENGTH =

Key length for AES-256 (32 bytes = 256 bits)

32

Class Method Summary collapse

Class Method Details

.decrypt(encrypted_password, mode:, account_name: nil, master_password: nil) ⇒ String

Decrypts an encrypted password using the specified mode and optional parameters.

Examples:

Decrypt a password in enhanced mode

decrypted_password = Lich::Common::GUI::PasswordCipher.decrypt(encrypted_password, mode: :enhanced, master_password: "my_master_password")

Parameters:

  • encrypted_password (String)

    the Base64 encoded encrypted password to decrypt

  • mode (Symbol)

    the encryption mode, either :standard or :enhanced

  • account_name (String, nil) (defaults to: nil)

    the account name for standard mode (required if mode is :standard)

  • master_password (String, nil) (defaults to: nil)

    the master password for enhanced mode (required if mode is :enhanced)

Returns:

  • (String)

    the decrypted password

Raises:

  • ArgumentError if the parameters are invalid

  • DecryptionError if decryption fails



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
# File 'documented/common/gui/password_cipher.rb', line 65

def self.decrypt(encrypted_password, mode:, account_name: nil, master_password: nil)
  validate_encryption_params(mode, , master_password)

  # Derive decryption key based on mode
  key = derive_key(mode, , master_password)

  # Decode from Base64
  encrypted_data = Base64.strict_decode64(encrypted_password)

  # Extract IV and ciphertext
  cipher = OpenSSL::Cipher.new(CIPHER_ALGORITHM)
  iv_length = cipher.iv_len
  iv = encrypted_data[0...iv_length]
  ciphertext = encrypted_data[iv_length..]

  # Initialize cipher for decryption
  cipher.decrypt
  cipher.key = key
  cipher.iv = iv

  # Decrypt password
  decrypted = cipher.update(ciphertext) + cipher.final
  decrypted.force_encoding('UTF-8')
rescue OpenSSL::Cipher::CipherError, ArgumentError => e
  raise DecryptionError, "Failed to decrypt password: #{e.message}"
end

.encrypt(password, mode:, account_name: nil, master_password: nil) ⇒ String

Encrypts a password using the specified mode and optional parameters.

Examples:

Encrypt a password in standard mode

encrypted_password = Lich::Common::GUI::PasswordCipher.encrypt("my_password", mode: :standard, account_name: "my_account")

Parameters:

  • password (String)

    the password to encrypt

  • mode (Symbol)

    the encryption mode, either :standard or :enhanced

  • account_name (String, nil) (defaults to: nil)

    the account name for standard mode (required if mode is :standard)

  • master_password (String, nil) (defaults to: nil)

    the master password for enhanced mode (required if mode is :enhanced)

Returns:

  • (String)

    the Base64 encoded encrypted password

Raises:

  • ArgumentError if the parameters are invalid



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'documented/common/gui/password_cipher.rb', line 33

def self.encrypt(password, mode:, account_name: nil, master_password: nil)
  validate_encryption_params(mode, , master_password)

  # Derive encryption key based on mode
  key = derive_key(mode, , master_password)

  # Initialize cipher
  cipher = OpenSSL::Cipher.new(CIPHER_ALGORITHM)
  cipher.encrypt
  cipher.key = key

  # Generate random IV
  iv = cipher.random_iv

  # Encrypt password
  encrypted = cipher.update(password) + cipher.final

  # Combine IV + encrypted data and encode as Base64
  Base64.strict_encode64(iv + encrypted)
end