感謝GregS's Point in the right direction,複製在EVP_BytesToKey()中發生的密鑰和初始向量生成非常容易。
基本上他們正在創建一個48字節的數組(密鑰是32字節數組,IV是16字節數組),並使用SHA1將私鑰和8個鹽字節散列到該緩衝區中。第一個散列只是私鑰和salt,連續的散列是與鍵和鹽字節串聯生成的最後一個散列,直到填充了48字節的數組爲止。
然後關鍵就是前32個字節,而IV是最後的16個字節。
使用System.Security.Crytpography中的AESManaged類和從此方法派生的密鑰和IV,我能夠以使用OpenSSL庫的第三方可以解密的方式加密我的密碼。
這裏是我用於導出密鑰和初始矢量的算法:
/// <summary>
/// Derives the key and IV.
/// </summary>
/// <param name="saltBytes">The salt bytes.</param>
/// <param name="privateKeyBytes">The private key bytes.</param>
/// <param name="iv">The iv.</param>
/// <returns>The Key</returns>
private static byte[] DeriveKeyAndIV(byte[] saltBytes, byte[] privateKeyBytes, out byte[] iv)
{
// we are creating a 16 byte initial vector and a 32 byte key
const int ivLength = 16;
iv = new byte[ivLength];
const int keyLength = 32;
var key = new byte[keyLength];
//SHA1 creates a 20 byte hash
const int hashLength = 20;
// container to store the hashed values
var keyContainer = new byte[keyLength + ivLength];
// munge together the privateKey and salt
var privateKeyAndSalt = new byte[privateKeyBytes.Length + saltBytes.Length];
Array.Copy(privateKeyBytes, privateKeyAndSalt, privateKeyBytes.Length);
Array.Copy(saltBytes, 0, privateKeyAndSalt, privateKeyBytes.Length, saltBytes.Length);
// use SHA1 crypto to match the -md SHA1 command line.
var sha1 = new SHA1CryptoServiceProvider();
// hashtarget holds the successive hash's source bytes.
var hashtarget = new byte[hashLength + privateKeyAndSalt.Length];
byte[] currentHash = null;
var bytesCopied = 0;
// do the hashing until we fill the container
while (bytesCopied < (ivLength + keyLength))
{
// Hash(0) is an empty set so just concatenate private key and salt.
if (currentHash == null)
{
currentHash = sha1.ComputeHash(privateKeyAndSalt);
}
else
{
// successive hashes are done on Hash(prev) + private key + salt.
Array.Copy(currentHash, hashtarget, currentHash.Length);
Array.Copy(privateKeyAndSalt, 0, hashtarget, currentHash.Length, privateKeyAndSalt.Length);
currentHash = hashtarget;
currentHash = sha1.ComputeHash(currentHash);
}
var copyAmount = Math.Min(currentHash.Length, keyContainer.Length - bytesCopied);
Array.Copy(currentHash, 0, keyContainer, bytesCopied, copyAmount);
bytesCopied += copyAmount;
}
// split out bytes in the container. first 32 are key, last 16 are iv.
Array.Copy(keyContainer, 0, key, 0, key.Length);
Array.Copy(keyContainer, key.Length, iv, 0, iv.Length);
return key;
}