Skip to content

Instantly share code, notes, and snippets.

@muhaisen
Created March 13, 2021 11:10
Show Gist options
  • Save muhaisen/cd9875c88a18f80c0dec1fb665f00543 to your computer and use it in GitHub Desktop.
Save muhaisen/cd9875c88a18f80c0dec1fb665f00543 to your computer and use it in GitHub Desktop.
Decrypts Salesforce encryptWithManagedIV using C#
using Newtonsoft.Json;
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
namespace ManagedAES
{
/// <summary>
/// Decrypts Salesforce Apex encryptWithManagedIV
/// </summary>
public class ManagedAESDecryptor
{
public static void Decrypt()
{
using (AesManaged myAes = new AesManaged())
{
// Decoded externally
var protected_string = "W+YnphJ2T8pH4X+FNTwZvFPab+R4wRbZg/6HuyZ8Ese15LYp1UJLs7HvmIco4w6A";
byte[] protected_bytes = RetrieveCipher(protected_string);
// Encryption key
var encrption_key = Convert.FromBase64String(Constants.s_encrption_key);
// IV
var byte_IV = RetrieveIv(protected_string);
// Decrypt the bytes to a string.
string plan_text = DecryptStringFromBytes_Aes(protected_bytes, encrption_key, byte_IV);
// To User information object
UserInfo user_info = JsonConvert.DeserializeObject<UserInfo>(plan_text);
Console.WriteLine(user_info.MAIL);
}
}
/// <summary>
/// Returns the IV needed for decryption. 16 Bytes
/// </summary>
/// <param name="base64_cipher_text"></param>
/// <returns></returns>
public static byte[] RetrieveIv(string base64_cipher_text)
{
// Just 16 the first bytes
// 16 not divisable by 3 (4 characters per 3 bytes)
// 4 -> 3
// ?? 18
// (4 * 18) / 3 = 24
// This will be 18 bytes long
base64_cipher_text = base64_cipher_text.Substring(0, 24);
// 18 bytes long
byte[] cipher_binary = Convert.FromBase64String(base64_cipher_text);
byte[] iv = new byte[16];
// Take first 16 only and discard the left
Array.Copy(cipher_binary, 0, iv, 0, 16);
return iv;
}
/// <summary>
/// Retivers the cipher text without the IV
/// </summary>
/// <param name="base64_cipher_text"></param>
/// <returns></returns>
public static byte[] RetrieveCipher(string base64_cipher_text)
{
byte[] cipher_binary = Convert.FromBase64String(base64_cipher_text);
var length = cipher_binary.Length - 16;
byte[] cipher_only = new byte[length];
Array.Copy(cipher_binary, 16, cipher_only, 0, length);
return cipher_only;
}
/// <summary>
/// Decrypts the cipher text.
/// </summary>
/// <param name="cipherText"></param>
/// <param name="Key"></param>
/// <param name="IV"></param>
/// <returns></returns>
static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an AesCryptoServiceProvider object
// with the specified key and IV.
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment