经过一番摸索,我决定生成一个随机的 RSA 密钥对,然后使用 AES 对称加密私钥。
这导致我采用以下两种方法:
public static byte[] EncryptData(string pass, byte[] salt, byte[] encryptedPrivateKey, byte[] targetPublicKey,
byte[] iv, byte[] data)
{
using (var rfc = new Rfc2898DeriveBytes(pass, salt, IterationCount))
{
using (var aes = new AesCryptoServiceProvider())
{
aes.KeySize = AesKeySize;
aes.Key = rfc.GetBytes(aes.KeySize / 8);
aes.IV = iv;
using (var dec = aes.CreateDecryptor(aes.Key, aes.IV))
{
using (var ms = new MemoryStream(encryptedPrivateKey))
{
using (var cs = new CryptoStream(ms, dec, CryptoStreamMode.Read))
{
var privKey = new byte[RsaKeySize];
cs.Read(privKey, 0, privKey.Length);
return RsaEncrypt(targetPublicKey, data);
}
}
}
}
}
}
public static byte[] DecryptData(string pass, byte[] salt, byte[] encryptedPrivateKey, byte[] iv, byte[] data)
{
using (var rfc = new Rfc2898DeriveBytes(pass, salt, IterationCount))
{
using (var aes = new AesCryptoServiceProvider())
{
aes.KeySize = AesKeySize;
aes.Key = rfc.GetBytes(aes.KeySize/8);
aes.IV = iv;
using (var dec = aes.CreateDecryptor(aes.Key, aes.IV))
{
using (var ms = new MemoryStream(encryptedPrivateKey))
{
using (var cs = new CryptoStream(ms, dec, CryptoStreamMode.Read))
{
var privKey = new byte[RsaKeySize];
cs.Read(privKey, 0, privKey.Length);
return RsaDecrypt(privKey, data);
}
}
}
}
}
}
RSA 还不够。
本质上,RSA 只能加密较小的数据than the key size
在我的新方案中:
- 用户身份是 RSA 公钥和 RSA 私钥,通过使用密码和 salt 派生 AES 密钥,使用 AES 加密
- 加密数据涉及:
- 生成随机 AES 密钥
- 使用该 AES 密钥加密数据
- 使用发起者的 RSA 私钥生成加密数据的 RSA 签名
- 通过 RSA 使用目标的公共 RSA 密钥加密随机 AES 密钥来授予对数据的访问权限
这让我可以存储所有核心信息:
- 公钥
- 盐
- 初始化向量
- 加密的私钥
几乎在我想要的地方,因为实际破解私钥需要密码。
解密也比较简单:
- 接收传入数据
- RSA 根据声称的发件人的 RSA 公钥对其进行验证
- 从派生密码 + salt AES 密钥中解密接收方的 RSA 私钥
- 解密访问密钥(嵌入式/托管 AES 密钥)
- 使用提供的密钥解密接收到的数据