<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aditya R</title>
    <description>The latest articles on DEV Community by Aditya R (@aditya_r_e0eab9ccef0d1122).</description>
    <link>https://dev.to/aditya_r_e0eab9ccef0d1122</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3446970%2F3f2f5150-a46d-4f24-b2b9-ead762d4a68f.png</url>
      <title>DEV Community: Aditya R</title>
      <link>https://dev.to/aditya_r_e0eab9ccef0d1122</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aditya_r_e0eab9ccef0d1122"/>
    <language>en</language>
    <item>
      <title>🔐 End-to-End File Encryption with AES and Integrity Checks</title>
      <dc:creator>Aditya R</dc:creator>
      <pubDate>Thu, 28 Aug 2025 12:00:00 +0000</pubDate>
      <link>https://dev.to/aditya_r_e0eab9ccef0d1122/end-to-end-file-encryption-with-aes-and-integrity-checks-310i</link>
      <guid>https://dev.to/aditya_r_e0eab9ccef0d1122/end-to-end-file-encryption-with-aes-and-integrity-checks-310i</guid>
      <description>&lt;h2&gt;
  
  
  🔑 Introduction
&lt;/h2&gt;

&lt;p&gt;Imagine sealing a letter inside a locked safe before sending it — even if someone grabs it, they can’t read what’s inside.&lt;br&gt;
That’s exactly what encryption brings to file transfers.&lt;/p&gt;

&lt;p&gt;In the previous parts of this series, we’ve built a foundation for trustworthy file transfers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ SHA-256 Checksums → detect accidental corruption.&lt;/li&gt;
&lt;li&gt;✅ HMAC-SHA256 → ensure integrity + authenticity with a shared secret.&lt;/li&gt;
&lt;li&gt;✅ Digital Signatures → verify authenticity using public/private keys.
So far, we’ve made sure files can’t be tampered with or forged.
But here’s the missing piece: what if someone intercepts the transfer and simply reads the file’s contents?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where confidentiality comes in.&lt;/p&gt;

&lt;p&gt;Think of it this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AES encryption is like putting your file inside a bank vault — only someone with the right key can open it.&lt;/li&gt;
&lt;li&gt;Integrity checks act like a tamper-evident seal on that vault — if someone even tries to mess with it, you’ll know immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this part, we’ll explore AES (Advanced Encryption Standard) — a fast and secure encryption method — and show how to combine it with integrity checks so your files remain both private and trusted end-to-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AES? (The Friendly Version)
&lt;/h2&gt;

&lt;p&gt;Think of AES (Advanced Encryption Standard) as a super-secure lockbox for your files.&lt;br&gt;
When you put a file inside this lockbox, it scrambles everything into unreadable gibberish — so if someone intercepts it, all they see is nonsense.&lt;/p&gt;

&lt;p&gt;The only way to open this lockbox is with the right secret key — just like a password. Without it, even the smartest hacker with the fastest computer would need billions of years to figure it out.&lt;/p&gt;

&lt;p&gt;That’s why AES is trusted worldwide: it’s not only fast and efficient, but also virtually unbreakable for protecting sensitive information. From online banking to cloud storage to secure messaging apps, AES is everywhere behind the scenes keeping data safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  In technical words
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AES (Advanced Encryption Standard) is a symmetric-key algorithm, meaning the same key is used for encryption and decryption.&lt;/li&gt;
&lt;li&gt;It’s fast, secure, and widely used in banking, cloud storage, and enterprise systems.&lt;/li&gt;
&lt;li&gt;Key sizes: 128, 192, or 256 bits. Most systems use AES-256 for stronger security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How AES Fits in File Transfers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sender encrypts the file using AES with a secret key.&lt;/li&gt;
&lt;li&gt;The encrypted file is transmitted.&lt;/li&gt;
&lt;li&gt;Along with the encrypted file, the sender computes an integrity check (like HMAC-SHA256) of the ciphertext.&lt;/li&gt;
&lt;li&gt;Receiver decrypts using the same AES key and verifies the integrity before trusting the file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No one can read the file during transfer.&lt;/li&gt;
&lt;li&gt;No one can tamper with it undetected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Python Sample Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Encrypting a File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import os

def encrypt_file(file_path, encrypted_file_path, key, iv):

    # Read File Data
    with open(file_path, 'rb') as fin:
        data = fin.read()

    # Pad the Data (AES needs data in blocks)
    padder = padding.PKCS7(128).padder()   # 128-bit AES Block Size
    padded_data = padder.update(data) + padder.finalize()

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

    # Encrypt the data
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()

    # Write IV + Encrypted Data to the Output File
    with open(encrypted_file_path, 'wb') as fout:
        fout.write(iv + encrypted_data)

    print("Encrypted file saved to {}".format(encrypted_file_path))

if __name__ == '__main__':

    # Generate a random AES key (256-bit for strong encryption)
    key = os.urandom(32)  # 32 bytes = 256-bits

    # Generate a random Initialization Vector (IV) for CBC Mode
    iv = os.urandom(16)   # 16 bytes for AES Block Size

    # Provide the Input File and Output File Paths
    file_path = 'sample.txt'
    output_file_path = 'sample.txt.enc'

    encrypt_file(file_path, output_file_path, key, iv)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Notes:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We generate a random 256-bit AES key and a 16-byte IV.&lt;/li&gt;
&lt;li&gt;The file data is padded so it fits into AES blocks.&lt;/li&gt;
&lt;li&gt;The IV is written at the start of the encrypted file — you’ll need it for decryption.&lt;/li&gt;
&lt;li&gt;The key must be stored securely (e.g., in a key vault, environment variable, or securely shared).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Decrypting a File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def decrypt_file(encrypted_file_path, output_file_path, key):

    # Read IV + Encrypted Data
    with open(encrypted_file_path, 'rb') as fin:
        data = fin.read()

    iv = data[:16]  # First 16 bytes is IV
    encrypted_data = data[16:]

    # Create AES Cipher with the same Key and IV
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()

    # Decrypt Data
    decrypted_padded = decryptor.update(encrypted_data) + decryptor.finalize()

    # Remove Padding
    padder = padding.PKCS7(128).padder()
    decrypted_data = padder.update(decrypted_padded) + padder.finalize()

    # Write the Original File
    with open(output_file_path, 'wb') as fout:
        fout.write(decrypted_data)

    print("Successfully decrypted file")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Encryption

&lt;ul&gt;
&lt;li&gt;File → Pad → Encrypt (AES CBC) → Write [IV + Ciphertext].&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Decryption

&lt;ul&gt;
&lt;li&gt;Read IV (first 16 bytes).&lt;/li&gt;
&lt;li&gt;Use same AES key + IV.&lt;/li&gt;
&lt;li&gt;Decrypt → Remove padding → Write original file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the file is decrypted, the next step is ensuring integrity. There are multiple ways to do this — from simple hashes to advanced digital signatures. Curious to learn how?&lt;/p&gt;

&lt;p&gt;Check out my earlier blog posts in this series on &lt;a href="https://dev.to/aditya_r_e0eab9ccef0d1122/securing-file-transfers-with-sha-256-a-simple-yet-effective-approach-1dfh"&gt;SHA-256&lt;/a&gt;, &lt;a href="https://dev.to/aditya_r_e0eab9ccef0d1122/beyond-checksums-securing-file-transfers-with-hmac-sha256-5396"&gt;HMAC&lt;/a&gt;, and &lt;a href="https://dev.to/aditya_r_e0eab9ccef0d1122/from-hashes-to-signatures-securing-file-transfers-with-rsaecdsa-digital-signatures-6im"&gt;Digital Signatures&lt;/a&gt; to see these approaches in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros and Cons of AES in File Transfers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong confidentiality (keeps file content secret)&lt;/li&gt;
&lt;li&gt;Fast and efficient (especially on large files)&lt;/li&gt;
&lt;li&gt;Widely supported and trusted&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Requires secure key exchange between sender &amp;amp; receiver&lt;/li&gt;
&lt;li&gt;Both systems must manage keys carefully (risk of compromise)&lt;/li&gt;
&lt;li&gt;Symmetric — not ideal for multi-party distribution without extra layers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where is this useful?
&lt;/h2&gt;

&lt;p&gt;Think of AES encryption with integrity checks as sending a locked vault with a tamper-proof seal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal file transfers within banks or enterprises → Just like how a bank moves money in armored trucks, files (like transaction records) need both protection (encryption) and proof that no one opened the truck on the way (integrity check).&lt;/li&gt;
&lt;li&gt;Healthcare systems exchanging patient data → Similar to how hospitals use sealed envelopes for sensitive test results, AES ensures the content stays private, while integrity checks prove nothing was swapped inside.&lt;/li&gt;
&lt;li&gt;Software distribution → Like buying a medicine bottle that’s shrink-wrapped: encryption protects the contents, while integrity ensures no one tampered with the medicine before it reached you.&lt;/li&gt;
&lt;li&gt;Government or defense communications → Comparable to sending secret orders in a locked briefcase with a wax seal; AES locks it tight, and integrity checks are the seal that shows whether it was broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, AES with integrity checks is valuable anywhere you need to keep files private AND prove they haven’t been altered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With AES, we’ve taken a major leap: not only do we lock files away with encryption, but we also seal them with integrity checks so that tampering can’t go unnoticed. It’s like sending a package in a vault that only the receiver can open — and if someone tries to meddle with it, the broken seal tells the story.&lt;/p&gt;

&lt;p&gt;But here’s the exciting part: this is just the beginning.&lt;br&gt;
So far, we’ve built our security journey step by step — from basic checksums to HMAC secrets, then into the realm of digital signatures, and now AES-powered encryption with integrity. Each step has been a new layer of defense.&lt;/p&gt;

&lt;p&gt;In the next stage, we’ll go beyond theory and start stitching these building blocks together — exploring end-to-end secure file transfer pipelines, hybrid encryption models, and how these approaches scale in real-world enterprise systems.&lt;/p&gt;

&lt;p&gt;Stay tuned — because the real magic happens when all these pieces come together.&lt;/p&gt;

&lt;p&gt;The sample codes can be found in my &lt;a href="https://github.com/WeirdThinker15/blog_posts/tree/main/practical_cryptography_series/end_to_end_security_with_aes" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>security</category>
      <category>tutorial</category>
      <category>fileintegrity</category>
    </item>
    <item>
      <title>From Hashes to Signatures: Securing File Transfers with RSA/ECDSA Digital Signatures</title>
      <dc:creator>Aditya R</dc:creator>
      <pubDate>Fri, 22 Aug 2025 12:30:00 +0000</pubDate>
      <link>https://dev.to/aditya_r_e0eab9ccef0d1122/from-hashes-to-signatures-securing-file-transfers-with-rsaecdsa-digital-signatures-6im</link>
      <guid>https://dev.to/aditya_r_e0eab9ccef0d1122/from-hashes-to-signatures-securing-file-transfers-with-rsaecdsa-digital-signatures-6im</guid>
      <description>&lt;h2&gt;
  
  
  🔑 Introduction
&lt;/h2&gt;

&lt;p&gt;In the first two parts of this series, I explored how to secure file transfers using SHA-256 checksums for integrity and then took it a step further with HMAC-SHA256, which added authenticity through a shared secret key. These approaches work well in trusted environments, especially for internal or on-prem systems.&lt;/p&gt;

&lt;p&gt;But what happens when the systems are not in the same secure network, or when you need to ensure that even without a shared secret, the file’s integrity and the sender’s identity can be verified? That’s where Digital Signatures come into play.&lt;/p&gt;

&lt;p&gt;Digital signatures, built on algorithms like RSA (Rivest–Shamir–Adleman) and ECDSA (Elliptic Curve Digital Signature Algorithm), bring two powerful guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrity — ensuring the file hasn’t been tampered with.&lt;/li&gt;
&lt;li&gt;Authenticity — proving that the file truly came from the claimed sender.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this part, I’ll explore how digital signatures fit into secure file transfers, compare RSA and ECDSA, and walk through generating and verifying signatures with code examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75hv0qa3vpkxnjpls3y3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75hv0qa3vpkxnjpls3y3.png" alt="From fingerprints to handshakes to seals — the evolution of securing file transfers: Checksum → HMAC → Digital Signatures." width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 What Are Digital Signatures?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A digital signature is like a virtual fingerprint for a file.&lt;/li&gt;
&lt;li&gt;It ensures that the file has not been tampered with (integrity).&lt;/li&gt;
&lt;li&gt;It ensures that the file truly comes from the claimed sender (authenticity).&lt;/li&gt;
&lt;li&gt;It works using a private key (to sign) and a public key (to verify).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚙️ How It Works (Step-by-Step)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sender generates a hash of the file (e.g., SHA-256).&lt;/li&gt;
&lt;li&gt;Sender encrypts the hash with their private key → digital signature.&lt;/li&gt;
&lt;li&gt;The file + signature are sent to the receiver.&lt;/li&gt;
&lt;li&gt;Receiver generates their own hash of the received file.&lt;/li&gt;
&lt;li&gt;Receiver decrypts the signature using sender’s public key to retrieve the original hash.&lt;/li&gt;
&lt;li&gt;If both hashes match → the file is authentic and untampered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1d2605nusadr28xnsfno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1d2605nusadr28xnsfno.png" alt="Overall Flow" width="720" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 How to Generate Key Pairs
&lt;/h2&gt;

&lt;p&gt;To use digital signatures, you need a key pair:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Private Key (kept secret, used for signing).&lt;/li&gt;
&lt;li&gt;Public Key (shared, used for verifying).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many ways to generate the key pairs. The common and straightforward way is to use the openssl library. Here I provide the Python way.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔑 Generating RSA Key Pairs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate RSA Public-Private Key
def generate_rsa_key(private_key_file, public_key_file):
    private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)

    # Save Private Key
    with open(private_key_file, "wb") as fout:
        fout.write(private_key.private_bytes(
            encoding=serialization.Encoding.PEM,             # Format = PEM
            format=serialization.PrivateFormat.TraditionalOpenSSL,  # Structure - OpenSSL style
            encryption_algorithm=serialization.NoEncryption()  # No password protection
        ))

    # Save Public Key
    public_key = private_key.public_key()
    with open(public_key_file, "wb") as fout:
        fout.write(public_key.public_bytes(
            encoding=serialization.Encoding.PEM,        # Format = PEM
            format=serialization.PublicFormat.SubjectPublicKeyInfo # Standard X.509 format
        ))

    print("RSA key generation complete")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔑 Generating ECDSA Key Pairs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate ECDSA Key Pair
def generate_ec_key(private_key_file, public_key_file):

    # Generate ECDSA Private Key
    private_key = ec.generate_private_key(ec.SECP256R1()) # Specifies which Elliptic Curve to use 
                          # Uses the curve known as prime256v1 or NIST P-256.

    # Save Private Key
    with open(private_key_file, "wb") as fout:
        fout.write(private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()
        ))

    # Save Public Key
    public_key = private_key.public_key()

    with open(public_key_file, "wb") as fout:
        fout.write(public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        ))

    print("EC key generation complete")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ RSA vs ECDSA Quick Note
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RSA → Widely used, mature, simpler to understand, but keys/signatures are larger.&lt;/li&gt;
&lt;li&gt;ECDSA → Faster, smaller keys, but more complex math. Popular in modern systems (TLS, blockchain).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A comparison table of RSA vs ECDSA is provided below for information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffikm7kofmvk3ehm980w1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffikm7kofmvk3ehm980w1.png" alt="RSA vs ECDSA" width="720" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Key Pairs are generated and saved, the next step is to generate the Digital Signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Signing the File
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_digital_signature(private_key_file, file_path, signature_file_path):

    # Load File Content
    with open(file_path, "rb") as fin:
        data = fin.read()

    # Read the Private Key from pem file
    with open(private_key_file, "rb") as fout:
        private_key = serialization.load_pem_private_key(
            fout.read(),
            password=None
        )

    # Sign the Data
    signature = private_key.sign(
        data,
        padding.PSS(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )

    # Save the Signature
    with open(signature_file_path, "wb") as fout:
        fout.write(signature)

    print("Signature generation complete")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand how the signing works.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;private_key.sign( …. ) :

&lt;ul&gt;
&lt;li&gt;Uses the RSA private key to generate a digital signature.&lt;/li&gt;
&lt;li&gt;Input is the raw data (in bytes) you want to sign.&lt;/li&gt;
&lt;li&gt;The result (signature) is a unique cryptographic value tied to  both the data and the private key.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;padding.PSS(…) : Provides Padding Schemes for Security

&lt;ul&gt;
&lt;li&gt;PSS (Probabilistic Signature Scheme) is used , which is the modern recommended padding for RSA signatures.&lt;/li&gt;
&lt;li&gt;It makes each signature different, even if the same data is signed multiple times (unlike older, deterministic schemes).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inside PSS:

&lt;ul&gt;
&lt;li&gt;mgf=padding.MGF1(hashes.SHA256()) → MGF1 is a mask generation function that adds randomness, using SHA-256 internally.&lt;/li&gt;
&lt;li&gt;salt_length=padding.PSS.MAX_LENGTH → Uses the largest possible salt (random value) to maximize security.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;hashes.SHA256()

&lt;ul&gt;
&lt;li&gt;Before signing, the file content is hashed using SHA-256.&lt;/li&gt;
&lt;li&gt;Instead of signing the entire raw file (which could be GBs in size), RSA signs this fixed-length hash digest.&lt;/li&gt;
&lt;li&gt;This ensures efficiency and security — even tiny changes in the file create a completely different hash, and thus a different signature.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ⚡ Plain-English Analogy
&lt;/h3&gt;

&lt;p&gt;Think of this like stamping a document with a unique wax seal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The document = your file (data).&lt;/li&gt;
&lt;li&gt;The stamp mold = your private key.&lt;/li&gt;
&lt;li&gt;The wax pattern (randomized via PSS) = padding randomness.&lt;/li&gt;
&lt;li&gt;The final wax seal impression = the signature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone with the public key can check the seal and confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The file hasn’t been changed.&lt;/li&gt;
&lt;li&gt;It really came from the holder of the private key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔑 Verifying the File
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Verify the File with the Signature
def verify_file(public_key_file, file_path, file_signature_path):

    # Load Public Key
    with open(public_key_file, "rb") as fin:
        public_key = serialization.load_pem_public_key(
            fin.read(),
            backend=default_backend()
        )

    # Load File Signature
    with open(file_signature_path, "rb") as fin:
        signature = fin.read()

    # Load File Content
    with open(file_path, "rb") as fin:
        data = fin.read()

    # Verify the Signature
    try:
        public_key.verify(
            signature=signature,
            data=data,
            padding=padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            algorithm=hashes.SHA256()
        )

        print("Signature verified")
    except Exception as e:
        print("Signature verification failed")
        print(f"Exception: {e}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✅ Pros and Cons
&lt;/h2&gt;

&lt;p&gt;Let's understand the Pros and Cons of this approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong authenticity (no shared secret needed).&lt;/li&gt;
&lt;li&gt;Works across untrusted networks.&lt;/li&gt;
&lt;li&gt;Non-repudiation: Sender cannot deny signing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Slower than checksum or HMAC.&lt;/li&gt;
&lt;li&gt;Requires secure key management.&lt;/li&gt;
&lt;li&gt;More complex setup compared to symmetric approaches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📂 When to Use Digital Signatures?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When files are shared across different organizations.&lt;/li&gt;
&lt;li&gt;When authenticity is critical (legal, financial, healthcare files).&lt;/li&gt;
&lt;li&gt;When compliance demands non-repudiation (e.g., contracts, audit logs).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📝 Conclusion
&lt;/h2&gt;

&lt;p&gt;Digital signatures add a powerful layer of security for file transfers — going beyond integrity to authenticity and trust. They are the go-to choice when sharing files in untrusted or external environments.&lt;/p&gt;

&lt;p&gt;➡️ In the next part of this series, I’ll look at AES Encryption for File Transfers to ensure not just authenticity, but also confidentiality.&lt;/p&gt;

&lt;p&gt;The code provided above can be found in &lt;a href="https://github.com/WeirdThinker15/blog_posts/tree/main/practical_cryptography_series/digital_signatures_approach" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>security</category>
      <category>securefiletransfers</category>
      <category>python</category>
    </item>
    <item>
      <title>Beyond Checksums: Securing File Transfers with HMAC-SHA256</title>
      <dc:creator>Aditya R</dc:creator>
      <pubDate>Thu, 21 Aug 2025 12:30:00 +0000</pubDate>
      <link>https://dev.to/aditya_r_e0eab9ccef0d1122/beyond-checksums-securing-file-transfers-with-hmac-sha256-5396</link>
      <guid>https://dev.to/aditya_r_e0eab9ccef0d1122/beyond-checksums-securing-file-transfers-with-hmac-sha256-5396</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/aditya_r_e0eab9ccef0d1122/securing-file-transfers-with-sha-256-a-simple-yet-effective-approach-1dfh"&gt;previous blog&lt;/a&gt;, we explored how to verify file integrity during transfers using SHA-256 checksums.&lt;br&gt;
That approach is effective in ensuring the file is intact — but it has a limitation: anyone who can get hold of the file can also generate the same SHA-256 hash.&lt;/p&gt;

&lt;p&gt;So how do we make it tamper-proof and also be able to verify authenticity without jumping to heavy public key cryptography?&lt;br&gt;
The answer: HMAC-SHA256.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 What is HMAC-SHA256?
&lt;/h2&gt;

&lt;p&gt;HMAC stands for Hash-based Message Authentication Code.&lt;br&gt;
It’s a cryptographic technique where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You take your file (or message),&lt;/li&gt;
&lt;li&gt;Combine it with a secret key that is known only to sender and receiver&lt;/li&gt;
&lt;li&gt;Run it through a hashing algorithm like SHA-256.
The result is a hash that can only be reproduced if you have both the exact file and the shared secret key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this matters:&lt;br&gt;
If an attacker changes the file, or tries to generate a fake hash without the secret key, the verification will fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ High-Level Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sender side:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Generate HMAC-SHA256 hash of the file using the shared secret key.&lt;/li&gt;
&lt;li&gt;Send both the file and the generated HMAC hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Receiver side:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recompute HMAC-SHA256 hash of the received file using the same key.&lt;/li&gt;
&lt;li&gt;Compare it with the sent hash.&lt;/li&gt;
&lt;li&gt;Match ✅ → file is intact and authenticated.
Mismatch ❌ → file is tampered or key mismatch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65rvoe5lsis8y6fse7vj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65rvoe5lsis8y6fse7vj.png" alt="High Level Workflow" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 How to Generate the Secret Key
&lt;/h2&gt;

&lt;p&gt;The security of HMAC entirely depends on the strength and secrecy of the key. A good secret key should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be long enough (at least 32 bytes for SHA-256).&lt;/li&gt;
&lt;li&gt;Be generated using a cryptographically secure random generator.&lt;/li&gt;
&lt;li&gt;Never be hardcoded in source code.&lt;/li&gt;
&lt;li&gt;Be stored securely (e.g., in environment variables, secrets manager, or secure vault).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📌 Example — Generate a Secret Key in Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_secret_key(key_outfile):
    # Generate a 32 byte(256-bit) random key
    key = secrets.token_bytes(32)
    encoded_key = base64.urlsafe_b64encode(key).decode()

    # Store the Key in a txt file for sharing it across 
    with open(key_outfile, "w") as fout:
        fout.write(encoded_key)

    print("Secret file generated")

# key_outfile is the file path to where the secret key is stored.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code generates a random base64-encoded key and stores it in a file, which can then be shared securely between systems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Pro Tip:&lt;br&gt;
Use a Secrets Manager (like AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) to store and retrieve the key securely.&lt;br&gt;
Rotate keys periodically to minimize risk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  📌 Example — Generating HMAC-SHA256 Hash in Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Function to generate the HMAC SHA-256 Hash 
def generate_hash(file_path, secret_key):
    with open(file_path, 'rb') as fin:
        file_data = fin.read()

    hash = hmac.new(secret_key.encode(), file_data, hashlib.sha256).hexdigest()
    return hash

# file_path : Path to the file for which hash is to be generated 
# secret_key : Secret Key to be used
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📌 Example — Verifying HMAC-SHA256 Hash in Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Function to verify the hash of the given file 
def verify_hash(file_path, secret_key, file_hash):

    # Compute the Hash of the File 
    calculated_hash = generate_hash(file_path=file_path, secret_key=secret_key)

    # Match the hash with the received hash 
    is_hash_valid = hmac.compare_digest(calculated_hash, file_hash)
    return is_hash_valid

# generate_hash Function as provided earlier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Pros
&lt;/h3&gt;

&lt;p&gt;Adds authentication: Ensures that only systems with the shared secret can generate the correct hash.&lt;br&gt;
Simple to implement: Works with most programming languages and libraries.&lt;br&gt;
Lightweight: No heavy cryptographic key pairs required.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Cons
&lt;/h3&gt;

&lt;p&gt;Key management: Both parties must securely store and protect the shared key.&lt;br&gt;
Not for untrusted distribution: If the key is leaked, security is compromised.&lt;br&gt;
Still no confidentiality: File content is not encrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Ideal Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Internal file transfers between trusted systems that share a secure key.&lt;/li&gt;
&lt;li&gt;Batch jobs or ETL processes where both ends are controlled environments.&lt;/li&gt;
&lt;li&gt;Verifying sensitive configuration files or scripts within DevOps pipelines.&lt;/li&gt;
&lt;li&gt;Ensuring authenticity of firmware updates within closed networks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧭 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;HMAC-SHA256 is a powerful upgrade from plain SHA-256 checksums, giving you both integrity and authenticity without overcomplicating the setup.&lt;br&gt;
It’s a great fit for controlled environments where a shared secret can be securely managed.&lt;/p&gt;

&lt;p&gt;Given that the secret needs to be securely shared and managed, in my next post, I will explore a way where the secret no longer needs to be shared.&lt;/p&gt;

&lt;p&gt;I have posted the code in &lt;a href="https://github.com/WeirdThinker15/blog_posts/tree/main/file_hashing/hmac_sha256_approach" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>sha256</category>
      <category>cryptography</category>
      <category>checksums</category>
    </item>
    <item>
      <title>Securing File Transfers with SHA-256: A Simple Yet Effective Approach</title>
      <dc:creator>Aditya R</dc:creator>
      <pubDate>Wed, 20 Aug 2025 10:30:00 +0000</pubDate>
      <link>https://dev.to/aditya_r_e0eab9ccef0d1122/securing-file-transfers-with-sha-256-a-simple-yet-effective-approach-1dfh</link>
      <guid>https://dev.to/aditya_r_e0eab9ccef0d1122/securing-file-transfers-with-sha-256-a-simple-yet-effective-approach-1dfh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In an era where data breaches and file tampering incidents make headlines, securing file transfers between systems has become a fundamental requirement in system design. While there are many mechanisms available to protect data in transit - such as encryption, digital signatures, and mutual authentication - these typically focus on who is sending or receiving the data.&lt;/p&gt;

&lt;p&gt;But what about what is being sent? How can you ensure that a file received at the destination is exactly the same as the one sent from the source system, with zero modifications - accidental or malicious?&lt;/p&gt;

&lt;p&gt;This is where checksums and hashes play a powerful role.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 The Integrity Challenge
&lt;/h2&gt;

&lt;p&gt;Even if the transport is secure (like over HTTPS, SFTP, or a VPN tunnel), file tampering can occur:&lt;br&gt;
During staging or transit through intermediate systems.&lt;br&gt;
Due to network glitches or disk write issues.&lt;br&gt;
Because of insider threats or misconfigured scripts.&lt;/p&gt;

&lt;p&gt;So, we need a mechanism to verify the integrity of the file, regardless of the identity or origin of the sender.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Enter Checksums and Hashing
&lt;/h3&gt;

&lt;p&gt;A checksum is a digital fingerprint of your file. It's generated using a mathematical algorithm (called a hash function) that takes in a file and outputs a fixed-length string. If even a single bit of the file changes, the resulting checksum will also change - making it a reliable method for detecting tampering.&lt;br&gt;
Historically, algorithms like CRC32 and MD5 were popular for checksum generation. However:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRC32 is fast but prone to collisions and not cryptographically secure.&lt;/li&gt;
&lt;li&gt;MD5 has been broken and is vulnerable to collision attacks, making it unsuitable for security-sensitive applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🔐 SHA-256 - A Modern, Secure Approach
&lt;/h2&gt;

&lt;p&gt;Today, SHA-256 (part of the SHA-2 family) is the industry standard for cryptographic hashing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It generates a 256-bit (32-byte) hash value.&lt;/li&gt;
&lt;li&gt;It's collision-resistant and widely used in SSL, blockchain, and file integrity systems.&lt;/li&gt;
&lt;li&gt;It's ideal for internal systems where encryption or digital signatures might be overkill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our scenario, we'll explore using SHA-256 for securing file transfers between two on-prem or internal systems that are already within a trusted network.&lt;/p&gt;
&lt;h2&gt;
  
  
  🏗️ High-Level Flow:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Source system computes the SHA-256 hash of the file.&lt;/li&gt;
&lt;li&gt;It sends both the file and its hash to the destination system.&lt;/li&gt;
&lt;li&gt;The destination system recomputes the SHA-256 hash of the received file.&lt;/li&gt;
&lt;li&gt;It compares the new hash with the original.&lt;/li&gt;
&lt;li&gt;If they match ✅: File is intact.&lt;/li&gt;
&lt;li&gt;If they differ ❌: File is tampered or corrupted.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  🧪 Example: Generating SHA-256 Hash
&lt;/h2&gt;

&lt;p&gt;You can use a variety of tools - Python, PowerShell, Linux utilities, or even C# - to generate the hash. For my use case, I had to develop PowerShell scripts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Save the code to a file : generate_hash.ps1

param (
    [Parameter(Mandatory = $true)]
    [string]$File,
    [string]$HashFile
)

#Check if the input file exists
if (-not (Test-Path $File)) {
    Write-Error "Input file '$File' not found."
    exit 1
}

#Set default hash file if not provided
if (-not $HashFile) {
    $HashFile = "$File.sha256"
}

try {
    # Compute SHA256 hash
    $hash = Get-FileHash -Path $File -Algorithm SHA256
    $hash.Hash | Out-File -FilePath $HashFile -Encoding ascii -Force
    Write-Output "SHA256 hash written to '$HashFile'"
    exit 0
}
catch {
    Write-Error "Failed to generate hash: $_"
    exit 2
}

# Sample Usage 
PS D:\GithubRepo\blog_posts\file_hashing&amp;gt; .\generate_hash.ps1 -File .\sample.txt
SHA256 hash written to '.\sample.txt.sha256'

PS D:\GithubRepo\blog_posts\file_hashing&amp;gt; cat .\sample.txt.sha256
C8447B1EC04E6D24B5B07D40126F30D7F6295B1F95E450EF64E4DEB627CADBC6`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔍 Verifying SHA-256 Hash on the Destination
&lt;/h2&gt;

&lt;p&gt;Once the file is received, verification is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Save the code to a file : verify_hash.ps1

param (
    [string]$File,
    [string]$HashFile
)

if (-not $File -or -not $HashFile) {
    Write-Output "Usage: .\verify_hash.ps1 -File &amp;lt;input_file&amp;gt; -HashFile &amp;lt;hash_file&amp;gt;"
    exit 1
}

if (-not (Test-Path $File)) {
    Write-Output "File '$File' not found."
    exit 1
}

if (-not (Test-Path $HashFile)) {
    Write-Output "Hash file '$HashFile' not found."
    exit 1
}

# Compute current hash
$computedHash = (Get-FileHash -Path $File -Algorithm SHA256).Hash.Trim()

# Read expected hash
$expectedHash = Get-Content $HashFile | Select-Object -First 1
$expectedHash = $expectedHash.Trim()

# Compare
if ($computedHash.ToUpper() -eq $expectedHash.ToUpper()) {
    Write-Output "Hash verified successfully."
} else {
    Write-Output "Hash mismatch!"
    Write-Output "Expected: $expectedHash"
    Write-Output "Actual:   $computedHash"
}

# Sample Usage
PS D:\GithubRepo\blog_posts\file_hashing&amp;gt; .\verify_hash.ps1 -File .\sample.txt -HashFile .\sample.txt.sha256
Hash verified successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔒 What About Security?
&lt;/h2&gt;

&lt;p&gt;While this approach ensures integrity, it does not provide:&lt;br&gt;
Confidentiality - File content is still in plaintext unless encrypted separately.&lt;br&gt;
Authentication - Anyone can generate a hash if they get the file.&lt;/p&gt;

&lt;p&gt;If your systems operate in an untrusted network or involve external parties, consider:&lt;br&gt;
Using HMAC-SHA256 (hash-based message authentication code with a secret key)&lt;br&gt;
Digitally signing the hash using a private key&lt;br&gt;
Encrypting the entire payload with TLS or PGP&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ When Is This Approach Ideal?
&lt;/h2&gt;

&lt;p&gt;Use SHA-256 checksum validation when:&lt;br&gt;
Systems are internal, trusted, and firewalled.&lt;br&gt;
You only care about integrity, not identity or secrecy.&lt;br&gt;
Lightweight and fast verification is a priority.&lt;/p&gt;

&lt;p&gt;This can be especially useful in:&lt;br&gt;
Automated data pipelines&lt;br&gt;
ETL jobs transferring CSV/JSON/XML files&lt;br&gt;
Batch file movement between microservices or legacy systems&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Bonus Tip: Automate the Workflow
&lt;/h2&gt;

&lt;p&gt;Generate hash on the source during export&lt;br&gt;
Transmit both .data and .data.sha256&lt;br&gt;
Use scheduled jobs or file watchers to verify and move files to staging or quarantine based on checksum match.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;SHA-256-based file integrity verification offers a simple, reliable, and effective way to secure file transfers in controlled environments. It doesn't replace encryption or authentication but serves as a complementary measure that gives you confidence your files haven't been tampered with.&lt;/p&gt;

</description>
      <category>fileintegrity</category>
      <category>sha256</category>
      <category>securefiletransfer</category>
      <category>datasecurity</category>
    </item>
  </channel>
</rss>
