Skip to content

Commit

Permalink
Added a new and innovative Project AES File Encryption Tool
Browse files Browse the repository at this point in the history
  • Loading branch information
AswinPKumar01 committed Oct 5, 2024
1 parent 02ab593 commit a458115
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 0 deletions.
87 changes: 87 additions & 0 deletions A/AES-File-Encryption-Tool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# AES Encryption Tool

This tool provides a simple interface to encrypt and decrypt files using the AES (Advanced Encryption Standard) encryption algorithm. It uses the AES-CBC mode for encryption, ensuring that your data remains secure and private. A password-based key derivation function (PBKDF2 with HMAC-SHA256) is used to derive the encryption key from the provided password, adding another layer of security.

## Features

- **Encrypt Files**: Securely encrypt any file with a password.
- **Decrypt Files**: Decrypt previously encrypted files using the same password.
- **Automatic Padding**: Automatically handles file padding to ensure proper encryption even for files that are not a multiple of the AES block size.
- **Salt and IV Generation**: Generates a random salt and initialization vector (IV) for each encryption to enhance security.

## Installation

### Prerequisites:

1. Python 3.x
2. `cryptography` package

### To install the required package:

```bash
pip install cryptography
```

## Usage

### Command-line Arguments

- `mode`: Choose between `encrypt` or `decrypt` mode.
- `input_file`: The path to the file you want to encrypt or decrypt.
- `output_file` (optional): The desired path for the encrypted or decrypted output file. If not provided, the tool will generate a default name:
- For encryption: `input_file.enc`
- For decryption: If the input file ends with `.enc`, it will remove this extension, otherwise it appends `.dec`.

### Encrypting a File

```bash
python aes_tool.py encrypt <input_file> <output_file>
```

**Example:**

```bash
python aes_tool.py encrypt example.txt
```

This will prompt you for a password and create an encrypted file called `example.txt.enc`.

### Decrypting a File

```bash
python aes_tool.py decrypt <input_file> <output_file>
```

**Example:**

```bash
python aes_tool.py decrypt example.txt.enc
```

This will prompt you for the password and decrypt the file to `example.txt`.

### Important Notes:

- You must remember the password used for encryption. The same password is required for decryption.
- If you provide an incorrect password during decryption, the tool will notify you of the failure and delete any incomplete output files to prevent corruption.

## How It Works

1. **Encryption:**

- The tool generates a random 16-byte salt and initialization vector (IV).
- The salt is used with PBKDF2HMAC (HMAC-SHA256) to derive a cryptographic key from the password.
- AES encryption (in CBC mode) is applied to the input file data.
- The encrypted file contains the salt, IV, and the encrypted data.

2. **Decryption:**
- The tool reads the salt and IV from the encrypted file.
- It derives the cryptographic key using the same password-based key derivation function (PBKDF2HMAC).
- AES decryption is applied, and the original file content is recovered.

## Author

- **Name**: Aswin P Kumar
- **GitHub**: [AswinPKumar01](https://github.com/AswinPKumar01)

---
128 changes: 128 additions & 0 deletions A/AES-File-Encryption-Tool/aes_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import os
import sys
import argparse
import getpass
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, padding as sym_padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

def derive_key(password, salt, key_size):
# Derive a cryptographic key from the password
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=key_size // 8,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = kdf.derive(password.encode())
return key

def encrypt_file(input_file, output_file, password):
# Generate salt and IV
salt = os.urandom(16)
iv = os.urandom(16)

# Derive key
key = derive_key(password, salt, 256)

# Initialize cipher
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()

# Read input file and encrypt
with open(input_file, 'rb') as f_in, open(output_file, 'wb') as f_out:
# Write salt and IV to the output file
f_out.write(salt)
f_out.write(iv)

# Read the file in chunks
while True:
chunk = f_in.read(1024)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
padder = sym_padding.PKCS7(128).padder()
chunk = padder.update(chunk) + padder.finalize()
encrypted_chunk = encryptor.update(chunk)
f_out.write(encrypted_chunk)
# Finalize encryption
f_out.write(encryptor.finalize())

print(f"File encrypted successfully: {output_file}")

def decrypt_file(input_file, output_file, password):
with open(input_file, 'rb') as f_in:
# Read salt and IV from the input file
salt = f_in.read(16)
iv = f_in.read(16)

# Derive key
key = derive_key(password, salt, 256)

# Initialize cipher
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()

# Prepare to write decrypted data
try:
with open(output_file, 'w+b') as f_out:
# Read the encrypted file in chunks
while True:
chunk = f_in.read(1024)
if len(chunk) == 0:
break
decrypted_chunk = decryptor.update(chunk)
f_out.write(decrypted_chunk)
# Finalize decryption
decrypted_chunk = decryptor.finalize()
f_out.write(decrypted_chunk)
# Remove padding
f_out.seek(0)
data = f_out.read()
unpadder = sym_padding.PKCS7(128).unpadder()
data = unpadder.update(data) + unpadder.finalize()
f_out.seek(0)
f_out.write(data)
f_out.truncate()
print(f"File decrypted successfully: {output_file}")
except Exception as e:
print("Decryption failed. Incorrect password or corrupted file.")
# Ensure the file is closed before deletion
if not f_out.closed:
f_out.close()
if os.path.exists(output_file):
os.remove(output_file)


def main():
parser = argparse.ArgumentParser(description='AES File Encryption Tool')
parser.add_argument('mode', choices=['encrypt', 'decrypt'], help='Mode of operation')
parser.add_argument('input_file', help='Input file path')
parser.add_argument('output_file', nargs='?', help='Output file path')
args = parser.parse_args()

if not os.path.exists(args.input_file):
print("Input file does not exist.")
sys.exit(1)

if not args.output_file:
# Generate default output file name
if args.mode == 'encrypt':
args.output_file = args.input_file + '.enc'
else:
if args.input_file.endswith('.enc'):
args.output_file = args.input_file[:-4]
else:
args.output_file = args.input_file + '.dec'

password = getpass.getpass(prompt='Enter password: ')

if args.mode == 'encrypt':
encrypt_file(args.input_file, args.output_file, password)
else:
decrypt_file(args.input_file, args.output_file, password)

if __name__ == '__main__':
main()

0 comments on commit a458115

Please sign in to comment.