Signature Wizardry: Crafting MD5 Signatures with C#

Bala Madhusoodhanan - Aug 5 - - Dev Community

Intro

MD5 (Message Digest Algorithm 5) is a popular tool that creates a unique code (128-bit hash) for any given data. It’s often used to check if data has been changed during transmission by comparing these unique codes. MD5 is also used to create checksums for files, ensuring they haven’t been tampered with during transfers.

Many older systems were built to use MD5 because it was a common standard back then. These systems might not support newer hash functions without major updates. MD5 is still useful for basic checks to make sure data hasn’t been altered, which is enough for many older applications.

How does MD5 works

1) Sender: Generates MD5 hash of file.txt (e.g., d41d8cd98f00b204e9800998ecf8427e) and sends both the file and the hash.
2) Receiver: Receives file.txt and the hash. Generates its own MD5 hash of file.txt.
3) Verification: Compares the received hash with the generated hash.
If they match, the file is verified as intact. If they don’t match, the file is flagged as potentially corrupted.

Image description

Custom Code plugin for custom connector:

using System.IO;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net;
using System.Threading.Tasks;

public class Script : ScriptBase
{
    public override async Task<HttpResponseMessage> ExecuteAsync()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

        // Read the request body
        string requestBody = await this.Context.Request.Content.ReadAsStringAsync();
        Console.WriteLine($"Request Body: {requestBody}");
        var input = JsonConvert.DeserializeObject<InputPayload>(requestBody);

        // Check if plainText is provided
        if (string.IsNullOrEmpty(input.PlainText))
        {
            response.StatusCode = HttpStatusCode.BadRequest;
            response.Content = CreateJsonContent("{\"error\": \"String parameter is required.\"}");
            return response;
        }

        // Determine if MD5 should be used
        bool useMD5 = input.Key.Equals("MD5", StringComparison.OrdinalIgnoreCase);

        // Encrypt the plain text
        string encryptedText = useMD5 ? CreateMD5(input.PlainText) : Convert.ToBase64String(EncryptStringToBytes_Aes(input.PlainText, input.Key));

        // Log the plain text and encrypted text
        Console.WriteLine($"Plain Text: {input.PlainText}");
        Console.WriteLine($"Encrypted Text: {encryptedText}");

        // Create JSON response
        var jsonResponse = new
        {
            message = "The text has been encrypted.",
            encryptedText = encryptedText
        };

        response.Content = CreateJsonContent(JsonConvert.SerializeObject(jsonResponse));
        return response;
    }

    public static string CreateMD5(string input)
    {
        // Use input string to calculate MD5 hash
        using (MD5 md5 = MD5.Create())
        {
            byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));

            // Convert the byte array to hexadecimal string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("x2")); // Use "x2" for lowercase
            }

            return sb.ToString();
        }
    }

    static byte[] EncryptStringToBytes_Aes(string plainText, string key)
    {
        byte[] encrypted;
        byte[] Key = Encoding.UTF8.GetBytes(key);
        byte[] IV = new byte[16]; // Initialization vector with zeros

        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }

        return encrypted;
    }
}

public class InputPayload
{
    public string PlainText { get; set; }
    public string Key { get; set; }
}

Enter fullscreen mode Exit fullscreen mode

Magic show

Demo

When different systems need to communicate, using a common hash function like MD5 ensures that they can understand and verify each other’s data without compatibility issues.

Further Read:

OKTA - MD5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .