Why decrypting Persian text in AES256 remove some characters from the end? - c#

Want to encrypt and decrypt Persian text in C# (.net framework 8) it works fine in English alphabets but when I use Persian/Arabic text, some characters have been removed from the end of the result, what's wrong with my codes?
public class AES256
{
private static RijndaelManaged rijndaelManaged;
private static byte[] key, pwd, ivBytes, iv;
private enum EncryptMode { ENCRYPT, DECRYPT };
public static string Encrypt(string _plainText, string _key, string _initVector)
{
InitAES256();
return Process(_plainText, _key, EncryptMode.ENCRYPT, _initVector);
}
public static string Decrypt(string _encryptedText, string _key, string _initVector)
{
InitAES256();
return Process(_encryptedText, _key, EncryptMode.DECRYPT, _initVector);
}
private static void InitAES256()
{
rijndaelManaged = new RijndaelManaged();
rijndaelManaged.Mode = CipherMode.CBC;
rijndaelManaged.Padding = PaddingMode.PKCS7;
rijndaelManaged.KeySize = 256;
rijndaelManaged.BlockSize = 128;
key = new byte[32];
iv = new byte[rijndaelManaged.BlockSize / 8];
ivBytes = new byte[16];
}
private static string Process(string _inputText, string _encryptionKey, EncryptMode _mode, string _initVector)
{
string _out = string.Empty;
pwd = Encoding.UTF8.GetBytes(_encryptionKey);
ivBytes = Encoding.UTF8.GetBytes(_initVector);
int len = pwd.Length;
if (len > key.Length)
{
len = key.Length;
}
int ivLenth = ivBytes.Length;
if (ivLenth > iv.Length)
{
ivLenth = iv.Length;
}
Array.Copy(pwd, key, len);
Array.Copy(ivBytes, iv, ivLenth);
rijndaelManaged.Key = key;
rijndaelManaged.IV = iv;
if (_mode.Equals(EncryptMode.ENCRYPT))
{
byte[] plainText = rijndaelManaged.CreateEncryptor().TransformFinalBlock(Encoding.UTF8.GetBytes(_inputText), 0, _inputText.Length);
_out = Convert.ToBase64String(plainText);
}
else if (_mode.Equals(EncryptMode.DECRYPT))
{
byte[] plainText = rijndaelManaged.CreateDecryptor().TransformFinalBlock(Convert.FromBase64String(_inputText), 0, Convert.FromBase64String(_inputText).Length);
_out = Encoding.UTF8.GetString(plainText);
}
rijndaelManaged.Dispose();
return _out;
}
}
Using:
string initVector = "123";
string SyncGetKey = "2587";
string result = AES256.Encrypt("داود", SyncGetKey, initVector);
result = AES256.Decrypt(h, SyncGetKey, initVector);
The result is "دا" and "ود" has been removed from the end (as an example).

Related

How to upgrade from RijndaelManaged to AES?

I have a working solution for crypt/decrypt data in my code (below) but when I have upgraded the project to DOTNET6, RijndaelManaged becomes obsolete:
Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.'
and
SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'
Now I want to change that to Aes/RandomNumberGenerator as stated but want to keep the output in the same way as is. Unfortunately, I am not familiar with crypt/decrypt.
Can somebody help me to rewrite the current block to work with Aes instead - or at least help me how to change that and keep the public methods works in the same way?
Whole Code I have (it works as is)
using System.Security.Cryptography;
namespace MyApp;
internal static class AES
{
private static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new())
{
using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
return encryptedBytes;
}
private static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new())
{
using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
return decryptedBytes;
}
public static string EncryptText(string password, string salt = "MySecretSaltWhichIWantToKeepWorking")
{
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(password);
byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string result = Convert.ToBase64String(bytesEncrypted);
return result;
}
public static string DecryptText(string hash, string salt = "MySecretSaltWhichIWantToKeepWorking")
{
try
{
byte[] bytesToBeDecrypted = Convert.FromBase64String(hash);
byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string result = Encoding.UTF8.GetString(bytesDecrypted);
return result;
}
catch (Exception e)
{
return e.Message;
}
}
private const int SALT_BYTE_SIZE = 24;
private const int HASH_BYTE_SIZE = 24;
private const int PBKDF2_ITERATIONS = 1000;
private const int ITERATION_INDEX = 0;
private const int SALT_INDEX = 1;
private const int PBKDF2_INDEX = 2;
public static string PBKDF2_CreateHash(string password)
{
RNGCryptoServiceProvider csprng = new(); // This reports SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'
byte[] salt = new byte[SALT_BYTE_SIZE];
csprng.GetBytes(salt);
byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
return PBKDF2_ITERATIONS + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
}
public static bool PBKDF2_ValidatePassword(string password, string correctHash)
{
char[] delimiter = { ':' };
string[] split = correctHash.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
private static bool SlowEquals(byte[] a, byte[] b)
{
uint diff = (uint)a.Length ^ (uint)b.Length;
for (int i = 0; i < a.Length && i < b.Length; i++)
diff |= (uint)(a[i] ^ b[i]);
return diff == 0;
}
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
{
Rfc2898DeriveBytes pbkdf2 = new(password, salt)
{
IterationCount = iterations
};
return pbkdf2.GetBytes(outputBytes);
}
}
As far as I can tell, you should be able to replace
using RijndaelManaged AES = new();
with
using var AES = Aes.Create("AesManaged");
note that you might want to change your variable name to avoid naming conflicts or confusion.
The only difference between AES and Rijndael should be that Rijndael allows more blocksizes/keysizes. But you seem to be using 256 bit key and 128 bit blocks, and this should be allowed by AES.

Encrypt/Decrypt in Android Similar to C#

I'm looking for implementation of AES encryption in Java similar to what I wrote in C#. Here is my AES encryption in C#:
public class MyCrypto
{
private const string AesIV = #"1234567812345678";
private const string AesKey = #"4566789945667899";
public MyCrypto()
{
}
public String Encrypt(String txt)
{
return EncryptCBC(txt);
}
public String Decrypt(String txt)
{
return DecryptCBC(txt);
}
public static byte[] EncryptToBytesCBC(string toEncrypt)
{
byte[] src = Encoding.UTF8.GetBytes(toEncrypt);
byte[] dest = new byte[src.Length];
using (var aes = new AesCryptoServiceProvider())
{
aes.BlockSize = 128;
aes.KeySize = 128;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.Zeros;
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor(aes.Key, aes.IV))
{
return encrypt.TransformFinalBlock(src, 0, src.Length);
}
}
}
public static string EncryptCBC(string toEncrypt)
{
return Convert.ToBase64String(EncryptToBytesCBC(toEncrypt));
}
public static String DecryptToBytesCBC(byte[] toDecrypt)
{
byte[] src = toDecrypt;
byte[] dest = new byte[src.Length];
using (var aes = new AesCryptoServiceProvider())
{
aes.BlockSize = 128;
aes.KeySize = 128;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.Zeros;
// decryption
using (ICryptoTransform decrypt = aes.CreateDecryptor(aes.Key, aes.IV))
{
byte[] decryptedText = decrypt.TransformFinalBlock(src, 0, src.Length);
return Encoding.UTF8.GetString(decryptedText);
}
}
}
public static string DecryptCBC(string toDecrypt)
{
return DecryptToBytesCBC(Convert.FromBase64String(toDecrypt));
}
}
My android/java code is:
public String encrypt(String value)
{
String initVector = "1234567812345678";
String key = "4566789945667899";
String res = "";
try
{
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
res = android.util.Base64.encodeToString(encrypted,0);
}
catch (Exception ex)
{
Crashlytics.logException(ex);
}
return res;
}
but both (C# and Java) give me two different encryption result. I take my c# code as reference because this code consistent to our database encryption. Any help is highly appreciated. Thank you
To get the similar encryption result in java with C# code above, pls change this line
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
to this
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/ZeroBytePadding");

Padding is invalid and cannot be removed AES PKCS7

I am attempting to test a simple class to encrypt and decrypt data in C#.
`
{ [TestFixture]
public class CryptTest
{
[Test]
public void TestMethod()
{
String text = "Hello World!";
String crypt = EncryptionService.Encrypt(text, Config.KEY_STRING);
Console.WriteLine(crypt);
String clear = EncryptionService.Decrypt(crypt, Config.KEY_STRING);
Console.WriteLine(clear);
Assert.That(clear, Is.EqualTo(text));
}
`However, I am receiving the following exception:
Message: System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed.
with the stack:
StackTrace " at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)\r\n at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)\r\n at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n at System.IO.StreamReader.ReadBuffer()\r\n at System.IO.StreamReader.ReadToEnd()\r\n at InsuranceMidAm.Services.EncryptionService.Decrypt(String cipher, String key) in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm\\Services\\EncryptionService.cs:line 72\r\n at InsuranceMidAm.Tests.CryptTest.TestMethod() in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm.Tests\\CryptTest.cs:line 20" string
This is the class under test:
namespace InsuranceMidAm.Services
{
public class EncryptionService
{
// Reference: https://stackoverflow.com/questions/273452/using-aes-encryption-in-c-sharp
public static String Encrypt(String text, String key)
{
byte[] value = UTF8Encoding.UTF8.GetBytes(text);
byte[] crypt;
byte[] iv;
using (Aes myAes = Aes.Create())
{
myAes.KeySize = 256;
myAes.Mode = CipherMode.CBC;
myAes.Key = HexToBin(key);
myAes.GenerateIV();
myAes.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, myAes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(value, 0, value.Length);
cs.FlushFinalBlock();
crypt = ms.ToArray();
}
}
iv = myAes.IV;
myAes.Clear();
}
return ByteArrayToString(crypt) + ":" + ByteArrayToString(iv);
}
public static string Decrypt(String cipher, String key)
{
String outputString = "";
byte[] ivBytes = HexToBin(getIV(cipher));
byte[] valBytes = HexToBin(getSSN(cipher));
using (Aes myAes = Aes.Create())
{
int size = valBytes.Count();
myAes.KeySize = 256;
myAes.Mode = CipherMode.CBC;
myAes.Key = HexToBin(key);
myAes.IV = ivBytes;
myAes.Padding = PaddingMode.PKCS7;
char[] output = new char[256];
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(ivBytes))
{
using (CryptoStream cryptStream = new CryptoStream(memory, myDecrypter, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cryptStream))
{
outputString = reader.ReadToEnd();
}
return outputString;
}
}
}
}
private static byte[] HexToBin(String hexString)
{
int charCount = hexString.Length;
byte[] output = new byte[charCount / 2];
for (int i = 0; i < charCount; i += 2)
{
output[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return output;
}
private static String getSSN(String cipher)
{
int delimiterIndex = cipher.IndexOf(":");
String SSN = cipher.Substring(0, delimiterIndex);
return SSN;
}
private static String getIV(String cipher)
{
int delimiterIndex = cipher.IndexOf(":");
String IV = cipher.Substring(delimiterIndex + 1);
return IV;
}
// Reference: https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa
private static string ByteArrayToString(byte[] ba)
{
string hex = BitConverter.ToString(ba);
return hex.Replace("-", "");
}
}
}
Line 73 (where the exception is encountered) is the end of the using block for the StreamReader in the decrypt method:
using (StreamReader reader = new StreamReader(cryptStream))
{
outputString = reader.ReadToEnd();
}
I referenced the following question, but could not resolve my issue.
Originally, the data was encrypted in a PHP application, and decrypted using a C# application (using nearly exactly the same decrypt method above). Now, I am wanting to both encrypt and decrypt the data using C#; however, I must still be able to properly decrypt the existing data (that was encrypted using PHP), so I would rather not modify the decrypt method too much.
Any advice would be appreciated.
You have minor mistake here:
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(ivBytes))
You pass your IV value to decrypt, instead of actually encrypted bytes. Fix:
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(valBytes))

AES cbc padding encryption/decryption on cross platform (.net c# and codename one bouncy castle)

Encryption/Decryption won't work in cross platform.
I have used this link to encrypt/decrypt text using bouncy castle AES cipher within codename one.
AES Encryption/Decryption with Bouncycastle Example in J2ME
While from server side (.net) , i am using this link to implement same method.
http://zenu.wordpress.com/2011/09/21/aes-128bit-cross-platform-java-and-c-encryption-compatibility/
now i am not getting any error but encrypted from codename one will not getting fully decrypted on server side and vice a versa.
any one please help me out on this.
Code from Codename one:
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;
public class Test
{
private static PaddedBufferedBlockCipher cipher = null;
public static void main(String[] args)
{
try
{
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = new byte[16];
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
new CBCBlockCipher(
new AESEngine()) );
//Encryption
String plainText = "Hello How are you !2#&*()% 123456#";
byte[] plainData = plainText.getBytes("UTF-8");
KeyParameter keyParam = new KeyParameter(key);
CipherParameters ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(true, ivAndKey);
byte[] ciptherBytes = cipherData(plainData); //48
String cipherText = new String(Base64.encode(ciptherBytes), "UTF-8");//FileUtil.getStringFromByteArray(Base64.encode(ciptherBytes));
System.out.println("encrypted >> "+cipherText);
//Decryption
byte[] cipherData = Base64.decode(cipherText);
ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(false, ivAndKey);
plainText = new String(cipherData(cipherData), "UTF-8");//FileUtil.getStringFromByteArray(cipherData(cipherData));
System.out.println("decrypted >> "+plainText);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static byte[] cipherData(byte[] data)
throws CryptoException
{
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
Code from .net:
public static RijndaelManaged GetRijndaelManaged(String secretKey)
{
var keyBytes = new byte[16];
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
return new RijndaelManaged
{
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
KeySize = 128,
BlockSize = 128,
Key = keyBytes,
IV = keyBytes
};
}
public static byte[] EncryptCBC(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateEncryptor()
.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}
public static byte[] DecryptCBC(byte[] encryptedData, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateDecryptor()
.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
}
public static String EncryptCBCStr(String plainText, String key)
{
var plainBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(EncryptCBC(plainBytes, GetRijndaelManaged(key)));
}
public static String DecryptCBCStr(String encryptedText, String key)
{
var encryptedBytes = Convert.FromBase64String(encryptedText);
return Encoding.UTF8.GetString(DecryptCBC(encryptedBytes, GetRijndaelManaged(key)));
}
// call
var PlainText = "Hello How are you !2#&*()% 123456#";
var EncryptionKey = "MAKV2SPBNI992122";
var cypherCBC = EncryptCBCStr(PlainText, EncryptionKey);
var decryptCBC = DecryptCBCStr(cypherCBC, EncryptionKey);
Thanks in adv.
This issue has been fixed...it is just key/IV bytes issue.as in .net there is same key and IV when in java i have used different IV.
correction in java code:
instead of this
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = new byte[16];
use this.
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = "MAKV2SPBNI992122".getBytes("UTF-8");

what is algorithm hash with login control?

I use Login control and membership asp.net 4. and create user with passwrod = "12345678", my password hash in database is "h8A5hga0Cy93JsKxYnJl/U2AluU=" and passwordsalt is "UhVlqavmEX9CiKcUXkSwCw==".
Then I use this code for hash password in other project:
public string HashPassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = HashPassword("12345678", "UhVlqavmEX9CiKcUXkSwCw==");
}
textBox2.Text = "YM/JNwFqlL+WA3SINQp48BIxZRI=". But textBox2.Text != my password hashed with login control in database. it is "h8A5hga0Cy93JsKxYnJl/U2AluU=".
Edit:
It is algorithm hash with login control?
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
MD5 and SHA1 are not encryption algorithms. They are hashing algorithms.
It is a one way formula. Running MD5 or SHA1 on a particular string gives a hash that is always the same. It isn't possible to reverse the function to get back to the original string.
so, you can not decrypt.
if you want encrypt & decrypt, you can use below methods.
public class Encryption
{
private const string _defaultKey = "*3ld+43j";
public static string Encrypt(string toEncrypt, string key)
{
var des = new DESCryptoServiceProvider();
var ms = new MemoryStream();
VerifyKey(ref key);
des.Key = HashKey(key, des.KeySize / 8);
des.IV = HashKey(key, des.KeySize / 8);
byte[] inputBytes = Encoding.UTF8.GetBytes(toEncrypt);
var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputBytes, 0, inputBytes.Length);
cs.FlushFinalBlock();
return HttpServerUtility.UrlTokenEncode(ms.ToArray());
}
public static string Decrypt(string toDecrypt, string key)
{
var des = new DESCryptoServiceProvider();
var ms = new MemoryStream();
VerifyKey(ref key);
des.Key = HashKey(key, des.KeySize / 8);
des.IV = HashKey(key, des.KeySize / 8);
byte[] inputBytes = HttpServerUtility.UrlTokenDecode(toDecrypt);
var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputBytes, 0, inputBytes.Length);
cs.FlushFinalBlock();
var encoding = Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
/// <summary>
/// Make sure key is exactly 8 characters
/// </summary>
/// <param name="key"></param>
private static void VerifyKey(ref string key)
{
if (string.IsNullOrEmpty(key))
key = _defaultKey;
key = key.Length > 8 ? key.Substring(0, 8) : key;
if (key.Length < 8)
{
for (int i = key.Length; i < 8; i++)
{
key += _defaultKey[i];
}
}
}
private static byte[] HashKey(string key, int length)
{
var sha = new SHA1CryptoServiceProvider();
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] hash = sha.ComputeHash(keyBytes);
byte[] truncateHash = new byte[length];
Array.Copy(hash, 0, truncateHash, 0, length);
return truncateHash;
}
}
try
private static string CreateSalt()
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[32];
rng.GetBytes(buff);
//Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1");
return hashedPwd;
}
Login control doesn't encode or decode password. Instead, it is MembershipProvider's job.
Here is the Hash Algorithm used by new ASP.Net Universal Provider.
private static string GenerateSalt()
{
byte[] numArray = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(numArray);
string base64String = Convert.ToBase64String(numArray);
return base64String;
}
private string EncodePassword(string pass, int passwordFormat, string salt)
{
byte[] numArray;
byte[] numArray1;
string base64String;
bool length = passwordFormat != 0;
if (length)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] numArray2 = Convert.FromBase64String(salt);
byte[] numArray3 = null;
HashAlgorithm hashAlgorithm = HashAlgorithm.Create(Membership.HashAlgorithmType);
if (hashAlgorithm as KeyedHashAlgorithm == null)
{
numArray1 = new byte[(int) numArray2.Length + (int) bytes.Length];
Buffer.BlockCopy(numArray2, 0, numArray1, 0, (int) numArray2.Length);
Buffer.BlockCopy(bytes, 0, numArray1, (int) numArray2.Length, (int) bytes.Length);
numArray3 = hashAlgorithm.ComputeHash(numArray1);
}
else
{
KeyedHashAlgorithm keyedHashAlgorithm = (KeyedHashAlgorithm) hashAlgorithm;
if (keyedHashAlgorithm.Key.Length != numArray2.Length)
{
if (keyedHashAlgorithm.Key.Length >= (int) numArray2.Length)
{
numArray = new byte[(int) keyedHashAlgorithm.Key.Length];
int num = 0;
while (true)
{
length = num < (int) numArray.Length;
if (!length)
{
break;
}
int num1 = Math.Min((int) numArray2.Length, (int) numArray.Length - num);
Buffer.BlockCopy(numArray2, 0, numArray, num, num1);
num = num + num1;
}
keyedHashAlgorithm.Key = numArray;
}
else
{
numArray = new byte[(int) keyedHashAlgorithm.Key.Length];
Buffer.BlockCopy(numArray2, 0, numArray, 0, (int) numArray.Length);
keyedHashAlgorithm.Key = numArray;
}
}
else
{
keyedHashAlgorithm.Key = numArray2;
}
numArray3 = keyedHashAlgorithm.ComputeHash(bytes);
}
base64String = Convert.ToBase64String(numArray3);
}
else
{
base64String = pass;
}
return base64String;
}

Categories

Resources