From 3cd7247d35a7fd2f721834f825911e81ce2af9ce Mon Sep 17 00:00:00 2001 From: Seimizu Joukan Date: Mon, 1 Dec 2025 23:19:07 +0900 Subject: [PATCH 1/2] Add kiro documents. --- .kiro/specs/file-encryption/design.md | 550 ++++++++++++++++++++ .kiro/specs/file-encryption/requirements.md | 115 ++++ .kiro/specs/file-encryption/tasks.md | 248 +++++++++ .kiro/steering/product.md | 31 ++ .kiro/steering/structure.md | 144 +++++ .kiro/steering/tech.md | 106 ++++ 6 files changed, 1194 insertions(+) create mode 100644 .kiro/specs/file-encryption/design.md create mode 100644 .kiro/specs/file-encryption/requirements.md create mode 100644 .kiro/specs/file-encryption/tasks.md create mode 100644 .kiro/steering/product.md create mode 100644 .kiro/steering/structure.md create mode 100644 .kiro/steering/tech.md diff --git a/.kiro/specs/file-encryption/design.md b/.kiro/specs/file-encryption/design.md new file mode 100644 index 0000000..02aa143 --- /dev/null +++ b/.kiro/specs/file-encryption/design.md @@ -0,0 +1,550 @@ +# Design Document: File Encryption Feature + +## Overview + +This design document describes the implementation of encryption capabilities for the JCZ compression utility. The feature adds support for encrypting compressed files using either password-based encryption (AES-256-GCM with Argon2id key derivation) or RSA public-key cryptography. The design integrates seamlessly with the existing compression/decompression workflow while maintaining the modular architecture of the JCZ system. + +The encryption layer operates on already-compressed data, wrapping it in an encrypted container with metadata. This approach allows encryption to work uniformly across all compression formats without modifying individual compressor implementations. + +## Architecture + +### High-Level Design + +The encryption feature follows a layered architecture: + +1. **CLI Layer**: Extended command-line arguments for encryption options +2. **Encryption Module**: Core encryption/decryption logic with support for multiple methods +3. **Integration Layer**: Hooks into existing compress/decompress operations +4. **Cryptography Layer**: Low-level cryptographic primitives using the `ring` and `rsa` crates + +### Data Flow + +**Compression with Encryption:** +``` +Input File → Compress → Encrypted Container → Output File + ↓ + [Encryption Metadata] +``` + +**Decompression with Decryption:** +``` +Encrypted File → Read Metadata → Decrypt → Decompress → Output File +``` + +### Module Structure + +``` +src/ +├── crypto/ +│ ├── mod.rs # Public API and types +│ ├── password.rs # Password-based encryption +│ ├── rsa.rs # RSA encryption +│ ├── container.rs # Encrypted container format +│ └── keys.rs # Key management utilities +├── core/ +│ ├── config.rs # Extended with encryption config +│ ├── error.rs # Extended with crypto errors +│ └── types.rs # Extended with encryption types +└── operations/ + ├── encrypt.rs # Encryption operations + └── decrypt.rs # Decryption operations +``` + +## Components and Interfaces + +### 1. Encryption Configuration + +```rust +/// Encryption method selection +pub enum EncryptionMethod { + Password, + Rsa { private_key_path: PathBuf }, +} + +/// Decryption method selection +pub enum DecryptionMethod { + Password, + Rsa { public_key_path: PathBuf }, +} + +/// Extended compression configuration with encryption +pub struct CompressionConfig { + // ... existing fields ... + pub encryption: Option, +} + +/// Extended decompression configuration +pub struct DecompressionConfig { + // ... existing fields ... + pub decryption: Option, +} +``` + +### 2. Encrypted Container Format + +The encrypted file format consists of: + +``` +[Magic Bytes: 4 bytes] "JCZE" +[Version: 1 byte] +[Encryption Type: 1 byte] (0x01 = Password, 0x02 = RSA) +[Metadata Length: 4 bytes] +[Metadata: variable] +[Encrypted Data: variable] +``` + +**Password Encryption Metadata:** +``` +[Salt: 32 bytes] +[Nonce: 12 bytes] +[Argon2 Parameters: variable] +``` + +**RSA Encryption Metadata:** +``` +[Encrypted Symmetric Key Length: 4 bytes] +[Encrypted Symmetric Key: variable] +[Nonce: 12 bytes] +``` + +### 3. Cryptography Interfaces + +```rust +/// Password-based encryption +pub trait PasswordEncryption { + fn encrypt(&self, data: &[u8], password: &str) -> Result, CryptoError>; + fn decrypt(&self, data: &[u8], password: &str) -> Result, CryptoError>; +} + +/// RSA encryption +pub trait RsaEncryption { + fn encrypt_with_private_key( + &self, + data: &[u8], + private_key: &RsaPrivateKey, + ) -> Result, CryptoError>; + + fn decrypt_with_public_key( + &self, + data: &[u8], + public_key: &RsaPublicKey, + ) -> Result, CryptoError>; +} + +/// Container operations +pub trait EncryptedContainer { + fn write(&self, output: &Path) -> Result<(), CryptoError>; + fn read(input: &Path) -> Result; + fn get_encryption_type(&self) -> EncryptionType; +} +``` + +### 4. CLI Extensions + +```rust +#[derive(Parser, Debug)] +pub struct CliArgs { + // ... existing fields ... + + /// Enable password-based encryption + #[arg(long = "encrypt-password", short = 'e')] + pub encrypt_password: bool, + + /// RSA private key file for encryption + #[arg(long = "encrypt-rsa")] + pub encrypt_rsa: Option, + + /// RSA public key file for decryption + #[arg(long = "decrypt-rsa")] + pub decrypt_rsa: Option, +} +``` + +## Data Models + +### EncryptedContainer + +```rust +pub struct EncryptedContainer { + pub version: u8, + pub encryption_type: EncryptionType, + pub metadata: EncryptionMetadata, + pub encrypted_data: Vec, +} + +pub enum EncryptionType { + Password, + Rsa, +} + +pub enum EncryptionMetadata { + Password { + salt: [u8; 32], + nonce: [u8; 12], + argon2_params: Argon2Params, + }, + Rsa { + encrypted_key: Vec, + nonce: [u8; 12], + }, +} + +pub struct Argon2Params { + pub memory_cost: u32, + pub time_cost: u32, + pub parallelism: u32, +} +``` + +### Error Types + +```rust +pub enum CryptoError { + InvalidPassword, + InvalidKey, + KeyDerivationFailed, + EncryptionFailed, + DecryptionFailed, + AuthenticationFailed, + InvalidContainer, + UnsupportedVersion(u8), + IoError(io::Error), + RsaError(String), +} +``` + +## Correctness Properties + +*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* + + +### Property Reflection + +After analyzing all acceptance criteria, several properties can be consolidated: + +**Consolidations:** +- Properties 1.3, 3.4, and 7.3 all relate to AES-256-GCM usage - can be verified through round-trip testing +- Properties 2.4, 4.4, and 4.5 all relate to RSA round-trip - can be combined into one comprehensive property +- Properties 1.4 and 2.5 both test metadata storage - can be unified +- Properties 3.3 and 1.2 both test key derivation - can be combined +- Properties 4.1 and 2.1 both test file validation - can be unified +- Properties 4.2 and 2.2 both test PEM parsing - can be unified +- Properties 5.1 and 5.2 describe the integration workflow - can be tested as one property + +**Core Properties to Implement:** +1. Password encryption round-trip (covers 1.2, 1.3, 1.4, 3.3, 3.4) +2. RSA encryption round-trip (covers 2.3, 2.4, 2.5, 4.3, 4.4, 4.5) +3. Encryption metadata completeness (covers 1.4, 2.5, 7.4) +4. Key file validation (covers 2.1, 4.1) +5. PEM key parsing (covers 2.2, 4.2) +6. Wrong password authentication failure (3.5) +7. Compression options preservation (5.3) +8. Independent file encryption (5.5) +9. Random value uniqueness (7.2) +10. RSA key size and padding validation (7.5) +11. Non-encrypted file handling (8.5) + +### Correctness Properties + +**Property 1: Password encryption round-trip** + +*For any* compressed file and any non-empty password, encrypting the file with that password and then decrypting with the same password should produce data that decompresses to the original content. + +**Validates: Requirements 1.2, 1.3, 1.4, 3.3, 3.4** + +--- + +**Property 2: RSA encryption round-trip** + +*For any* compressed file and any valid RSA key pair (private key for encryption, public key for decryption), encrypting the file with the private key and then decrypting with the corresponding public key should produce data that decompresses to the original content. + +**Validates: Requirements 2.3, 2.4, 2.5, 4.3, 4.4, 4.5** + +--- + +**Property 3: Encryption metadata completeness** + +*For any* encrypted file (password or RSA), the stored metadata should contain all parameters necessary for decryption (salt, nonce, Argon2 parameters for password; encrypted key and nonce for RSA) and should not contain the actual encryption key or password. + +**Validates: Requirements 1.4, 2.5, 7.4** + +--- + +**Property 4: Key file validation** + +*For any* file path provided as a key file, if the file does not exist or is not readable, the system should reject the operation with an appropriate error before attempting any cryptographic operations. + +**Validates: Requirements 2.1, 4.1** + +--- + +**Property 5: PEM key parsing** + +*For any* valid PEM-formatted RSA key file (private or public), the system should successfully parse the key and be able to use it for cryptographic operations. + +**Validates: Requirements 2.2, 4.2** + +--- + +**Property 6: Wrong password authentication failure** + +*For any* password-encrypted file, attempting to decrypt with an incorrect password should fail authentication during the AES-GCM decryption process and return a clear error message. + +**Validates: Requirements 3.5** + +--- + +**Property 7: Compression options preservation** + +*For any* compression operation with encryption enabled and any combination of compression options (level, timestamp, move-to directory), the resulting file should reflect all specified compression options as if encryption were not enabled. + +**Validates: Requirements 5.3** + +--- + +**Property 8: Independent file encryption** + +*For any* set of multiple files being compressed and encrypted, each file should be encrypted with an independent symmetric key and nonce, such that compromising one file's encryption does not affect others. + +**Validates: Requirements 5.5** + +--- + +**Property 9: Random value uniqueness** + +*For any* sequence of encryption operations, generated random values (nonces, symmetric keys, salts) should be unique across operations with overwhelming probability. + +**Validates: Requirements 7.2** + +--- + +**Property 10: RSA key size and padding validation** + +*For any* RSA key provided for encryption or decryption, the system should verify the key size is at least 2048 bits and should use OAEP padding for all RSA operations. + +**Validates: Requirements 7.5** + +--- + +**Property 11: Non-encrypted file handling** + +*For any* non-encrypted compressed file, providing encryption/decryption options during decompression should not cause errors and should proceed with normal decompression. + +**Validates: Requirements 8.5** + +--- + +**Property 12: Encrypted file detection** + +*For any* file processed by the system, the system should correctly identify whether it is encrypted by reading the magic bytes and metadata header. + +**Validates: Requirements 3.1** + +--- + +**Property 13: File extension indication** + +*For any* encrypted compressed file, the output filename should include an extension that indicates encryption (e.g., .jcze or .enc) in addition to the compression format extension. + +**Validates: Requirements 5.4** + +--- + +**Property 14: Error message specificity** + +*For any* encryption or decryption error condition (wrong password, invalid key, corrupted data, etc.), the system should provide an error message that specifically identifies the type of failure. + +**Validates: Requirements 6.5** + +## Error Handling + +### Error Categories + +1. **Input Validation Errors** + - Empty password + - Missing key files + - Invalid key file format + - Conflicting encryption options + +2. **Cryptographic Errors** + - Key derivation failure + - Encryption/decryption failure + - Authentication failure (wrong password/key) + - Invalid key size + +3. **Container Format Errors** + - Invalid magic bytes + - Unsupported version + - Corrupted metadata + - Truncated encrypted data + +4. **I/O Errors** + - File read/write failures + - Permission errors + - Disk space issues + +### Error Handling Strategy + +- All cryptographic operations return `Result` +- Errors are propagated up to the CLI layer for user-friendly display +- Sensitive information (passwords, keys) is never included in error messages +- Failed operations clean up temporary files automatically +- Authentication failures are distinguished from other decryption errors + +## Testing Strategy + +### Unit Testing + +Unit tests will cover: + +- Container format serialization/deserialization +- Key derivation with known test vectors +- Metadata parsing and validation +- Error condition handling (empty passwords, invalid keys) +- CLI argument validation +- File extension generation + +### Property-Based Testing + +Property-based testing will be implemented using the `proptest` crate for Rust. Each correctness property will be tested with a minimum of 100 randomly generated test cases. + +**Property Test Configuration:** +```rust +proptest! { + #![proptest_config(ProptestConfig::with_cases(100))] + // ... test cases +} +``` + +**Test Generators:** + +1. **Random Data Generator**: Generates arbitrary byte sequences for file content +2. **Password Generator**: Generates valid passwords of varying lengths and character sets +3. **RSA Key Pair Generator**: Generates valid RSA key pairs with different key sizes +4. **Compression Config Generator**: Generates random compression configurations +5. **File Path Generator**: Generates valid and invalid file paths + +**Property Test Tags:** + +Each property-based test will be tagged with a comment referencing the design document: + +```rust +// Feature: file-encryption, Property 1: Password encryption round-trip +#[test] +fn prop_password_round_trip() { ... } +``` + +### Integration Testing + +Integration tests will verify: + +- End-to-end encryption/decryption workflows +- Integration with all compression formats (gzip, bzip2, xz, zip, tar, compound) +- CLI argument parsing and execution +- File system operations (move-to directory, timestamps) +- Parallel processing of multiple encrypted files + +### Security Testing + +Security-focused tests will verify: + +- Argon2id parameters meet security recommendations +- Random number generation uses cryptographically secure sources +- Sensitive data is properly zeroized after use +- Timing attacks are mitigated where possible +- Key sizes meet minimum security requirements + +## Implementation Notes + +### Dependencies + +New dependencies to add to `Cargo.toml`: + +```toml +# Cryptography +ring = "0.17" # AES-GCM, CSPRNG +rsa = "0.9" # RSA operations +argon2 = "0.5" # Password hashing +pem = "3.0" # PEM file parsing +zeroize = "1.7" # Secure memory clearing + +# Property testing +[dev-dependencies] +proptest = "1.4" # Property-based testing +``` + +### Security Considerations + +1. **Password Handling** + - Passwords are read from stdin without echo + - Passwords are zeroized immediately after key derivation + - No password caching or storage + +2. **Key Material** + - Symmetric keys are generated using `ring::rand::SystemRandom` + - Keys are zeroized after use using the `zeroize` crate + - Private keys are never written to disk by the application + +3. **Argon2id Parameters** + - Memory cost: 64 MB (65536 KB) + - Time cost: 3 iterations + - Parallelism: 4 threads + - These parameters provide strong resistance to brute-force attacks + +4. **RSA Configuration** + - Minimum key size: 2048 bits (recommended: 4096 bits) + - Padding: OAEP with SHA-256 + - Only the symmetric key is encrypted with RSA, not the entire file + +### Performance Considerations + +1. **Parallel Processing** + - Encryption/decryption operations can be parallelized across multiple files + - Individual file encryption is sequential (AES-GCM is not easily parallelizable) + +2. **Memory Usage** + - Files are processed in streaming mode where possible + - Argon2id memory cost is configurable but defaults to 64 MB + - RSA operations are performed only on small symmetric keys (32 bytes) + +3. **Overhead** + - Encryption adds minimal overhead to file size (< 1 KB metadata) + - Performance impact is primarily from AES-GCM encryption (typically > 1 GB/s on modern CPUs) + +### File Extension Convention + +Encrypted files will use the following naming convention: + +- Password-encrypted: `filename.ext.jcze` (e.g., `data.tar.gz.jcze`) +- RSA-encrypted: `filename.ext.jcze` (same extension, type stored in metadata) + +The `.jcze` extension stands for "JCZ Encrypted" and clearly indicates the file requires decryption. + +### Backward Compatibility + +- Existing compressed files without encryption remain fully compatible +- The system automatically detects encrypted vs. non-encrypted files +- No changes to existing compression/decompression workflows +- Encryption is opt-in via CLI flags + +## Future Enhancements + +Potential future improvements: + +1. **Additional Encryption Methods** + - ChaCha20-Poly1305 as an alternative to AES-GCM + - Support for hardware security modules (HSM) + +2. **Key Management** + - SSH key integration + - Key agent support + - Multiple recipient support (encrypt for multiple public keys) + +3. **Compression Integration** + - Encrypt-then-compress vs. compress-then-encrypt options + - Streaming encryption for very large files + +4. **Advanced Features** + - Digital signatures for authenticity verification + - Key rotation capabilities + - Encrypted archive inspection without decryption diff --git a/.kiro/specs/file-encryption/requirements.md b/.kiro/specs/file-encryption/requirements.md new file mode 100644 index 0000000..a95e017 --- /dev/null +++ b/.kiro/specs/file-encryption/requirements.md @@ -0,0 +1,115 @@ +# Requirements Document + +## Introduction + +This document specifies the requirements for adding encryption capabilities to the JCZ compression utility. The encryption feature will allow users to secure compressed files using either password-based encryption or RSA public-key cryptography. Users will be able to encrypt files during compression and decrypt them during decompression, providing an additional layer of security for sensitive data. + +## Glossary + +- **JCZ System**: The Just Compress Zip compression utility application +- **Encrypted Archive**: A compressed file that has been encrypted using either password-based or RSA encryption +- **Password-Based Encryption**: Symmetric encryption using a user-provided password +- **RSA Encryption**: Asymmetric encryption using RSA public/private key pairs +- **Private Key**: The secret key used for RSA encryption of the symmetric key +- **Public Key**: The key used for RSA decryption of the symmetric key +- **Symmetric Key**: The actual encryption key used to encrypt/decrypt file data +- **Key Derivation**: The process of generating a cryptographic key from a password +- **Encryption Metadata**: Information stored with the encrypted file indicating encryption method and parameters + +## Requirements + +### Requirement 1 + +**User Story:** As a user, I want to encrypt compressed files with a password, so that I can protect sensitive data from unauthorized access. + +#### Acceptance Criteria + +1. WHEN a user specifies password encryption during compression THEN the JCZ System SHALL prompt for a password securely +2. WHEN a user provides a password THEN the JCZ System SHALL derive a cryptographic key using a secure key derivation function +3. WHEN encrypting with a password THEN the JCZ System SHALL encrypt the compressed data using AES-256-GCM encryption +4. WHEN password encryption completes THEN the JCZ System SHALL store encryption metadata with the encrypted archive +5. WHEN a user provides an empty password THEN the JCZ System SHALL reject the operation and display an error message + +### Requirement 2 + +**User Story:** As a user, I want to encrypt compressed files with an RSA private key, so that only holders of the corresponding public key can decrypt the data. + +#### Acceptance Criteria + +1. WHEN a user specifies RSA encryption with a private key file path THEN the JCZ System SHALL validate the private key file exists and is readable +2. WHEN the private key file is valid THEN the JCZ System SHALL parse the RSA private key in PEM format +3. WHEN encrypting with RSA THEN the JCZ System SHALL generate a random symmetric key for AES-256-GCM encryption +4. WHEN the symmetric key is generated THEN the JCZ System SHALL encrypt the symmetric key using the RSA private key +5. WHEN RSA encryption completes THEN the JCZ System SHALL store both the encrypted symmetric key and encryption metadata with the encrypted archive + +### Requirement 3 + +**User Story:** As a user, I want to decrypt password-encrypted files, so that I can access my protected compressed data. + +#### Acceptance Criteria + +1. WHEN a user attempts to decompress an encrypted archive THEN the JCZ System SHALL detect the encryption metadata +2. WHEN password encryption is detected THEN the JCZ System SHALL prompt the user for the decryption password +3. WHEN the user provides a password THEN the JCZ System SHALL derive the decryption key using the stored key derivation parameters +4. WHEN the decryption key is derived THEN the JCZ System SHALL decrypt the archive data using AES-256-GCM +5. WHEN the password is incorrect THEN the JCZ System SHALL fail authentication and display a clear error message + +### Requirement 4 + +**User Story:** As a user, I want to decrypt RSA-encrypted files with a public key, so that I can access data encrypted for me. + +#### Acceptance Criteria + +1. WHEN a user specifies RSA decryption with a public key file path THEN the JCZ System SHALL validate the public key file exists and is readable +2. WHEN the public key file is valid THEN the JCZ System SHALL parse the RSA public key in PEM format +3. WHEN decrypting with RSA THEN the JCZ System SHALL extract the encrypted symmetric key from the archive metadata +4. WHEN the encrypted symmetric key is extracted THEN the JCZ System SHALL decrypt it using the RSA public key +5. WHEN the symmetric key is decrypted THEN the JCZ System SHALL decrypt the archive data using AES-256-GCM with the recovered symmetric key + +### Requirement 5 + +**User Story:** As a user, I want the encryption process to be transparent and integrated with existing compression workflows, so that I can easily secure my files without changing my workflow. + +#### Acceptance Criteria + +1. WHEN a user adds encryption options to a compression command THEN the JCZ System SHALL perform compression followed by encryption in a single operation +2. WHEN a user decompresses an encrypted file THEN the JCZ System SHALL perform decryption followed by decompression automatically +3. WHEN encryption is enabled THEN the JCZ System SHALL preserve all existing compression options and behaviors +4. WHEN an encrypted archive is created THEN the JCZ System SHALL use a file extension that indicates both compression and encryption +5. WHEN processing multiple files with encryption THEN the JCZ System SHALL encrypt each compressed file independently + +### Requirement 6 + +**User Story:** As a user, I want clear feedback about encryption operations, so that I understand what security measures are being applied to my files. + +#### Acceptance Criteria + +1. WHEN encryption begins THEN the JCZ System SHALL log the encryption method being used +2. WHEN encryption completes successfully THEN the JCZ System SHALL display a confirmation message with the output file path +3. WHEN decryption begins THEN the JCZ System SHALL log the detected encryption method +4. WHEN decryption completes successfully THEN the JCZ System SHALL display a confirmation message +5. WHEN an encryption or decryption error occurs THEN the JCZ System SHALL display a specific error message indicating the failure reason + +### Requirement 7 + +**User Story:** As a developer, I want encryption to follow security best practices, so that the implementation is cryptographically sound and resistant to common attacks. + +#### Acceptance Criteria + +1. WHEN deriving keys from passwords THEN the JCZ System SHALL use Argon2id with appropriate parameters for key derivation +2. WHEN generating random values THEN the JCZ System SHALL use a cryptographically secure random number generator +3. WHEN encrypting data THEN the JCZ System SHALL use authenticated encryption with AES-256-GCM +4. WHEN storing encryption metadata THEN the JCZ System SHALL include all necessary parameters for decryption without exposing sensitive key material +5. WHEN handling RSA operations THEN the JCZ System SHALL use RSA with OAEP padding and a minimum key size of 2048 bits + +### Requirement 8 + +**User Story:** As a user, I want to specify encryption options via command-line arguments, so that I can automate encryption in scripts and workflows. + +#### Acceptance Criteria + +1. WHEN the user provides the password encryption flag THEN the JCZ System SHALL enable password-based encryption mode +2. WHEN the user provides an RSA private key path argument THEN the JCZ System SHALL enable RSA encryption mode +3. WHEN the user provides an RSA public key path argument during decompression THEN the JCZ System SHALL enable RSA decryption mode +4. WHEN both password and RSA options are specified THEN the JCZ System SHALL reject the operation and display an error message +5. WHEN encryption options are provided in decompression mode without an encrypted input THEN the JCZ System SHALL ignore the encryption options and proceed with normal decompression diff --git a/.kiro/specs/file-encryption/tasks.md b/.kiro/specs/file-encryption/tasks.md new file mode 100644 index 0000000..5ad39e6 --- /dev/null +++ b/.kiro/specs/file-encryption/tasks.md @@ -0,0 +1,248 @@ +# Implementation Plan + +- [x] 1. Set up cryptography dependencies and core types + - Add required dependencies to Cargo.toml (ring, rsa, argon2, pem, zeroize, proptest) + - Create crypto module structure (mod.rs, password.rs, rsa.rs, container.rs, keys.rs) + - Define core encryption types (EncryptionMethod, DecryptionMethod, EncryptionType, EncryptionMetadata) + - Define CryptoError enum with all error variants + - _Requirements: 7.1, 7.3, 7.5_ + +- [ ] 2. Implement encrypted container format + - [x] 2.1 Create EncryptedContainer struct and serialization logic + - Implement container structure with magic bytes, version, encryption type, metadata, and encrypted data + - Write serialization method to convert container to bytes + - Write deserialization method to parse bytes into container + - _Requirements: 1.4, 2.5_ + + - [x] 2.2 Write property test for container round-trip + - **Property 3: Encryption metadata completeness** + - **Validates: Requirements 1.4, 2.5, 7.4** + + - [x] 2.3 Implement metadata structures for password and RSA encryption + - Create PasswordMetadata with salt, nonce, and Argon2 parameters + - Create RsaMetadata with encrypted key and nonce + - Implement serialization/deserialization for both metadata types + - _Requirements: 1.4, 2.5, 7.4_ + + - [x] 2.4 Write unit tests for metadata serialization + - Test password metadata serialization/deserialization + - Test RSA metadata serialization/deserialization + - Test metadata size calculations + - _Requirements: 1.4, 2.5_ + +- [ ] 3. Implement password-based encryption + - [x] 3.1 Implement Argon2id key derivation + - Create key derivation function using Argon2id with secure parameters + - Implement salt generation using cryptographically secure RNG + - Add password validation (reject empty passwords) + - _Requirements: 1.2, 1.5, 7.1, 7.2_ + + - [x] 3.2 Implement AES-256-GCM encryption for password mode + - Create encryption function that takes data and derived key + - Generate random nonce for each encryption + - Implement AES-256-GCM encryption with authentication + - _Requirements: 1.3, 7.3_ + + - [x] 3.3 Implement AES-256-GCM decryption for password mode + - Create decryption function that takes encrypted data and derived key + - Extract nonce from metadata + - Implement AES-256-GCM decryption with authentication verification + - _Requirements: 3.4, 3.5_ + + - [x] 3.4 Write property test for password encryption round-trip + - **Property 1: Password encryption round-trip** + - **Validates: Requirements 1.2, 1.3, 1.4, 3.3, 3.4** + + - [x] 3.5 Write property test for wrong password authentication failure + - **Property 6: Wrong password authentication failure** + - **Validates: Requirements 3.5** + + - [x] 3.6 Write property test for random value uniqueness + - **Property 9: Random value uniqueness** + - **Validates: Requirements 7.2** + +- [ ] 4. Implement RSA encryption + - [x] 4.1 Implement RSA key file parsing + - Create function to read and parse PEM-formatted private keys + - Create function to read and parse PEM-formatted public keys + - Add key file validation (existence, readability) + - _Requirements: 2.1, 2.2, 4.1, 4.2_ + + - [x] 4.2 Write property test for key file validation + - **Property 4: Key file validation** + - **Validates: Requirements 2.1, 4.1** + + - [x] 4.3 Write property test for PEM key parsing + - **Property 5: PEM key parsing** + - **Validates: Requirements 2.2, 4.2** + + - [x] 4.4 Implement RSA key size and padding validation + - Validate RSA key size is at least 2048 bits + - Configure RSA operations to use OAEP padding with SHA-256 + - _Requirements: 7.5_ + + - [x] 4.5 Write property test for RSA key size and padding validation + - **Property 10: RSA key size and padding validation** + - **Validates: Requirements 7.5** + + - [x] 4.6 Implement symmetric key generation and RSA encryption + - Generate random 256-bit symmetric key for AES-256-GCM + - Encrypt symmetric key using RSA private key with OAEP padding + - Encrypt file data using AES-256-GCM with generated symmetric key + - _Requirements: 2.3, 2.4, 2.5_ + + - [x] 4.7 Implement RSA decryption and symmetric key recovery + - Extract encrypted symmetric key from metadata + - Decrypt symmetric key using RSA public key + - Decrypt file data using recovered symmetric key with AES-256-GCM + - _Requirements: 4.3, 4.4, 4.5_ + + - [x] 4.8 Write property test for RSA encryption round-trip + - **Property 2: RSA encryption round-trip** + - **Validates: Requirements 2.3, 2.4, 2.5, 4.3, 4.4, 4.5** + +- [ ] 5. Extend CLI arguments for encryption options + - [x] 5.1 Add encryption-related CLI arguments + - Add --encrypt-password flag for password-based encryption + - Add --encrypt-rsa option for RSA private key path + - Add --decrypt-rsa option for RSA public key path + - Update CliArgs struct and validation + - _Requirements: 8.1, 8.2, 8.3_ + + - [x] 5.2 Implement CLI argument validation + - Validate that password and RSA options are mutually exclusive + - Validate key file paths when provided + - Add appropriate error messages for invalid combinations + - _Requirements: 8.4_ + + - [x] 5.3 Write unit tests for CLI argument validation + - Test mutual exclusivity of password and RSA options + - Test key file path validation + - Test error messages for invalid combinations + - _Requirements: 8.4_ + +- [ ] 6. Extend configuration types for encryption + - [x] 6.1 Extend CompressionConfig with encryption options + - Add encryption field to CompressionConfig + - Create EncryptionMethod enum (Password, Rsa) + - Update config builder methods + - _Requirements: 5.1, 5.3_ + + - [x] 6.2 Create DecompressionConfig with decryption options + - Create DecompressionConfig struct + - Add decryption field with DecryptionMethod enum + - Implement config builder methods + - _Requirements: 3.1, 4.1_ + + - [x] 6.3 Write property test for compression options preservation + - **Property 7: Compression options preservation** + - **Validates: Requirements 5.3** + +- [ ] 7. Implement encryption operations + - [x] 7.1 Create encrypt_file function + - Implement function that takes compressed file and encryption config + - Route to password or RSA encryption based on config + - Generate output filename with .jcze extension + - Write encrypted container to output file + - _Requirements: 5.1, 5.4_ + + - [x] 7.2 Write property test for file extension indication + - **Property 13: File extension indication** + - **Validates: Requirements 5.4** + + - [x] 7.3 Create encrypt_files function for batch processing + - Implement parallel encryption of multiple files using rayon + - Ensure each file gets independent encryption keys + - Handle errors for individual files without stopping batch + - _Requirements: 5.5_ + + - [x] 7.4 Write property test for independent file encryption + - **Property 8: Independent file encryption** + - **Validates: Requirements 5.5** + + - [x] 7.5 Add encryption logging and user feedback + - Log encryption method at start of operation + - Display confirmation message with output path on success + - Display specific error messages on failure + - _Requirements: 6.1, 6.2, 6.5_ + + - [x] 7.6 Write property test for error message specificity + - **Property 14: Error message specificity** + - **Validates: Requirements 6.5** + +- [ ] 8. Implement decryption operations + - [x] 8.1 Create decrypt_file function + - Implement function to read and parse encrypted container + - Detect encryption type from metadata + - Route to password or RSA decryption based on type + - Write decrypted data to output file + - _Requirements: 3.1, 5.2_ + + - [x] 8.2 Write property test for encrypted file detection + - **Property 12: Encrypted file detection** + - **Validates: Requirements 3.1** + + - [x] 8.3 Implement password prompting for decryption + - Create secure password prompt function (no echo) + - Prompt user when password-encrypted file is detected + - Handle password input errors gracefully + - _Requirements: 3.2_ + + - [x] 8.4 Create decrypt_files function for batch processing + - Implement parallel decryption of multiple files + - Handle mixed encrypted/non-encrypted files + - Prompt for passwords as needed + - _Requirements: 5.2, 8.5_ + + - [x] 8.5 Write property test for non-encrypted file handling + - **Property 11: Non-encrypted file handling** + - **Validates: Requirements 8.5** + + - [x] 8.6 Add decryption logging and user feedback + - Log detected encryption method at start + - Display confirmation message on successful decryption + - Display specific error messages on failure + - _Requirements: 6.3, 6.4, 6.5_ + +- [ ] 9. Integrate encryption with compression workflow + - [x] 9.1 Modify compress operations to support encryption + - Update compress_file to optionally encrypt after compression + - Update compress_files to handle encryption in parallel + - Ensure compression options (level, timestamp, move-to) work with encryption + - _Requirements: 5.1, 5.3_ + + - [x] 9.2 Modify decompress operations to support decryption + - Update decompress_file to detect and decrypt encrypted files + - Update decompress_files to handle decryption automatically + - Ensure decompression works seamlessly after decryption + - _Requirements: 5.2_ + + - [x] 9.3 Update CLI command execution + - Wire encryption options from CLI args to compression config + - Wire decryption options from CLI args to decompression config + - Update command handlers to use new encryption/decryption functions + - _Requirements: 8.1, 8.2, 8.3_ + +- [x] 10. Write integration tests + - Test end-to-end password encryption/decryption with all compression formats + - Test end-to-end RSA encryption/decryption with all compression formats + - Test encryption with timestamps and move-to directory options + - Test batch encryption/decryption of multiple files + - Test error handling for various failure scenarios + - _Requirements: All_ + +- [ ] 11. Implement secure memory handling + - [x] 11.1 Add zeroization for sensitive data + - Zeroize passwords after key derivation + - Zeroize symmetric keys after use + - Zeroize derived keys after encryption/decryption + - _Requirements: 7.1, 7.2_ + + - [x] 11.2 Write unit tests for memory zeroization + - Verify passwords are zeroized after use + - Verify keys are zeroized after use + - Test zeroization on error paths + - _Requirements: 7.1, 7.2_ + +- [x] 12. Final checkpoint - Ensure all tests pass + - Ensure all tests pass, ask the user if questions arise. diff --git a/.kiro/steering/product.md b/.kiro/steering/product.md new file mode 100644 index 0000000..6f80500 --- /dev/null +++ b/.kiro/steering/product.md @@ -0,0 +1,31 @@ +# Product Overview + +JCZ (Just Compress Zip) is a unified command-line compression utility written in Rust that provides a consistent interface for multiple compression formats. + +## Core Purpose + +Simplify file and directory compression/decompression by providing a single command that wraps system compression tools (gzip, bzip2, xz, zip, tar) with a consistent, user-friendly interface. + +## Key Features + +- **Multi-format support**: GZIP, BZIP2, XZ, ZIP, TAR, and compound formats (TGZ, TBZ2, TXZ) +- **File encryption**: Password-based (AES-256-GCM) and RSA public-key encryption +- **Parallel processing**: Concurrent compression/decompression using Rayon +- **Timestamp options**: Add date/time stamps to output filenames +- **File collection**: Combine multiple files into single archives +- **Automatic format detection**: Smart decompression of compound formats +- **Original file preservation**: Always keeps original files intact + +## Target Users + +- System administrators needing reliable, scriptable compression tools +- Developers requiring automation-friendly utilities +- Power users wanting advanced features like batch processing +- Regular users seeking simple compression operations + +## Design Philosophy + +- **Consistent interface**: Single command for all compression formats +- **Safety first**: Preserve original files, validate inputs +- **Performance**: Leverage Rust's zero-cost abstractions and parallel processing +- **User-friendly**: Clear error messages, sensible defaults diff --git a/.kiro/steering/structure.md b/.kiro/steering/structure.md new file mode 100644 index 0000000..f63c523 --- /dev/null +++ b/.kiro/steering/structure.md @@ -0,0 +1,144 @@ +# Project Structure + +## Module Organization + +``` +src/ +├── main.rs # Entry point, CLI initialization +├── lib.rs # Library root, public API exports +├── cli/ # Command-line interface +│ ├── mod.rs # CLI module root +│ ├── args.rs # Argument parsing with clap +│ └── commands.rs # Command execution logic +├── core/ # Core abstractions and types +│ ├── mod.rs # Core module root +│ ├── compressor.rs # Compressor trait definitions +│ ├── config.rs # Configuration structures +│ ├── error.rs # Error types (JcError, JcResult) +│ └── types.rs # Common type definitions +├── compressors/ # Compression implementations +│ ├── mod.rs # Compressor module root +│ ├── gzip.rs # GZIP implementation +│ ├── bzip2.rs # BZIP2 implementation +│ ├── xz.rs # XZ implementation +│ ├── zip.rs # ZIP implementation +│ └── tar.rs # TAR implementation +├── crypto/ # Encryption/decryption +│ ├── mod.rs # Crypto module root +│ ├── container.rs # Encrypted container format +│ ├── keys.rs # Key management +│ ├── password.rs # Password-based encryption +│ └── rsa.rs # RSA public-key encryption +├── operations/ # High-level operations +│ ├── mod.rs # Operations module root +│ ├── compress.rs # Compression operations +│ ├── decompress.rs # Decompression operations +│ ├── encrypt.rs # Encryption operations +│ ├── decrypt.rs # Decryption operations +│ ├── collection.rs # Multi-file collection +│ └── compound.rs # Compound format handling +└── utils/ # Utility functions + ├── mod.rs # Utils module root + ├── fs.rs # File system utilities + ├── logger.rs # Logging initialization + ├── prompt.rs # User prompts + ├── timestamp.rs # Timestamp generation + └── validation.rs # Input validation +``` + +## Architecture Layers + +### 1. CLI Layer (`cli/`) +- Parses command-line arguments using clap +- Dispatches to appropriate operations +- Handles user interaction and output + +### 2. Operations Layer (`operations/`) +- High-level business logic +- Orchestrates compression/decompression workflows +- Handles batch processing with Rayon +- Manages temporary directories and cleanup + +### 3. Core Abstraction Layer (`core/`) +- **Compressor trait**: Common interface for all compressors +- **MultiFileCompressor trait**: Extended interface for archive formats +- **Error types**: Comprehensive error handling with JcError enum +- **Configuration**: Shared config structures (CompressionConfig, CollectionConfig) + +### 4. Implementation Layer (`compressors/`, `crypto/`) +- Concrete implementations of Compressor trait +- Each compressor in its own module +- Wraps system utilities via std::process::Command +- Crypto operations for encryption/decryption + +### 5. Utility Layer (`utils/`) +- Cross-cutting concerns +- File system operations +- Logging setup +- Validation helpers + +## Key Design Patterns + +### Trait-Based Polymorphism +All compressors implement the `Compressor` trait, enabling uniform handling: +```rust +pub trait Compressor: Send + Sync { + fn name(&self) -> &'static str; + fn extension(&self) -> &'static str; + fn compress(&self, input: &Path, config: &CompressionConfig) -> JcResult; + fn decompress(&self, input: &Path, config: &CompressionConfig) -> JcResult; + fn supports_levels(&self) -> bool; + fn validate_level(&self, level: u8) -> bool; + fn default_level(&self) -> u8; +} +``` + +### Error Handling +- Custom error type `JcError` with specific variants +- Type alias `JcResult = Result` +- All operations return `JcResult` for consistent error propagation +- Automatic conversion from `io::Error` via `From` trait + +### Configuration Pattern +- Immutable configuration structures +- Builder pattern with `with_*` methods for fluent API +- Separation: base config vs. specialized configs (CollectionConfig) + +### RAII for Resource Management +- Temporary directories cleaned up automatically via Drop +- File handles closed automatically +- Guard patterns for cleanup on error + +### Concurrent Processing +- Rayon for parallel file processing +- Thread-safe compressor implementations (Send + Sync) +- Independent file operations processed concurrently + +## Module Dependencies + +- `cli` → `operations` → `compressors` + `crypto` → `core` + `utils` +- `core` defines interfaces, `compressors` implements them +- `utils` is a leaf module used by all layers +- No circular dependencies + +## Testing Structure + +``` +tests/ +├── common/ # Shared test utilities +│ └── mod.rs +├── test_compression.rs # Compression tests +├── test_decompression.rs # Decompression tests +├── test_compound.rs # Compound format tests +├── test_errors.rs # Error handling tests +├── test_options.rs # CLI options tests +└── test_*.rs # Format-specific tests +``` + +## Documentation + +``` +docs/ +├── jcz_srs.md # Software Requirements Specification +└── jcz_sdd.md # Software Design Document +``` diff --git a/.kiro/steering/tech.md b/.kiro/steering/tech.md new file mode 100644 index 0000000..6a06206 --- /dev/null +++ b/.kiro/steering/tech.md @@ -0,0 +1,106 @@ +# Technology Stack + +## Language & Edition + +- **Rust 2021 edition** +- Minimum toolchain: stable Rust compiler + +## Build System + +**Cargo** - Standard Rust package manager and build tool + +### Common Commands + +```bash +# Build debug version +cargo build + +# Build optimized release version +cargo build --release + +# Run the application +cargo run -- [args] + +# Run tests +cargo test + +# Run specific test +cargo test test_name + +# Check code without building +cargo check + +# Format code +cargo fmt + +# Run linter +cargo clippy + +# Install locally +cargo build --release +sudo cp target/release/jcz /usr/local/bin/ +``` + +## Core Dependencies + +### CLI & Argument Parsing +- **clap** (v4.0) with derive features - Command-line argument parsing + +### Concurrency +- **rayon** (v1.7) - Data parallelism and work-stealing for concurrent file processing + +### Logging +- **log** (v0.4) - Logging facade +- **env_logger** (v0.10) - Logger implementation controlled by `JCDBG` environment variable + +### Date/Time +- **chrono** (v0.4) - Timestamp generation for filename suffixes + +### File System +- **tempfile** (v3.8) - Temporary directory management with automatic cleanup + +### Cryptography +- **ring** (v0.17) - AES-256-GCM encryption +- **rsa** (v0.9) - RSA public-key cryptography +- **argon2** (v0.5) - Password-based key derivation +- **pem** (v3.0) - PEM file parsing +- **sha2** (v0.10) - SHA-256 hashing +- **rand** (v0.8) - Cryptographically secure random number generation +- **zeroize** (v1.7) - Secure memory zeroing for sensitive data +- **rpassword** (v7.3) - Secure password input without echo + +### Testing +- **assert_cmd** (v2.0) - CLI testing utilities +- **predicates** (v3.0) - Assertion predicates for tests +- **proptest** (v1.4) - Property-based testing + +## External System Dependencies + +The application wraps these system utilities (must be in PATH): +- `gzip` - GZIP compression/decompression +- `bzip2` - BZIP2 compression/decompression +- `xz` - XZ compression/decompression +- `zip` - ZIP compression +- `unzip` - ZIP decompression +- `tar` - TAR archive creation/extraction +- `mv` - File moving +- `cp` - File copying +- `readlink` - Symbolic link resolution + +## Release Profile + +Optimized for performance: +```toml +[profile.release] +opt-level = 3 # Maximum optimization +lto = true # Link-time optimization +codegen-units = 1 # Single codegen unit for better optimization +``` + +## Environment Variables + +- `JCDBG` - Control logging verbosity + - `error` - Only errors + - `warn` - Warnings and errors + - `info` - Info, warnings, errors (default) + - `debug` - All messages including debug From b359b86d947d458c2f500e2c93a8eb6937847728 Mon Sep 17 00:00:00 2001 From: Seimizu Joukan Date: Mon, 1 Dec 2025 23:19:28 +0900 Subject: [PATCH 2/2] Update Cargo.lock for v0.2.3. --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 052aa7f..444b853 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,7 +481,7 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "jcz" -version = "0.2.2" +version = "0.2.3" dependencies = [ "argon2", "assert_cmd",