Skip to content

Instantly share code, notes, and snippets.

@elevine
Forked from beveradb/AES-CTR-256-Example.cs
Created April 14, 2016 20:00
Show Gist options
  • Save elevine/47f8365936eb595c4beaf46283570825 to your computer and use it in GitHub Desktop.
Save elevine/47f8365936eb595c4beaf46283570825 to your computer and use it in GitHub Desktop.
Example AES CTR 256 bit encryption with no IV in C#
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main(String[] args)
{
// Define string data to be encrypted - in this case this is an object encoded as a JSON string for convenience
string inputString = "{\"DeliveryDate\": \"2015-10-09\", \"CustomerId\": \"2548\", \"PodId\": \"254\"}";
// Get UTF8 byte array of input string for encryption
byte[] inputBytes = ASCIIEncoding.UTF8.GetBytes(inputString);
// Define string to use as symmetrical encryption key - this must be known at both ends to decrypt
string keyString = "ThisShouldBecomeA32ByteSecretKey";
// Again, get UTF8 byte array of key for use in encryption
byte[] keyBytes = ASCIIEncoding.UTF8.GetBytes(keyString);
// Initialize AES CTR (counter) mode cipher from the BouncyCastle cryptography library
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");
// Set cipher parameters to use the encryption key we defined above for encryption
// Since we are encrypting using the CTR mode / algorithm, the cipher is operating as a stream cipher.
// For perfect secrecy with a stream cipher, we should be generating a stream of pseudorandom characters called a keystream,
// then XOR'ing that with the plaintext. Instead, for convenience we are just XOR'ing the first [blocksize] bytes of null values.
// While convenient, as we only need a single key for two way encryption/decryption, this method is vulnerable to a simple known-plaintext attack
// As such, it should not be relied upon for true secrecy, only for security through obscurity.
cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", keyBytes), new byte[16]));
// As this is a stream cipher, you can process bytes chunk by chunk until complete, then close with DoFinal.
// In our case we don't need a stream, so we simply call DoFinal() to encrypt the entire input at once.
byte[] encryptedBytes = cipher.DoFinal(inputBytes);
// The encryption is complete, however we still need to get the encrypted byte array into a useful form for passing as a URL parameter
// First, we convert the encrypted byte array to a Base64 string to make it use ASCII characters
string base64EncryptedOutputString = Convert.ToBase64String(encryptedBytes);
Console.Write("\n" + base64EncryptedOutputString);
// Lastly, we replace the 2 characters from Base64 which are not URL safe ( + and / ) with ( - and _ ) as recommended in IETF RFC4648
string urlEncodedBase64EncryptedOutputString = base64EncryptedOutputString.Replace("+", "-").Replace("/", "_");
// This final string is now safe to be passed around, into our web service by URL, etc.
Console.Write("\n" + urlEncodedBase64EncryptedOutputString);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment