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 cipher algorithm used for encryption and decryption

'AES-256-CBC'
KEY_ITERATIONS =

PBKDF2 iteration count for key derivation PBKDF2 iteration count for key derivation

10_000
KEY_LENGTH =

Key length for AES-256 (32 bytes = 256 bits) 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 parameters.

Examples:

decrypted_password = PasswordCipher.decrypt(encrypted_password, mode: :standard, account_name: "my_account")

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).

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

    The master password for enhanced mode (required).

Returns:

  • (String)

    The decrypted password.

Raises:

  • DecryptionError if decryption fails.

  • ArgumentError if the parameters are invalid.



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

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 parameters.

Examples:

encrypted_password = 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).

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

    The master password for enhanced mode (required).

Returns:

  • (String)

    The Base64 encoded encrypted password.

Raises:

  • ArgumentError if the parameters are invalid.



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

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