Class: Omnizip::Formats::SevenZip::HeaderEncryptor
- Inherits:
-
Object
- Object
- Omnizip::Formats::SevenZip::HeaderEncryptor
- Includes:
- Constants
- Defined in:
- lib/omnizip/formats/seven_zip/header_encryptor.rb
Overview
7z header encryption using AES-256 Encrypts archive headers to hide filenames and structure
Constant Summary collapse
- AES_KEY_SIZE =
AES-256 parameters
32- AES_IV_SIZE =
256 bits
16- SALT_SIZE =
128 bits
16- PBKDF2_ITERATIONS =
PBKDF2 parameters
262_144
Constants included from Constants
Constants::MAJOR_VERSION, Constants::MAX_NUM_BONDS, Constants::MAX_NUM_CODERS, Constants::MAX_NUM_PACK_STREAMS, Constants::MINOR_VERSION, Constants::SIGNATURE, Constants::SIGNATURE_SIZE, Constants::START_HEADER_SIZE
Instance Attribute Summary collapse
-
#iv ⇒ Object
readonly
256K iterations for strong key derivation.
-
#password ⇒ Object
readonly
256K iterations for strong key derivation.
-
#salt ⇒ Object
readonly
256K iterations for strong key derivation.
Instance Method Summary collapse
-
#calculate_crc(data) ⇒ Integer
Calculate CRC of header data.
-
#decrypt(encrypted_data, salt, iv) ⇒ String
Decrypt header data.
-
#derive_key(password, salt) ⇒ String
Derive encryption key from password using PBKDF2.
-
#encrypt(header_data) ⇒ Hash
Encrypt header data.
-
#initialize(password) ⇒ HeaderEncryptor
constructor
Initialize encryptor with password.
-
#verify_password(encrypted_data, salt, iv) ⇒ Boolean
Verify password against encrypted header.
Constructor Details
#initialize(password) ⇒ HeaderEncryptor
Initialize encryptor with password
26 27 28 29 30 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 26 def initialize(password) @password = password @salt = nil @iv = nil end |
Instance Attribute Details
#iv ⇒ Object (readonly)
256K iterations for strong key derivation
21 22 23 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 21 def iv @iv end |
#password ⇒ Object (readonly)
256K iterations for strong key derivation
21 22 23 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 21 def password @password end |
#salt ⇒ Object (readonly)
256K iterations for strong key derivation
21 22 23 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 21 def salt @salt end |
Instance Method Details
#calculate_crc(data) ⇒ Integer
Calculate CRC of header data
124 125 126 127 128 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 124 def calculate_crc(data) crc = Omnizip::Checksums::Crc32.new crc.update(data) crc.value end |
#decrypt(encrypted_data, salt, iv) ⇒ String
Decrypt header data
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 71 def decrypt(encrypted_data, salt, iv) # Derive decryption key from password key = derive_key(@password, salt) # Decrypt data decipher = OpenSSL::Cipher.new("AES-256-CBC") decipher.decrypt decipher.key = key decipher.iv = iv # Ensure padding validation is enabled (default, but explicit) decipher.padding = 1 begin decipher.update(encrypted_data) + decipher.final rescue OpenSSL::Cipher::CipherError => e raise "Failed to decrypt header: incorrect password or corrupted data (#{e.})" rescue StandardError => e raise "Failed to decrypt header: incorrect password or corrupted data (#{e.})" end end |
#derive_key(password, salt) ⇒ String
Derive encryption key from password using PBKDF2
97 98 99 100 101 102 103 104 105 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 97 def derive_key(password, salt) OpenSSL::PKCS5.pbkdf2_hmac( password, salt, PBKDF2_ITERATIONS, AES_KEY_SIZE, OpenSSL::Digest.new("SHA256"), ) end |
#encrypt(header_data) ⇒ Hash
Encrypt header data
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 40 def encrypt(header_data) # Generate random salt and IV @salt = OpenSSL::Random.random_bytes(SALT_SIZE) @iv = OpenSSL::Random.random_bytes(AES_IV_SIZE) # Derive encryption key from password key = derive_key(@password, @salt) # Encrypt data cipher = OpenSSL::Cipher.new("AES-256-CBC") cipher.encrypt cipher.key = key cipher.iv = @iv encrypted = cipher.update(header_data) + cipher.final { data: encrypted, salt: @salt, iv: @iv, size: header_data.bytesize, } end |
#verify_password(encrypted_data, salt, iv) ⇒ Boolean
Verify password against encrypted header
113 114 115 116 117 118 |
# File 'lib/omnizip/formats/seven_zip/header_encryptor.rb', line 113 def verify_password(encrypted_data, salt, iv) decrypt(encrypted_data, salt, iv) true rescue StandardError false end |