AES Encrypted SSO

Passing information between one site and another is becoming more and more common but how can you do it without exposing confidential data?

Below are some examples of how you can encrypt text and then decrypt it on the other end.

C# to C#

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AES_Encryption.aspx.cs" Inherits="AES_Encryption" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>AES Text Encryption</title>
    <style type="text/css">
        .Label_Bold {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <p>
            <asp:Label runat="server" ID="lblGeneratedKey" Text="Generated Key" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblGeneratedKeyResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblPlainText" Text="Plain Text" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblPlainTextResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblUTCDTS" Text="UTC DateTime String" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblUTCDTSResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblEncrypted" Text="Encrypted String" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblEncryptedResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblDecryptionLink" Text="Decryption Link" CssClass="Label_Bold" /><br />
            <asp:HyperLink runat="server" ID="hlDecryptionLinkResult" />
        </p>
    </form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

#region Encryption Specific
using System.Text;
using System.Security.Cryptography;
#endregion Encryption Specific

public partial class AES_Encryption : System.Web.UI.Page
{
    private readonly byte[] Salt = new byte[] { 10, 20, 30, 40, 50, 60, 70, 80 };

    protected void Page_Load(object sender, EventArgs e)
    {
        int iKeySize = 256; // Can be 128, 192, or 256
        string sPlainText = "TestUser";
        string sDateTime = DateTime.UtcNow.ToString();
        string sSep = "rn";

        #region Generate Key
        // This should only get ran for a new project and not at every load of the page
        // string sKeyStr = GenerateKey(iKeySize);
        #endregion Generate Key

        string sKeyStr = "eWZwczQ2YUpCK0pEZ0NtZVRrQXB0UT09LHFNSE5DZmx0aVZKeEsyR2IxZWdsZjV1S25kSkZ3VkplS3gwbC9taHhNNVk9";

        lblGeneratedKeyResult.Text = sKeyStr;
        lblPlainTextResult.Text = sPlainText;
        lblUTCDTSResult.Text = sDateTime;

        string sEncryptedText = Encrypt(sPlainText + sSep + sDateTime, sKeyStr, iKeySize);

        lblEncryptedResult.Text = sEncryptedText;

        hlDecryptionLinkResult.Text = "AES_Decryption.aspx?ct=" + sEncryptedText;
        hlDecryptionLinkResult.NavigateUrl = hlDecryptionLinkResult.Text;

    }

    private string GenerateKey(int iKeySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = iKeySize;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.PKCS7;
        aesEncryption.GenerateIV();
        string ivStr = Convert.ToBase64String(aesEncryption.IV);
        aesEncryption.GenerateKey();
        string keyStr = Convert.ToBase64String(aesEncryption.Key);
        string completeKey = ivStr + "," + keyStr;

        return Convert.ToBase64String(ASCIIEncoding.UTF8.GetBytes(completeKey));
    }

    private string Encrypt(string iPlainStr, string iCompleteEncodedKey, int iKeySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = iKeySize;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.PKCS7;
        aesEncryption.IV = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(iCompleteEncodedKey)).Split(',')[0]);
        aesEncryption.Key = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(iCompleteEncodedKey)).Split(',')[1]);
        byte[] plainText = ASCIIEncoding.UTF8.GetBytes(iPlainStr);
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
        return Convert.ToBase64String(cipherText);
    }
}

Once you get to the destination machine you can setup rules/logic to make sure it’s a valid connection, in this example we are asking that the connection happen within a 4 minute range (2 minutes before or 2 minutes after UTC date time stamp).

NOTE: The sKeyStr on the host machine has to match the sKeyStr on the destination machine otherwise you will get an immediate failure.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AES_Decryption.aspx.cs" Inherits="AES_Decryption" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>AES Text Decryption</title>
    <style type="text/css">
        .Label_Bold {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <p>
            <asp:Label runat="server" ID="lblValid" Text="Decryption Results" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblValidResult" />
        </p>

        <p>
            <asp:Label runat="server" ID="lblDecrypted" Text="Decrypted String" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblDecryptedResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblDecryptedUsername" Text="Decrypted Username" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblDecryptedUsernameResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblDecryptedDateTime" Text="Decrypted DateTime" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblDecryptedDateTimeResult" />
        </p>
        <p>
            <asp:Label runat="server" ID="lblCDT2s" Text="Current DateTime with 2 minutes subtracted" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblCDT2sResult" />
        </p>

        <p>
            <asp:Label runat="server" ID="lblUTCDTS" Text="UTC DateTime String" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblUTCDTSResult" />
        </p>

        <p>
            <asp:Label runat="server" ID="lblCDT2a" Text="Current DateTime with 2 minutes added" CssClass="Label_Bold" /><br />
            <asp:Label runat="server" ID="lblCDT2aResults" />
        </p>
    </form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

#region Encryption Specific
using System.Text;
using System.Security.Cryptography;
#endregion Encryption Specific

public partial class AES_Decryption : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string sCipherText = Request.QueryString["ct"];
        DateTime dtCurrentDateTime = DateTime.UtcNow;
        int iKeySize = 256; // Can be 128, 192, or 256

        string[] sSep = new string[] { "rn" };

        string sKeyStr = "eWZwczQ2YUpCK0pEZ0NtZVRrQXB0UT09LHFNSE5DZmx0aVZKeEsyR2IxZWdsZjV1S25kSkZ3VkplS3gwbC9taHhNNVk9";

        try
        {
            string sDecryptedText = Decrypt(sCipherText, sKeyStr, iKeySize);

            lblDecryptedResult.Text = sDecryptedText;

            string[] sDecryptedValues = sDecryptedText.Split(sSep, StringSplitOptions.None);

            string sDecryptedUsername = sDecryptedValues[0];
            string sDecryptedDateTime = sDecryptedValues[1];

            lblDecryptedUsernameResult.Text = sDecryptedUsername;

            lblDecryptedDateTimeResult.Text = sDecryptedDateTime;

            #region DateTime Logic

            // If the decrypted DateTime is not within two minutes plus or minus, reject the pass-through

            lblCDT2sResult.Text = dtCurrentDateTime.AddMinutes(-2).ToString();

            lblUTCDTSResult.Text = dtCurrentDateTime.ToString();

            lblCDT2aResults.Text = dtCurrentDateTime.AddMinutes(2).ToString();

            DateTime dtDate = DateTime.Parse(sDecryptedDateTime);
            if (dtDate <= dtCurrentDateTime.AddMinutes(2) && dtDate >= dtCurrentDateTime.AddMinutes(-2))
            {
                lblValidResult.Text = "Proper Timing";
            }
            else
            {
                lblValidResult.Text = "Bad Timing";
            }
            #endregion DateTime Logic
        }
        catch (Exception ex)
        {
            lblValidResult.Text = "Problem with decryption<br/>" + ex.Message;
        }
    }

    private string Decrypt(string iEncryptedText, string iCompleteEncodedKey, int iKeySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = iKeySize;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.PKCS7;
        aesEncryption.IV = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(iCompleteEncodedKey)).Split(',')[0]);
        aesEncryption.Key = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(iCompleteEncodedKey)).Split(',')[1]);
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
        byte[] encryptedBytes = Convert.FromBase64CharArray(iEncryptedText.ToCharArray(), 0, iEncryptedText.Length);
        return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length));
    }
}
All information on this site is shared with the intention to help. Before any source code or program is ran on a production (non-development) system it is suggested you test it and fully understand what it is doing not just what it appears it is doing. I accept no responsibility for any damage you may do with this code.