Reputation: 3494
I have a document that is saying to Encrypted string using AES256
. According to my document with two value 10002:1486703720424 AND HashKey: hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF
it will generate the result 1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc=
but when i try to generate the result it is generating 6SKbqJAxbBrg4eU7r/B8gJoJEPg+KjMvGL5L7bfykUU=
from my code. Can you please tell what i am doing mistakes. This is the first time when i doing encryption so i am little bit confuse to find the my mistakes.
string getHashKey1 = EncryptText("10002:1486703720424", "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");
public string EncryptText(string input, string password)
{
string result = "";
try
{
// Get the bytes of the string
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
result = Convert.ToBase64String(bytesEncrypted);
}
catch (Exception ex)
{
ErrorLog errLog = new ErrorLog();
errLog.LogsWrite(ex, Path.GetDirectoryName(Application.ExecutablePath));
}
return result;
}
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
try
{
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
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();
}
}
}
catch (Exception ex)
{
ErrorLog errLog = new ErrorLog();
errLog.LogsWrite(ex, Path.GetDirectoryName(Application.ExecutablePath));
}
return encryptedBytes;
}
Upvotes: 1
Views: 1070
Reputation: 111810
Found... They are using ECB as the cypher mode, so no IV. I won't comment on the "security" of this. The padding seems to be PKCS7 (the default of AES). The password is used "as is", simply encoded in UTF8 (or perhaps even ASCII) (so it must be 32 bytes long).
public static string EncryptText(string input, string password)
{
// Get the bytes of the string
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string result = Convert.ToBase64String(bytesEncrypted);
return result;
}
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
using (MemoryStream ms = new MemoryStream())
{
using (Aes aes = Aes.Create())
{
aes.Key = passwordBytes;
aes.Mode = CipherMode.ECB;
// "zero" IV
aes.IV = new byte[16];
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
}
byte[] encryptedBytes = ms.ToArray();
return encryptedBytes;
}
}
@LukePark correctly made a tirade about this answer that is useful for the OP but useless in the greater world. I'll bold the correctly word. For this reason I'll explain what is "wrong" on the specification given to A. Goutam and what a "correct" specification must always contain.
A specification for encryption should always contain: the algorithm used (AES for example), the key size (if you say AES256 then clearly it is 256 bits), the block mode (CBC, ECB etc). Many block modes (CBC for example) require an IV vector. ECB has a lower security than other block modes (see for example https://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher). If the IV is necessary, then the specification must contain it (or explain how it should be generated). The specification must contain the padding that should be used. The Padding.None
should be used only if the data to be encrypted can be exactly subdivided in encryption blocks (so for example, with AES, PaddingMode.None
is good only if the data is 16, 32, 64, 96, ... bytes). PaddingMode.Zeros
is good only for text (and I wouldn't use it, because it will add '\0'
at the end of the text). The other padding modes are good.
Often the key isn't used "as is", because for example it is a string. The specification should contain how the encryption key must be derived from the string key. SHA256
on the key is a weak solution. Normally a good solution is using a strong key derivation function, like Rfc2898DeriveBytes
. If this function is used, the specification must contain the number of iteration and other informations about using Rfc2898DeriveBytes
or similar functions. Clearly what encoding should be used for the key (and for the data to be encrypted, if it is a text) must be included (UTF8
is always a good idea).
I'll add that a good specification should contain some test cases. At least one test case should be of length smaller than the encryption block and at least one test case must be of length greater than the encryption block but smaller than two encryption blocks (or > 2 and < 3... some complete blocks and one non-complete block). In this way you are testing both the PaddingMode
and the CipherMode
(note the should/must: by testing something bigger than an encryption block plus an incomplete block you are already testing everything)
Upvotes: 4