Password Encryption/Decryption Code in .Net

Password encryption/decryption code in .NET

Here you go. I found it somewhere on the internet. Works well for me.

    /// <summary>
/// Encrypts a given password and returns the encrypted data
/// as a base64 string.
/// </summary>
/// <param name="plainText">An unencrypted string that needs
/// to be secured.</param>
/// <returns>A base64 encoded string that represents the encrypted
/// binary data.
/// </returns>
/// <remarks>This solution is not really secure as we are
/// keeping strings in memory. If runtime protection is essential,
/// <see cref="SecureString"/> should be used.</remarks>
/// <exception cref="ArgumentNullException">If <paramref name="plainText"/>
/// is a null reference.</exception>
public string Encrypt(string plainText)
{
if (plainText == null) throw new ArgumentNullException("plainText");

//encrypt data
var data = Encoding.Unicode.GetBytes(plainText);
byte[] encrypted = ProtectedData.Protect(data, null, Scope);

//return as base64 string
return Convert.ToBase64String(encrypted);
}

/// <summary>
/// Decrypts a given string.
/// </summary>
/// <param name="cipher">A base64 encoded string that was created
/// through the <see cref="Encrypt(string)"/> or
/// <see cref="Encrypt(SecureString)"/> extension methods.</param>
/// <returns>The decrypted string.</returns>
/// <remarks>Keep in mind that the decrypted string remains in memory
/// and makes your application vulnerable per se. If runtime protection
/// is essential, <see cref="SecureString"/> should be used.</remarks>
/// <exception cref="ArgumentNullException">If <paramref name="cipher"/>
/// is a null reference.</exception>
public string Decrypt(string cipher)
{
if (cipher == null) throw new ArgumentNullException("cipher");

//parse base64 string
byte[] data = Convert.FromBase64String(cipher);

//decrypt data
byte[] decrypted = ProtectedData.Unprotect(data, null, Scope);
return Encoding.Unicode.GetString(decrypted);
}

Encrypt and Decrypt password

In the URL there are come characters that conflict with the encrypted output, and at least on my code, this is what make the problem. So I use this two functions to change this characters and avoid that.

public static string ChangeSPChart(string sTheInput)
{
StringBuilder sRetMe = new StringBuilder(sTheInput);

sRetMe.Replace('+', '-');
sRetMe.Replace('/', '*');
sRetMe.Replace('=', '!');

return sRetMe.ToString();
}

public static string FixSPChart(string sTheInput)
{
StringBuilder sRetMe = new StringBuilder(sTheInput);

sRetMe.Replace('-', '+');
sRetMe.Replace('*', '/');
sRetMe.Replace('!', '=');

return sRetMe.ToString();
}

and the encryption/decryption code will be:

public static string Encrypt(string toEncrypt, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
// Get the key from config file
string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
//System.Windows.Forms.MessageBox.Show(key);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);

TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;

ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

tdes.Clear();
var encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);

// here I change it
return ChangeSPChart(encrypted);
}
/// <summary>
/// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
/// </summary>
/// <param name="cipherString">encrypted string</param>
/// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
/// <returns></returns>
public static string Decrypt(string cipherString, bool useHashing)
{
cipherString = FixSPChart(cipherString);

byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(cipherString);

System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
//Get your key from config file to open the lock!
string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));

if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);

TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;

ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

tdes.Clear();
return UTF8Encoding.UTF8.GetString(resultArray);
}

C# - Looking for Encryption/Decryption Method

You should not be using RtlEncryptMemory if you want to store the string, it is meant to only keep strings secure inside the running applications memory, it therefore can be stored/serialized and decrypted.

Have a look at DPAPI password encryption I think it should meet your needs.

C#.net to Java- Encryption and decryption using AES with Password

Rfc2898DeriveBytes implements PBKDF2, and RijndaelManaged with a block size of 128 bits implements AES. Both seem to be applied correctly in the Java code.

However, there are differences in determining the IV and regarding concatenation: In the C# code, the salt and IV are determined randomly and concatenated with the ciphertext at the end.

In the Java code only the salt is determined randomly, the IV is derived together with the key and the concatenation is missing.

I.e. the encrypt() method in the Java code could be changed for instance as follows, so that a decryption with the C# code is possible:

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

...

byte[] salt = Generate128BitsOfRandomEntropy();
byte[] iv = Generate128BitsOfRandomEntropy();

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec pbeKeySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, 1000, 128);
SecretKey secretKey = factory.generateSecret(pbeKeySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");

AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] ciphertext = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

byte[] saltIvCiphertext = ByteBuffer.allocate(salt.length + iv.length + ciphertext.length).put(salt).put(iv).put(ciphertext).array();
return Base64.getEncoder().encodeToString(saltIvCiphertext);

Note that for PBKDF2, an iteration count of 1000 is generally too low.

Java to C#.net - Encryption and decryption using AES with Password

The two methods:

public static byte[] EncryptionToBytes(string str)
{
using (var aes = new AesManaged())
{
aes.Key = new byte[] { 0x72, 0x8f, 0xaf, 0x34, 0xb6, 0x4c, 0xd5, 0x5c, 0x8d, 0x1d, 0x50, 0x02, 0x68, 0x02, 0x6f, 0xfb };
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;

using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] data = Encoding.UTF8.GetBytes(str);
cs.Write(data, 0, data.Length);
}

byte[] encrypted = ms.ToArray();
return encrypted;
}
}
}

public static string DecryptionFromBytes(byte[] encrypted)
{
using (var aes = new AesManaged())
{
aes.Key = new byte[] { 0x72, 0x8f, 0xaf, 0x34, 0xb6, 0x4c, 0xd5, 0x5c, 0x8d, 0x1d, 0x50, 0x02, 0x68, 0x02, 0x6f, 0xfb };
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;

using (var ms2 = new MemoryStream())
{
using (var ms = new MemoryStream(encrypted))
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
cs.CopyTo(ms2);
}

byte[] decrypted = ms2.ToArray();
return Encoding.UTF8.GetString(decrypted);
}
}
}

Note that

System.out.println("Encrypted: " + encrypted);

won't print the byte[], but will print [, followed by a character representing the type of the array's elements (in your case C for char), followed by @ then the "identity hash code" of the array (think of it like you would a "memory address").

Java seems to use (haven't looked for documentation) AES with mode ECB, padding PKCS7 (this confirms my observation)

Note that String.getBytes() encodes using the "default" encoding, that could be different in different computers. Better to use getBytes("UTF-8") and new String(bytes, "UTF-8") (see https://stackoverflow.com/a/5729823/613130). In the code I wrote I used UTF8. You can simulate the Java code by using Encoding.Default.



Related Topics



Leave a reply



Submit