10.2.1 Standard Key Length Handling
AspEncrypt's CryptoContext.GenerateKeyFromPassword method
takes 4 arguments, of which only the first one, the password string,
is required. The other three arguments are the hash algorithm (SHA by default),
cipher algorithm (RC2 by default) and key length (128 by default for
the Enhanced, Strong cryptographic providers, and 40 for the Base provider.)
Consider the following code snippet:
VBScript |
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Context = CM.OpenContext("", True)
Set Key = Context.GenerateKeyFromPassword("My password")
Set Blob = Key.EncryptText("Hello World!")
Response.Write Blob.Base64 |
Assuming the Strong or Enhanced cryptographic provider is used, this code snippet produces
the following output:
16Ij1qo4gRbfXuaEE3uTtQ==
The snippet above implicitly uses the SHA hash function to convert the specified text string
to the key bits, and produces a 128-bit RC2 cipher key. The 160-bit hash function generates more data than necessary
for the key, so the rest of the bits is discarded.
The .NET equivalent of the code above is as follows:
C# |
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
byte[] shahash = sha.ComputeHash(Encoding.UTF8.GetBytes("My password"));
byte[] keybytes = new byte[16];
Array.Copy(shahash, keybytes, 16);
rc2.Key = keybytes;
rc2.IV = new byte[rc2.BlockSize / 8];
ICryptoTransform ctr = rc2.CreateEncryptor();
byte[] plaintext = Encoding.UTF8.GetBytes("Hello World!");
byte[] ciphertext = ctr.TransformFinalBlock(plaintext, 0, (int)plaintext.Length);
Response.Write( Convert.ToBase64String(ciphertext) ); |
The output is also 16Ij1qo4gRbfXuaEE3uTtQ==.
Note that the .NET code requires that an initialization vector be specified even if it is all 0s.
Omitting the .IV property results in random output.
10.2.2 Short (40-bit) Key Handling
40-bit encryption is extremely weak and should never be used. However, some very old legacy systems
originally designed for Windows NT and Windows 2000 still use 40-bit RC2 and RC4 keys.
Consider the following ASP code:
VBScript |
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Context = CM.OpenContext("", True)
Set Key = Context.GenerateKeyFromPassword("My password", calgSHA, calgRC2, 40)
Response.Write Key.EncryptText("Hello World!").Base64 |
Output: 3PmOk7WfLPRlYxa+PTboYA==
To generate a compatible in .NET code, it is not sufficient to change the C# code snippet above by replacing
the two lines
byte[] keybytes = new byte[16];
Array.Copy(shahash, keybytes, 16); ' 128-bit
with
byte[] keybytes = new byte[5];
Array.Copy(shahash, keybytes, 5); ' 40-bit
because CryptoAPI/AspEncrypt uses a special all-0 "salt" to generate 40-bit keys.
For more information on 40-bit key generation and salt, see the MSDN CryptDeriveKey Function documentation.
The matching .NET code must set the UseSalt property to true, as follows:
C# |
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
byte[] shahash = sha.ComputeHash(Encoding.UTF8.GetBytes("My password"));
byte[] keybytes = new byte[5];
Array.Copy(shahash, keybytes, 5);
rc2.Key = keybytes;
rc2.IV = new byte[rc2.BlockSize / 8];
rc2.UseSalt = true;
ICryptoTransform ctr = rc2.CreateEncryptor();
byte[] plaintext = Encoding.UTF8.GetBytes("Hello World!");
byte[] ciphertext = ctr.TransformFinalBlock(plaintext, 0, (int)plaintext.Length);
Response.Write( Convert.ToBase64String(ciphertext) ); |
Output: 3PmOk7WfLPRlYxa+PTboYA==