Cryptography − File



File encryption is the process of encoding files, including any sensitive data they contain, in order to transport them securely. The encoding protects against unauthorized access and tampering by malicious actors. It prevents a file from being viewed by anyone other than the intended recipient(s).

For example, if you operate in life sciences, you may require dependable methods to prevent innovative new designs or breakthrough medicine patents from coming into competitors' hands. Or maybe you work in the media and need a dependable technique to keep the most popular new script under wraps so no one can leak details.

Sometimes you work in law, banking, or another professional field where your clients expect you to keep their personal information private and secure. File encryption provides an effective solution. It allows you to make your sensitive data inaccessible to anyone except authorized recipients.

How File Encryption Work?

File encryption is done by a set of complicated algorithms. An encrypted file contains data that has been encrypted using an encryption algorithm. The file becomes unreadable after encryption, but this is only temporary.

The data is encrypted with a key provided by the sender. This key is typically in the form of a password or passphrase, like a string of alphanumeric digits that allows decryption.

  • Only those who are authorized to access the data are given the decryption key. When the authorized recipient enters the right password or passphrase, the file becomes readable again.
  • Most of the operating systems and file systems allow file encryption by default. The system saves important files securely, and the decryption key allows access to them.
  • It frequently uses public key cryptography, in which key pairs are generated using certain mathematical processes that are difficult to break.
  • These key pairs are distributed only to predefined recipients and senders, resulting in a lock-and-key method for encrypting and decrypting data in transit, use, and at rest.
  • File encryption is very useful when sending files over the internet or to a portable device like a USB drive. It secures the files throughout transit, when they are usually most susceptible.

Encryption Methods

You have to select the right encryption method before you start the process of encrypting files. You have multiple alternatives to select from −

  • File-level Encryption − With this type of protection, you can encrypt individual files to protect them more specifically. This strategy is ideal for files that need additional security or contain sensitive information.

    Encrypting individual files provides you more control over access and makes sure even if one file is compromised, the others remain protected.

  • Folder-level Encryption − Encrypting all of the folders and all of the data stored within them is a more comprehensive approach. This method can be useful for protecting a large number of connected files at once.

    Encrypting folders simplifies the encryption process because it allows you to protect several files at the same time while maintaining their structure and order.

  • Complete-disk Encryption − Encrypting the entire storage device like a hard drive or SSD quickly encrypts all data and files on it which provides complete protection.

    Complete-disk encryption is particularly helpful with portable devices like laptops since it protects all data stored on them even if the device is lost or stolen.

Popular File Encryption Standards

There are many methods of encryption for encrypted file sharing. Some are commonly used in specific organisations, while others are well suited to specific databases. Popular encryption standards are as following −

  • AS2, AS3, or AS4
  • Open PGP
  • PeSIT
  • HTTPS
  • ZIP with AES
  • FTPS (File Transfer Protocol over SSL)
  • SFTP (SSH File Transfer Protocol)

In order to conceal the message, most encryption algorithms filter data multiple times through substitutions, permutations, and other processes.

How to Encrypt a File?

As we have seen earlier, encryption is usually carried out using public key cryptography, but there are several different kinds to be aware of, each with its own set of advantages for particular application scenarios.

The first is asymmetric cryptography, which uses public and private keys provided to users to ensure secure and encrypted communication.

  • Public keys encrypt files, and private keys, which differ by user, decrypt files that are knowingly intended for them. Asymmetric encryption is commonly used for activities over public networks and internet connections, like when a user sends an image to friends using an instant messaging application like WhatsApp.
  • Whereas, symmetric encryption encrypts and decrypts data sent between users using only one private key. This creates a vulnerability since a stolen private key provides quick and easy access to a sensitive data.

But symmetric encryption is useful when a large amount of information needs to be encrypted at once, such as when an organization transfers all of its data from one software application or device to another.

The algorithm used to encrypt files depends on the software program, but normal methods include −

  • PGP and OpenPGP − PGP stands for pretty good privacy and was created in the 1990s by Phil Zimmermann as one of the first methods to encrypted communication. It works with asymmetric cryptography.

    Because of patent rights, PGP is only available with Symantec licensing. To make PGP more accessible, Zimmermann made its source code, OpenPGP, available for all organizations to use and adapt to create their own encryption system.

  • Secure Shell Protocol (SSH) − SSH is also known as the ssh-key gen program in its open-source version. It connects SSH clients to SSH servers using both asymmetric and symmetric cryptography.

    Asymmetric cryptography is used for initial identification and connection establishment, while symmetric cryptography is used to maintain and secure future conversations. SSH supports a number of common algorithms, like RSA, DSA, ECDSA, and ED25519.

  • ZIP using AES − Instead of using symmetric encryption, ZIP with AES compresses and encrypts files via the substitution permutation network (SPN) technique. SPN, as legally stated by the National Institute of Standards and Technology (NIST), builds keys that are at least 128 bits long, allowing an attacker to run over an infinite number of variations, which may take millions of years to break. ZIP with AES provides one of the most powerful encryption options available today.

What File Transfer Encryption Do?

Each encryption standard provides somewhat different protections for the privacy and integrity of the company's data. For example −

  • Open PGP encryption is used to encrypt, decrypt, and authenticate files. It secures data by hashing, data compression, symmetric private-key cryptography, and asymmetric public-key cryptography. PGP encryption, which is carried out using software tools, converts plain, readable text into a complex code of characters that are unreadable.
  • GPG (GnuPG), an alternative implementation of the Open PGP standard, can open and decipher files encrypted by PGP or Open PGP.
  • SFTP uses encryption algorithms to securely transmit data to your server, keeping files unreadable in the process. SFTP additionally needs authentication to prevent un-authorized file access during the transfer.

Implement File Encryption and Decryption

In this code, we encrypt and decrypt files using symmetric encryption with the Fernet module. A random encryption key is generated and used to encrypt and decrypt the contents of a file.

Example

Following are the programs to encrypt and decrypt files in different languages i.e. C, C++, Python and Java −

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/sha.h>

// Function to generate a random key
void generate_key(unsigned char *key) {
   if (!RAND_bytes(key, 32)) {
      fprintf(stderr, "Error generating random bytes.\n");
      exit(1);
   }
}

// Function to encrypt a file
void encrypt_file(const unsigned char *key, const char *input_file, const char *output_file) {
   FILE *in_file = fopen(input_file, "rb");
   FILE *out_file = fopen(output_file, "wb");
   unsigned char iv[AES_BLOCK_SIZE]; // Initialization vector
   unsigned char buffer[1024]; // Buffer for file reading
   unsigned char encrypted[1024];
   int bytes_read, encrypted_len;

   if (!in_file || !out_file) {
      fprintf(stderr, "File opening error.\n");
      exit(1);
   }

   // Generate a random IV
   if (!RAND_bytes(iv, AES_BLOCK_SIZE)) {
      fprintf(stderr, "Error generating random IV.\n");
      exit(1);
   }
    
   // Write IV to the output file first
   fwrite(iv, 1, AES_BLOCK_SIZE, out_file);

   // Initialize the encryption context
   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
   EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);

   // Read from input file and encrypt the data
   while ((bytes_read = fread(buffer, 1, sizeof(buffer), in_file)) > 0) {
      if (!EVP_EncryptUpdate(ctx, encrypted, &encrypted_len, buffer, bytes_read)) {
         fprintf(stderr, "Encryption error.\n");
         exit(1);
      }
      fwrite(encrypted, 1, encrypted_len, out_file);
   }

   // Finalize encryption
   if (!EVP_EncryptFinal_ex(ctx, encrypted, &encrypted_len)) {
      fprintf(stderr, "Final encryption error.\n");
      exit(1);
   }
   fwrite(encrypted, 1, encrypted_len, out_file);

   EVP_CIPHER_CTX_free(ctx);
   fclose(in_file);
   fclose(out_file);
}

// Function to decrypt a file
void decrypt_file(const unsigned char *key, const char *input_file, const char *output_file) {
   FILE *in_file = fopen(input_file, "rb");
   FILE *out_file = fopen(output_file, "wb");
   unsigned char iv[AES_BLOCK_SIZE]; // Initialization vector
   unsigned char buffer[1024]; // Buffer for file reading
   unsigned char decrypted[1024];
   int bytes_read, decrypted_len;

   if (!in_file || !out_file) {
      fprintf(stderr, "File opening error.\n");
      exit(1);
   }

   // Read IV from the encrypted file
   fread(iv, 1, AES_BLOCK_SIZE, in_file);

   // Initialize the decryption context
   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
   EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);

   // Read and decrypt the data
   while ((bytes_read = fread(buffer, 1, sizeof(buffer), in_file)) > 0) {
      if (!EVP_DecryptUpdate(ctx, decrypted, &decrypted_len, buffer, bytes_read)) {
         fprintf(stderr, "Decryption error.\n");
         exit(1);
      }
      fwrite(decrypted, 1, decrypted_len, out_file);
   }

   // Finalize decryption
   if (!EVP_DecryptFinal_ex(ctx, decrypted, &decrypted_len)) {
      fprintf(stderr, "Final decryption error.\n");
      exit(1);
   }
   fwrite(decrypted, 1, decrypted_len, out_file);

   EVP_CIPHER_CTX_free(ctx);
   fclose(in_file);
   fclose(out_file);
}

int main() {
   unsigned char key[32]; // 256-bit key
   generate_key(key); // Generate a random key

   const char *input_file = "plain_text.txt";   // Input file to be encrypted
   const char *encrypted_file = "encrypted_file.txt"; // Output encrypted file
   const char *decrypted_file = "decrypted_file.txt"; // Output decrypted file

   // Encrypt the file
   encrypt_file(key, input_file, encrypted_file);
   printf("File encrypted successfully.\n");

   // Decrypt the file
   decrypt_file(key, encrypted_file, decrypted_file);
   printf("File decrypted successfully.\n");

   return 0;
}

Output

The output obtained is as follows −

File encrypted successfully.
File decrypted successfully.
#include <iostream>
#include <fstream>
#include <sstream>  // Include this header for stringstream
#include <openssl/evp.h>
#include <openssl/rand.h>

using namespace std;

// Function to generate a random key for encryption
void generate_key(unsigned char *key) {
   if (!RAND_bytes(key, 32)) {
      cerr << "Error generating random key." << endl;
      exit(1);
   }
}

// Function to encrypt a file
void encrypt_file(const unsigned char *key, const char *input_file, const char *output_file) {
   // Open the input file
   ifstream infile(input_file, ios::binary);
   if (!infile) {
      cerr << "Error opening input file: " << input_file << endl;
      exit(1);
   }

   // Read the input file data
   stringstream buffer;
   buffer << infile.rdbuf();
   string data = buffer.str();
   infile.close();

   // Initialize the encryption context
   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
   if (!ctx) {
      cerr << "Error initializing cipher context." << endl;
      exit(1);
   }

   if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, nullptr)) {
      cerr << "Error initializing encryption." << endl;
      exit(1);
   }

   unsigned char iv[EVP_MAX_IV_LENGTH] = {0}; // Initialize with zeros, IV can be random as well
   unsigned char *encrypted_data = new unsigned char[data.size() + EVP_MAX_BLOCK_LENGTH];
   int len = 0;
   int ciphertext_len = 0;

   // Encrypt the data
   if (1 != EVP_EncryptUpdate(ctx, encrypted_data, &len, reinterpret_cast<const unsigned char*>(data.c_str()), data.size())) {
      cerr << "Error encrypting data." << endl;
      exit(1);
   }
   ciphertext_len = len;

   if (1 != EVP_EncryptFinal_ex(ctx, encrypted_data + len, &len)) {
      cerr << "Error finalizing encryption." << endl;
      exit(1);
   }
   ciphertext_len += len;

   // Write the encrypted data to the output file
   ofstream outfile(output_file, ios::binary);
   if (!outfile) {
      cerr << "Error opening output file: " << output_file << endl;
      exit(1);
   }

   outfile.write(reinterpret_cast<char*>(encrypted_data), ciphertext_len);
   outfile.close();

   // Clean up
   EVP_CIPHER_CTX_free(ctx);
   delete[] encrypted_data;
}

// Function to decrypt a file
void decrypt_file(const unsigned char *key, const char *input_file, const char *output_file) {
   // Open the input file
   ifstream infile(input_file, ios::binary);
   if (!infile) {
      cerr << "Error opening input file: " << input_file << endl;
      exit(1);
   }

   // Read the encrypted file data
   stringstream buffer;
   buffer << infile.rdbuf();
   string encrypted_data = buffer.str();
   infile.close();

   // Initialize the decryption context
   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
   if (!ctx) {
      cerr << "Error initializing cipher context." << endl;
      exit(1);
   }

   if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, nullptr)) {
      cerr << "Error initializing decryption." << endl;
      exit(1);
   }

   unsigned char iv[EVP_MAX_IV_LENGTH] = {0}; // Initialize with zeros, IV can be random as well
   unsigned char *decrypted_data = new unsigned char[encrypted_data.size()];
   int len = 0;
   int plaintext_len = 0;

   // Decrypt the data
   if (1 != EVP_DecryptUpdate(ctx, decrypted_data, &len, reinterpret_cast<const unsigned char*>(encrypted_data.c_str()), encrypted_data.size())) {
      cerr << "Error decrypting data." << endl;
      exit(1);
   }
   plaintext_len = len;

   if (1 != EVP_DecryptFinal_ex(ctx, decrypted_data + len, &len)) {
      cerr << "Error finalizing decryption." << endl;
      exit(1);
   }
   plaintext_len += len;

   // Write the decrypted data to the output file
   ofstream outfile(output_file, ios::binary);
   if (!outfile) {
      cerr << "Error opening output file: " << output_file << endl;
      exit(1);
   }

   outfile.write(reinterpret_cast<char*>(decrypted_data), plaintext_len);
   outfile.close();

   // Clean up
   EVP_CIPHER_CTX_free(ctx);
   delete[] decrypted_data;
}

int main() {
   unsigned char key[32];
   generate_key(key); // Generate the key

   const char *input_file = "plain_text.txt";
   const char *encrypted_file = "encrypted_file.txt";
   const char *decrypted_file = "decrypted_file.txt";

   // Encrypt the file
   encrypt_file(key, input_file, encrypted_file);
   cout << "File encrypted successfully!" << endl;

   // Decrypt the file
   decrypt_file(key, encrypted_file, decrypted_file);
   cout << "File decrypted successfully!" << endl;

   return 0;
}

Output

The output produced is as follows −

File encrypted successfully!
File decrypted successfully!
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.security.*;

public class FileEncryption {
   public static void generateKey(byte[] key) throws NoSuchAlgorithmException {
      SecureRandom random = new SecureRandom();
      random.nextBytes(key);
   }

   public static void encryptFile(byte[] key, String inputFile, String outputFile) throws Exception {
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
      IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]); // Initialization vector

      cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

      try (FileInputStream inFile = new FileInputStream(inputFile);
           FileOutputStream outFile = new FileOutputStream(outputFile);
           CipherOutputStream cipherOut = new CipherOutputStream(outFile, cipher)) {
         byte[] buffer = new byte[1024];
         int bytesRead;
         while ((bytesRead = inFile.read(buffer)) != -1) {
            cipherOut.write(buffer, 0, bytesRead);
         }
      }
   }

   public static void decryptFile(byte[] key, String inputFile, String outputFile) throws Exception {
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
      IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]);

      cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

      try (FileInputStream inFile = new FileInputStream(inputFile);
           FileOutputStream outFile = new FileOutputStream(outputFile);
           CipherInputStream cipherIn = new CipherInputStream(inFile, cipher)) {
         byte[] buffer = new byte[1024];
         int bytesRead;
         while ((bytesRead = cipherIn.read(buffer)) != -1) {
            outFile.write(buffer, 0, bytesRead);
         }
      }
   }

   public static void main(String[] args) {
      try {
         byte[] key = new byte[32];
         generateKey(key);

         encryptFile(key, "plain_text.txt", "encrypted_file.txt");
         decryptFile(key, "encrypted_file.txt", "decrypted_file.txt");

         System.out.println("Encryption and Decryption completed successfully.");
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

Output

The output obtained is as shown below −

Encryption and Decryption completed successfully.
from cryptography.fernet import Fernet

def generate_key():
   return Fernet.generate_key()

def encrypt_file(key, input_file, output_file):
   with open(input_file, 'rb') as f:
      data = f.read()

   cipher_suite = Fernet(key)
   encrypted_data = cipher_suite.encrypt(data)

   with open(output_file, 'wb') as f:
      f.write(encrypted_data)

def decrypt_file(key, input_file, output_file):
   with open(input_file, 'rb') as f:
      encrypted_data = f.read()

   cipher_suite = Fernet(key)
   decrypted_data = cipher_suite.decrypt(encrypted_data)

   with open(output_file, 'wb') as f:
      f.write(decrypted_data)

# Function execution
key = generate_key()
input_file = 'plain_text.txt'
encrypted_file = 'encrypted_file.txt'
decrypted_file = 'decrypted_file.txt'

encrypt_file(key, input_file, encrypted_file)
decrypt_file(key, encrypted_file, decrypted_file)

First create a text file in which we will create the plaintext and name it as plain_text.txt. To run the above code go to the directory where your program and plain_text.txt files are saved and run the program using 'python file_encryption.py'.

Here file_encryption.py is our file name. So after running the code you will see two text files have been created in the same folder where your python program is located. First file is encrypted_file.txt and second file is decrypted_file.txt.

Input

#plain_text.txt 
Cryptography - Image
Cryptography - File
Steganography - Image

Output

#encrypted_file.txt 
gAAAAABmOK54sMc5plvajOUICbeR5OCGfC7C_2ZWZVOYwU0SSWM1V4qkZcYR4kWpE4u1HvsQmbjkCwLOBGbrs0gIt6s4eXnSP06xsjryhD1CqhylQaFsWiFQ8K78uOb8DPSAIF2Aw3vFrPbIviO29b6LPFjBz39_MQ==
Output

Future of File Encryption

File encryption will increasingly depend on password less and key-less authentication, which has several benefits. First, it improves usability by removing the need for users to memorize difficult passwords or manually manage keys.

This allows unlimited access to information. Second, it saves IT departments money and effort by eliminating the need to handle passwords and keys.

Passwordless authentication minimizes administration tasks and costs. Third, it increases security by reducing the possibility of passwords or keys falling into malicious hands. Overall, passwordless and keyless authentication will offer a more efficient, cost-effective, and secure method of file encryption in the future.

What Files Can be Encrypted?

Encryption is possible for almost any file type, such as text files, emails, data files, directories, even disc partitions. Encryption software can be used on a variety of platforms, including cloud-based and on-premises, like Windows, VMware, Linux, Azure, IBM i, AIX, UNIX, and Mac OS.

Advertisements