ASP MVC: E-mail Verification (Encrypting the activation link) - c#

Okay i'm a little bit stuck on how to solve this problem.
When a user registers. I want to send him a link so that he can verify hes email address.
But i have troubles generating the link.
I've already written the controller to accept the links with the correct keys. i only have no idea on how to generate the activation keys.
So when the user registers i'll send him a link by mail like this:
Your activation link is : http://site.com/user/verify?key=keyhere
Now i have created this method (called by the controller/action) to handle the key in the link:
public string Verify(string value)
{
String email = Decrypt(value);
user u = gebRep.GetUsers().WithEmail(email).SingleOrDefault();
if (u != null)
{
u.emailValid = true;
userReppository.Save();
}
return "Invallid validation value!";
}
Now my problem is I have no idea on how to encrypt and decrypt the email into some sort of key (url friendly) So i can mail it with the link and can use it to verify the email.
I need some kind of (not to complicated but secure) way to encrypt the email into a urlfriendly key.
Tyvm

You could use something like Rijndael encryption to encrypt the user's e-mail address as the verification key, then when they click the link you simply decrypt the verification code with your private encryption key to retrieve the e-mail address and activate the appropriate user. With this technique you would not need to store any extra data about the user for account activation and you'd still have an encrypted, very hard to guess value as the verification code.
Here's an example of Rijndael encryption with C#.
In case you aren't familiar with it, with Rijndael encryption you have a private key that only you know, which is used as the encryption key for your data. So long as you know the encryption key you can always decrypt whatever you have encrypted.
The additional beauty of this technique is that it also makes it easy to have an expiring link. Say for example you want a 24 hour password reset link, so you send the user a link with a verification code in it, but rather than storing data about the verification code and its expiration date in your system, encrypt the user's e-mail and an expiration date and send that as the verification code. So basically, you could encrypt a value like, 1272746267|14 where first part is the link expiration timestamp and the second value is the user's ID in the system. Upon decrypting and parsing out the timestamp you can make the decision right there whether or not the link is still valid. The only drawback I see to this approach is possibly the length of the encrypted string, but seeing as you're sending it in an e-mail that shouldn't matter too much.
Here's a quick example:
Key: a1b2c3d4e5f6h7i8
Value: 1272746267|14
Encrypted: wxtVC1u5Q7N9+FymCln3qA==
Decrypted: 1272746267|14
Be sure to throw a Url.Encode() on the encrypted value before linking it, as it can contain some unfriendly characters like slashes.

It may easier to not use any encryption and make things a bit more simple.
Create a new Guid for the link (and save this with the user) then just verify the user when the link is called

The way I would do this is simply generate a largish-random number for the "key" and then store a mapping in your database between activation key and email.

This is what I use. Short and easy.
private string GetNewValidationCode()
{
long i = 1;
foreach (byte b in Guid.NewGuid().ToByteArray())
{
i *= ((int)b + 1);
}
return string.Format("{0:x}", i - DateTime.Now.Ticks);
}
Result looks like this: 8e85a8a078884bbc

Encrypt, Decrypt using AES. Please find example below:
class AesExample
{
public static void Main()
{
try
{
string original = "Here is some data to encrypt!";
// Create a new instance of the AesManaged
// class. This generates a new key and initialization
// vector (IV).
using (AesManaged myAes = new AesManaged())
{
// Encrypt the string to an array of bytes.
string encrypted = EncryptPasswordAes(original, myAes.Key, myAes.IV);
// Decrypt the bytes to a string.
string roundtrip = DecryptPasswordAes(encrypted, myAes.Key, myAes.IV);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Encrypted: {0}", encrypted);
Console.WriteLine("Round Trip: {0}", roundtrip);
Console.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
}
static string EncryptPasswordAes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return Convert.ToBase64String(encrypted);
}
static string DecryptPasswordAes(string encryptedString, byte[] Key, byte[] IV)
{
//Convert cipher text back to byte array
byte[] cipherText = Convert.FromBase64String(encryptedString);
// Byte[] cipherText = System.Text.Encoding.UTF8.GetBytes(encryptedString);
// 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("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor 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;
}
}

Related

how many bits generate aes.create() method in C#

I'm actually trying to make a secure file transfer program
and I would like to encrypt the sent file with the c# Aes.Create() method
but I wanted a AES-256 encryption and I'm not sure that the method does a 256 bits key
so I searched on Microsoft docs and many sketchy websites but I did find nothing.
So, how many bits generate Aes.Create()?
There is my code:
using System.Security.Cryptography;
namespace ConsoleApp1
{
internal class Program
{
public static void Main()
{
string original = File.ReadAllText(#"C:\SomePath");
// Create a new instance of the Aes
// class. This generates a new key and initialization
// vector (IV).
using (Aes myAes = Aes.Create())
{
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Encrypted: {0}", System.Text.Encoding.Default.GetString(encrypted));
Console.WriteLine("Round Trip: {0}", roundtrip);
}
}
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
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 Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
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;
}
}
}
Yes, it's a modified version of Microsoft docs on Aes class: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes
AES is a block cipher. That means it encrypts a fixed-sized block of clear text bytes into a same-sized block of cipher text bytes (hence the term block cipher). AES uses 128-bit blocks, i.e. 16 bytes long. This is irrespective of key size.
To be able to encrypt data of an arbitrary length, block ciphers use different modes of operation. Depending on the mode, padding is applied, an initialization vector may be used, salt prepended, and dependencies between blocks are employed.
Hence, as a result, the total size of encrypted data may be slightly bigger than the original size of the unencrypted data. The difference accounts for (at least) the length of the initialization vector and/or salt and any padding to the nearest multiple of the cipher's block size.

How to create Aes 256bit Encryption with key in C# Windows Phone application?

I'm trying to create Aes 256bit Encryption with key in login screen. I need a large encrypted string as i'm using 256bit But it result in small encrypted string.I have checked many samples But all are for Windows desktop application not for windows Phone application. Please help regarding this.
This is my code
namespace SampleEncription
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
byte[] encryptedPassword;
// Create a new instance of the RijndaelManaged
// class. This generates a new key and initialization
// vector (IV).
using (var algorithm = new AesManaged())
{
algorithm.KeySize = 256;
algorithm.BlockSize = 128;
// Encrypt the string to an array of bytes.
encryptedPassword = Cryptology.EncryptStringToBytes("Password", algorithm.Key, algorithm.IV);
//string chars = encryptedPassword.Aggregate(string.Empty, (current, b) => current + b.ToString());
string chars = System.Convert.ToBase64String(encryptedPassword);
Debug.WriteLine(chars);
}
}
}
}
one another class named cryptology:
namespace SampleEncription
{
class Cryptology
{
private const string Salt = "603deb1015ca71be2b73aef0857d7781";
private const int SizeOfBuffer = 1024 * 8;
internal static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
{
throw new ArgumentNullException("plainText");
}
if (key == null || key.Length <= 0)
{
throw new ArgumentNullException("key");
}
if (iv == null || iv.Length <= 0)
{
throw new ArgumentNullException("key");
}
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new AesManaged())
{
rijAlg.Key = key;
rijAlg.IV = iv;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
}
}
instead of
string chars = System.Convert.ToBase64String(encryptedPassword);
do this
Encoding.UTF8.GetString(encryptedPassword, 0, encryptedPassword.Length);
I think wp8 doesn't allow you to use System.Text.Encoding.Default.GetString, you can try to default it to UTF8, which i assume that the cipher text are all in latin characters..
You forgot to flush :)
You are calling encrypted = msEncrypt.ToArray(); before closing and therefore flushing the CryptoStream. As the final block needs to be padded, not all bytes will have been written. If you use a block cipher mode of encryption or an authenticated cipher, it is always required to flush. Only stream cipher modes of encryption may not require you to flush the stream as each bit can be encryption separately.
In your implementation, you should be able to just move msEncrypt.ToArray() below the using scope of the CryptoStream, if I'm not mistaken.

Encrypt in C# and decrypt using Apex

I want to pass a field in the query string from asp .net to Apex . I want to encrypt the value of the field and then pass it in the query string.
I am not sure how to approach this, are there any example code /links for same ?
Basically i want to encrypt in C# and decrypt using Apex.
In C#
static string key = "eU5WzoFgU4n8Apu5PYxcNGRZswRDZJWDEMdbQVU85gw=";
static string IV = "9ehY9gYtfIGlLRgwqg6F2g==";
static void Main(string[] args)
{
string source = "test";
string encrypted = EncryptStringToBytes_Aes(source, Convert.FromBase64String(key), Convert.FromBase64String(IV));
Console.ReadLine();
}
static string EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
string encrypted;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = Convert.ToBase64String(msEncrypt.ToArray());// ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
In Apex:
string cryptoKey='eU5WzoFgU4n8Apu5PYxcNGRZswRDZJWDEMdbQVU85gw=';
String det= System.currentPageReference().getParameters().get('Det');
Blob decryptedData = Crypto.decryptWithManagedIV('AES256', EncodingUtil.base64Decode(cryptoKey), EncodingUtil.base64Decode(det));
But this doesn't work, decryptedData.toString() does not come as 'test' (the original text). How do i decrypt it back ?
Why? All communication with SF is done via SSL anyway (https://salesforce.stackexchange.com/questions/8273/data-loader-cli-and-encryption for example).
If you absolutely have to - Apex has Crypto class that supports several algorithms. Hopefully you'll find matching ones in C# libraries.
There's also EncodingUtil class if you need to pass some binary data (as base64 for example).
The person who created the above example was VERY close. They probably would have realized it if they had encrypted a longer string than "Test" -- they just needed to insert some padding in front of what they were encrypting:
string spadding = "paddingxxxxxxxxx";
string source = spadding + "Opportunity0065";
-- Output would have been "Opportunity0065"

Why RijndaelManaged returns junk data after encryption?

I have taken the decrypt code from http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.aspx and modified it as follows below. I have an encrypted example, and it works just fine while decoding. But when using the encryption function, it returns junk string with strange symbols. below are the functions of encrypt/decrypt.
An example of encrypted string "hey" : "???U?b???z?Y???"
When decoded again: "ûc{ÁpÅ`ñ""Â"
I'm using this code to convert the byte array to string:
private string ByteArrayToString(byte[] input)
{
ASCIIEncoding dec = new ASCIIEncoding();
return dec.GetString(input);
}
here are the encrypt/decrypt functions. the decryption function is working fine.
private string DecryptStringFromBytesAes(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");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = Key;
aesAlg.Padding = PaddingMode.Zeros;
aesAlg.Mode = CipherMode.ECB;
// Create a decrytor 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;
}
private byte[] EncryptStringToBytesAes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = Key;
aesAlg.Padding = PaddingMode.Zeros;
aesAlg.Mode = CipherMode.ECB;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
What you observe is the problem of mapping arbitrary bytes (in the range 0-255) to characters. Meaningful characters are only in the range 32-255 or even only 32-127 (ASCII). Values below 32 are the so-called non-printable characters and values above 127 are dependent on the character encoding you are using. That's why the crypted text looks like junk. Mast crypto-systems therefore transform the bytes into the sensible ASCII-range. One such algorithm is BASE64. So mangling the crypted bytes through BASE64 gives characters that are all printable and that will go without problems through e-mail. Before decrypting you then have to undo the BASE64 encoding.
Another way to make the encrypted result look better is to show the hexa-decimal representation of it. For example if you have a byte value of 15 you print 0F. You may use this to represent your byte array in hex:
private string ByteArrayToHexString(byte[] data)
{
return String.Concat(data.Select(b => b.ToString("x2")));
}
In order to have your output as a hexadecimal encoding of the data, follow the methods found here. I modified them slightly to be extension methods:
public static string ToHexString(this byte[] bytes)
{
return bytes == null ? string.Empty : BitConverter.ToString(bytes).Replace("-", string.Empty);
}
public static byte[] FromHexString(this string hexString)
{
if (hexString == null)
{
return new byte[0];
}
var numberChars = hexString.Length;
var bytes = new byte[numberChars / 2];
for (var i = 0; i < numberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return bytes;
}
Encrypted strings will look like garble. The way to test if the encryption is working correctly is to pass your string back through decrypt. If it works at decrypting then you know the string is correct despite looking like garbage to you.

Rijndael: same string, different results

We had a small desktop app that needs to be provided as a web feature now (.Net). This app contains some code for encryption and uses Rijndael classes from .Net framework. The code accepts an input string, encrypts it and writes it out the results to a file. Since all the code is contained in one class, I just copied the class to my web service application. When I encrypt the same string, using the same key, in the original app and the new app, the results are different.
The result string given by the original app is a subset of the result string given by my web service. The latter has additional characters at the end of the encrypted string.
Below is the code I am using. Please note that I did not develop this code nor do I understand it fully. Any thoughts on the difference in behaviour? Please help!!
Here is the code that gets the user input and calls the encryptor.
public void EncryptDomain(string EncryptValue, string outputDomainFile)
{
if (EncryptValue.Length > 0)
{
if ((outputDomainFile != null) && (outputDomainFile.Length > 0))
{
_outputDomainFile = outputDomainFile;
}
byte[] input = Encoding.UTF8.GetBytes(EncryptValue);
Transform(input, TransformType.ENCRYPT);
}
This is the encryptor code:
private byte[] Transform(byte[] input, TransformType transformType)
{
CryptoStream cryptoStream = null; // Stream used to encrypt
RijndaelManaged rijndael = null; // Rijndael provider
ICryptoTransform rijndaelTransform = null;// Encrypting object
FileStream fsIn = null; //input file
FileStream fsOut = null; //output file
MemoryStream memStream = null; // Stream to contain data
try
{
// Create the crypto objects
rijndael = new RijndaelManaged();
rijndael.Key = this._Key;
rijndael.IV = this._IV;
rijndael.Padding = PaddingMode.Zeros;
if (transformType == TransformType.ENCRYPT)
{
rijndaelTransform = rijndael.CreateEncryptor();
}
else
{
rijndaelTransform = rijndael.CreateDecryptor();
}
if ((input != null) && (input.Length > 0))
{
//memStream = new MemoryStream();
//string outputDomainFile =
FileStream fsOutDomain = new FileStream(_outputDomainFile,
FileMode.OpenOrCreate, FileAccess.Write);
cryptoStream = new CryptoStream(
fsOutDomain, rijndaelTransform, CryptoStreamMode.Write);
cryptoStream.Write(input, 0, input.Length);
cryptoStream.FlushFinalBlock();
//return memStream.ToArray();
return null;
}
return null;
}
catch (CryptographicException)
{
throw new CryptographicException("Password is invalid. Please verify once again.");
}
finally
{
if (rijndael != null) rijndael.Clear();
if (rijndaelTransform != null) rijndaelTransform.Dispose();
if (cryptoStream != null) cryptoStream.Close();
if (memStream != null) memStream.Close();
if (fsOut != null) fsOut.Close();
if (fsIn != null) fsIn.Close();
}
}
Code that sets up the IV values:
private void GenerateKey(string SecretPhrase)
{
// Initialize internal values
this._Key = new byte[24];
this._IV = new byte[16];
// Perform a hash operation using the phrase. This will
// generate a unique 32 character value to be used as the key.
byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);
SHA384Managed sha384 = new SHA384Managed();
sha384.ComputeHash(bytePhrase);
byte[] result = sha384.Hash;
// Transfer the first 24 characters of the hashed value to the key
// and the remaining 8 characters to the intialization vector.
for (int loop = 0; loop < 24; loop++) this._Key[loop] = result[loop];
for (int loop = 24; loop < 40; loop++) this._IV[loop - 24] = result[loop];
}
I would guess that's because of the IV (Initialisation Vector)
This is a classic mistake. Whether you generate an IV yourself or not Rijndael (AES) will provide one for you. The trick is to always save the IV (there's a getter on RijndaelManaged).
When you decrypt, you need to pass both the Key and IV.
If you're saving data to a file or database you can store the IV as a plain text. You can even pass the IV on wire (network, internet) as a plain text. The attacker wont be able(as far as I know) break your cipher based just on an IV. Passing or storing the IV is usually done by prefixing it in front of ciphertext or appending it at the end. (concatenating the two strings)
e.g.
CiphertextIV or IVCiphertext. (remember IV is in plaintext is it should be of a fixed length - making it easy to separate upon receiving for decryption or for database insertion)
So, if your Key is ABCDEFABCDEFABCD and your IV is ABCDEF0123456789
and this plaintext:
'this is some secrect text' (let's say) produces a cipher such as: abcd1234abcd00
You would transmit(or store) like it this: ABCDEF0123456789abcd1234abcd00

Categories

Resources