Class: Omnizip::Crypto::Aes256::KeyDerivation

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/crypto/aes256/key_derivation.rb

Overview

7-Zip password-based key derivation

Uses SHA-256 iterative hashing to derive encryption keys from passwords. The number of iterations is 2^cycles_power.

Constant Summary

Constants included from Constants

Constants::BLOCK_SIZE, Constants::DEFAULT_CYCLES_POWER, Constants::IV_SIZE, Constants::KEY_SIZE, Constants::MAX_CYCLES_POWER, Constants::MIN_CYCLES_POWER, Constants::SALT_SIZE, Constants::SALT_SIZE_MAX

Class Method Summary collapse

Class Method Details

.derive_key(password, salt, cycles_power = DEFAULT_CYCLES_POWER) ⇒ String

Derive AES-256 key from password

This implements 7-Zip's key derivation:

  1. Concatenate salt and password
  2. Hash with SHA-256 for 2^cycles_power iterations
  3. Extract first 32 bytes as key

Parameters:

  • password (String)

    User password

  • salt (String)

    Random salt

  • cycles_power (Integer) (defaults to: DEFAULT_CYCLES_POWER)

    Power of 2 for iterations

Returns:

  • (String)

    32-byte AES-256 key



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/omnizip/crypto/aes256/key_derivation.rb', line 28

def self.derive_key(password, salt, cycles_power = DEFAULT_CYCLES_POWER)
  validate_inputs(password, salt, cycles_power)

  # Calculate number of iterations
  num_cycles = 1 << cycles_power

  # Initial input: salt + password (in UTF-16LE for 7-Zip compat)
  # Force binary encoding to make concatenation work
  encoded_password = encode_password(password).force_encoding(Encoding::BINARY)
  input = salt.dup.force_encoding(Encoding::BINARY) + encoded_password

  # Iterative SHA-256 hashing
  key = perform_hashing(input, num_cycles)

  # Return first 32 bytes
  key[0, KEY_SIZE]
end