Let's say I need to do this in Powershell:
    $SecurePass = Get-Content $CredPath | ConvertTo-SecureString -Key (1..16)
    [String]$CleartextPass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($CredPass));
The content of $CredPath is a file that contains the output of ConvertFrom-SecureString -Key (1..16).
How do I accomplish the ConvertTo-SecureString -key (1..16) portion in C#/.NET? 
I know how to create a SecureString, but I'm not sure how the encryption should be handled. 
Do I encrypt each character using AES, or decrypt the string and then create a the secure string per character?
I know next to nothing about cryptography, but from what I've gathered I might just want to invoke the Powershell command using C#.
For reference, I found a similar post about AES encryption/decryption here: Using AES encryption in C#
UPDATE
I have reviewed the link Keith posted, but I face additional unknowns. The DecryptStringFromBytes_Aes takes three arguments:
static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
The first argument is a byte array represents the encrypted text. The question here is, how should the string be represented in the byte array? Should it be represented with or without encoding?
byte[] ciphertext = Encoding.ASCII.GetBytes(encrypted_text);
byte[] ciphertext = Encoding.UTF8.GetBytes(encrypted_text);
byte[] ciphertext = Encoding.Unicode.GetBytes(encrypted_text);    
byte[] ciphertext = new byte[encrypted_password.Length * sizeof(char)];
System.Buffer.BlockCopy(encrypted_password.ToCharArray(), 0, text, 0, text.Length);
The second byte array is the key should simply be an array of integers:
byte[] key = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
The third byte array is an "Initialization Vector" - it looks like the Aes.Create() call will generate a byte[] for IV randomly. Reading around, I've found that I might need to use the same IV. As ConvertFrom-SecureString and ConvertTo-SecureString are able to encrypt/decrypt using simply the key, I am left with the assumption that the IV[] can be random -or- has a static definition.
I have not yet found a winning combination, but I will keep trying.
Description. The ConvertTo-SecureString cmdlet converts encrypted standard strings into secure strings. It can also convert plain text to secure strings. It is used with ConvertFrom-SecureString and Read-Host .
In PowerShell, there are a number of cmdlets that work with something called a secure string. When you create a saved credential object, the password is stored as a secure string.
SecureString is a string type that provides a measure of security. It tries to avoid storing potentially sensitive strings in process memory as plain text.
PowerShell Commands Used ConvertTo-SecureString - Decrypt data. Read-Host - Read input as a secure string. RNGCryptoServiceProvider. GetBytes - RNGCryptoServiceProvider's GetBytes method will be used to create an encryption key which will be used for encryption and decryption.
I know this is an old post. I am posting this for completeness and posterity, because I couldn't find a complete answer on MSDN or stackoverflow. It will be here in case I ever need to do this again.
It is a C# implementation of of powershell's ConvertTo-SecureString with AES encryption (turned on by using the -key option). I will leave it for exercise to code a C# implementation of ConvertFrom-SecureString.
# forward direction
[securestring] $someSecureString = read-host -assecurestring
[string] $psProtectedString = ConvertFrom-SecureString -key (1..16) -SecureString $someSecureString
# reverse direction
$back = ConvertTo-SecureString -string $psProtectedString -key (1..16)
My work is combining answers and re-arranging user2748365's answer to be more readable and adding educational comments! I also fixed the issue with taking a substring -- at the time of this post, his code only has two elements in strArray.
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Globalization;
// psProtectedString - this is the output from
//   powershell> $psProtectedString = ConvertFrom-SecureString -SecureString $aSecureString -key (1..16)
// key - make sure you add size checking 
// notes: this will throw an cryptographic invalid padding exception if it cannot decrypt correctly (wrong key)
public static SecureString ConvertToSecureString(string psProtectedString, byte[] key)
{
    // '|' is indeed the separater
    byte[] asBytes = Convert.FromBase64String( psProtectedString );
    string[] strArray = Encoding.Unicode.GetString(asBytes).Split(new[] { '|' });
    if (strArray.Length != 3) throw new InvalidDataException("input had incorrect format");
    // strArray[0] is a static/magic header or signature (different passwords produce
    //    the same header)  It unused in our case, looks like 16 bytes as hex-string
    // you know strArray[1] is a base64 string by the '=' at the end
    //    the IV is shorter than the body, and you can verify that it is the IV, 
    //    because it is exactly 16bytes=128bits and it decrypts the password correctly
    // you know strArray[2] is a hex-string because it is [0-9a-f]
    byte[] magicHeader = HexStringToByteArray(encrypted.Substring(0, 32));
    byte[] rgbIV = Convert.FromBase64String(strArray[1]);
    byte[] cipherBytes = HexStringToByteArray(strArray[2]);
    // setup the decrypter
    SecureString str = new SecureString();
    SymmetricAlgorithm algorithm = SymmetricAlgorithm.Create();
    ICryptoTransform transform = algorithm.CreateDecryptor(key, rgbIV);
    using (var stream = new CryptoStream(new MemoryStream(cipherBytes), transform, CryptoStreamMode.Read))
    {
        // using this silly loop format to loop one char at a time
        // so we never store the entire password naked in memory
        int numRed = 0;
        byte[] buffer = new byte[2]; // two bytes per unicode char
        while( (numRed = stream.Read(buffer, 0, buffer.Length)) > 0 )
        {
            str.AppendChar(Encoding.Unicode.GetString(buffer).ToCharArray()[0]);
        }
    }
    //
    // non-production code
    // recover the SecureString; just to check
    // from http://stackoverflow.com/questions/818704/how-to-convert-securestring-to-system-string
    //
    IntPtr valuePtr = IntPtr.Zero;
    string secureStringValue = "";
    try
    {
        // get the string back
        valuePtr = Marshal.SecureStringToGlobalAllocUnicode(str);
        secureStringValue = Marshal.PtrToStringUni(valuePtr);
    }
    finally
    {
        Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
    }
    return str;
}
// from http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa
public static byte[] HexStringToByteArray(String hex)
{
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];
    for (int i = 0; i < NumberChars; i += 2) bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    return bytes;
}
public static SecureString DecryptPassword( string psPasswordFile, byte[] key )
{
    if( ! File.Exists(psPasswordFile)) throw new ArgumentException("file does not exist: " + psPasswordFile);
    string formattedCipherText = File.ReadAllText( psPasswordFile );
    return ConvertToSecureString(formattedCipherText, key);
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With