使用本地公共 PEM 文件加密字符串,使用 Azure KayVault 中的私钥解密

Encrypt a string using local public PEM file, decrypt using private key in Azure KayVault

提问人:Damo 提问时间:11/18/2023 更新时间:11/18/2023 访问量:61

问:

我正在尝试编写一个概念证明,通过该证明,我们可以在本地使用公钥加密字符串,并使用 Azure Key Vault 中的关联私钥解密字符串。

如果我使用直接从 Azure KeyVault 中的密钥进行加密和解密,则可以成功执行此操作;但是,我们的用例是,我们希望从 Azure KeyVault 下载并存储(手动)公钥以进行加密。

在下面的示例代码中,我可以使用本地公共 PEM 文件进行加密。当我尝试在 Azure 中使用关联的私钥进行解码时,出现以下错误:

System.AggregateException: 'One or more errors occurred. (Error occurred while decoding OAEP padding.
Status: 400 (Bad Request)
ErrorCode: BadParameter

我知道加密和解密中的 RSAEncryptionPadding 和 EncryptionAlgorithm 可能不兼容,但我不知道从这里去哪里。

法典:

using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;


string input = "SomeString";
var encryptStringAsync = EncryptStringAsync(input);

var valenc = encryptStringAsync.Result;

Console.WriteLine(valenc);

var decryptStringAsync = DecryptStringAsync(valenc);

var valueenc = decryptStringAsync.Result;

Console.WriteLine(valueenc);

static async Task<string> EncryptStringAsync(string input)
{
    byte[] inputAsByteArray = Encoding.UTF8.GetBytes(input);

    using (RSA rsa = GetRSAFromPemFile())
    {
        byte[] encryptedData = rsa.Encrypt(inputAsByteArray, RSAEncryptionPadding.OaepSHA256);
        return Convert.ToBase64String(encryptedData);
    }

    RSA GetRSAFromPemFile()
    {
        string publicKey = File.ReadAllText("C:\\temp\\20231117.pem");

        var rsaPublicKey = RSA.Create();
        rsaPublicKey.ImportFromPem(publicKey);

        return rsaPublicKey;
    }
}


static async Task<string> DecryptStringAsync(string input)
{

    string keyVaultName = "xxx";
    string keyVaultUri = "https://" + keyVaultName + ".vault.azure.net";
    string keyVaultKeyName = "xxx";
    
    var client = new KeyClient(new Uri(keyVaultUri), new DefaultAzureCredential());
    KeyVaultKey key = await client.GetKeyAsync(keyVaultKeyName).ConfigureAwait(false);
    var cryptoClient = new CryptographyClient(key.Id, new DefaultAzureCredential());
    
    byte[] inputAsByteArray = Convert.FromBase64String(input);
    DecryptResult decryptResult = await cryptoClient.DecryptAsync(EncryptionAlgorithm.RsaOaep, inputAsByteArray).ConfigureAwait(false);
    return Encoding.Default.GetString(decryptResult.Plaintext);
}
C# Azure 加密 azure-keyvault

评论

1赞 Topaco 11/18/2023
只是一个猜测:In 你使用 ,对应于带有 SHA-256 的 OAEP(用于 OAEP 和 MGF1 摘要),而 in 则用于 ,它对应于带有 SHA-1 的 OAEP(对于两个摘要)。为了兼容,OAEP 参数必须相同。因此,尝试例如.EncryptStringAsync()RSAEncryptionPadding.OaepSHA256DecryptStringAsync()EncryptionAlgorithm.RsaOaepEncryptionAlgorithm.RsaOaep256
0赞 Damo 11/18/2023
谢谢。不幸的是,这不是一个有效的选择。我的选项是 Pkcs1、OaepSHA1、OaepSHA256、OaepSHA384、OaepSHA512
1赞 Topaco 11/18/2023
如果无法在 中更改,则可以使用 中的 来实现兼容性。正如我所说,为了兼容,OAEP参数必须相同才能进行加密和解密。EncryptionAlgorithm.RsaOaepDecryptStringAsync()RSAEncryptionPadding.OaepSHA1EncryptStringAsync()
0赞 Damo 11/21/2023
就是这样。你想创建一个答案,我会接受它。
0赞 Topaco 11/21/2023
我已将我的评论作为答案。感谢。

答:

1赞 Topaco 11/21/2023 #1

将 RSA 与 OAEP 一起使用时,用于解密的 OAEP 参数必须与用于加密的参数相对应。这尤其适用于两个摘要,即 OAEP 摘要和 MGF1 摘要。另一个参数是 OAEP 标签,该标签通常始终留空。有关带有 OAEP 的 RSA,请参阅 RFC 8017、7.1。RSAES-OAEP的。

但是,在发布的代码中,加密和解密的摘要有所不同。在 中,使用 RSAEncryptionPadding.OaepSHA256,它将 SHA-256 应用于两个摘要,而在 EncryptionAlgorithm.RsaOaep 中使用(另请参阅此处),它将 SHA-1 应用于两个摘要。EncryptStringAsync()DecryptStringAsync()

因此,解决方法是在 RSAEncryptionPadding.OaepSHA1 中使用 RSAEncryptionPadding.OaepSHA1EncryptionAlgorithm.RsaOaep256,以便在两端使用相同的 OAEP 参数。EncryptStringAsync()DecryptStringAsync()