我需要正确加密文本(特定密码),以便第三方可以解密它。他们为我提供了他们用来解密的密钥,并告诉我他们将使用OpenSSL解密它。
我一直在尝试使用AESManaged和System.Security.Cryptography中的RijndaelManaged类来创建可解密但不是非常成功的东西。
他们提供的加密的OpenSSL示例是:
回显“密码”| enc -base64 -aes-256-cbc -k“providedKey”-p -md sha1
所以我需要创建一个CryptoStream,它是一个密钥大小为256的AES加密器,以及一个CBC的密码模式。然后base64编码生成的字节数组。那部分非常简单。
我不确定如何创造是关键,我正在寻找正确方向的一点。
我注意到OpenSSL中这些参数创建的所有base64解码文本都以相同的8个字符“Salted__”开头。所以我猜这是用来生成密钥的Salt。
任何人都知道如何使用私钥和“Salted __”创建SHA1密钥?
我知道OpenSSL.Net项目用于包装OpenSSL dll,但我希望尽可能避免使用该路由。
答案 0 :(得分:3)
感谢GregS's Point in the right direction,复制EVP_BytesToKey()中发生的密钥和初始向量生成非常容易。
基本上他们创建了一个48字节的数组(密钥为32字节数组,IV为16字节数组),并使用SHA1将私钥和8个盐字节散列到该缓冲区。第一个哈希只是私钥和salt,连续哈希是生成的最后一个哈希,它与key和salt字节连接起来,直到填充48字节数组。
密钥只是前32个字节,IV是最后16个字节。
使用AESManaged中的System.Security.Crytpography类以及从此方法派生的密钥和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;
}
答案 1 :(得分:1)
我在相关的openssl源(apps/enc.c
)中略微探讨了一下,我认为openssl使用了一种有点专有的方法。我承认我太懒了,无法弄清楚所有的细节,但他们在那里。看起来ASCII字符串“Salted__”后跟8个随机盐字节被添加到文件中。使用名为EVP_BytesToKey()
的openssl方法从密码和salt 派生 和 AES的AES密钥和。该手册中描述了该算法。在版本1.0.0a的enc.c
source code中,此部分从第510行开始。
希望这可以让你开始。