4

我有公钥模数和公钥指数,我需要在 Metro 风格应用程序中生成公钥并加密数据。在 c# 中,我们有 RSAParameters 类,但对于 Metro 风格的应用程序,我找不到任何此类的东西。

当我使用直接从证书接收到的 base64 编码公钥并尝试使用以下代码导入密钥时,我得到一个异常抛出 ASN1 bad tag value met。我认为这是由于数据格式无效。

     //sample dummy key from certificate in base64encoded
     string key =   @"MIIB0zCCAX2gAwIBAgIJAMF/bHcA799IMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTIwMzI3MTEyNjQ5WhcNMTMwMzI3MTEyNjQ5WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMEPeWjP4sdqxvBlDId4BtRRTeWPwjlZLSOFvOVgmoSyoPva8psFUF6tH9/vPXIJrL80tdCoBt8YFH6pwDN9a1sCAwEAAaNQME4wHQYDVR0OBBYEFGARqQfUhX7atVU4sS+aQAPt/jFxMB8GA1UdIwQYMBaAFGARqQfUhX7atVU4sS+aQAPt/jFxMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADQQALqOyjovRbWUZvziVaE8QYy83WEln1l+HJU9D6tFncUZTlwSd8aUwyQsd3zOVNZ41oCAVv5R3h1jtBtPbM+c1K";
       symmetricKeyAlgorithmProvider asymmAlg = AsymmetricKeyAlgorithmProvider.OpenAlgorithm("RSA_OAEP_SHA1");
       CryptographicKey publicKey = asymmAlg.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(key));
        string input64string ="encrypt this";
        IBuffer dataToEncrypt = CryptographicBuffer.DecodeFromBase64String(input64string);
        IBuffer encryptedData = CryptographicEngine.Encrypt(publicKey, dataToEncrypt, null);
4

2 回答 2

2

key是公钥的模数部分,长度为 128。考虑从 Metro 中的 C# 代码导出的标准密钥:

using System.Runtime.InteropServices.WindowsRuntime;
CryptographicKey standardKeyPair = provider.CreateKeyPair(1024);
byte[] standardKey = standardKeyPair.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey).ToArray();

你可以看到 byte[] standardKey 的长度是 140,它有 7 位前缀和 5 位尾部。我不知道原因,但我将额外的 12 位复制到已知密钥,它可以工作。希望这可以帮助你:

public static IBuffer RsaEncrypt(this IBuffer dataToEncrypt, string publicKeyN)
{
    AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);

    CryptographicKey standardKeyPair = provider.CreateKeyPair(1024);
    byte[] standardKey = standardKeyPair.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey).ToArray();
    var data_n = CryptographicBuffer.DecodeFromBase64String(publicKeyN).ToArray();
    Array.Copy(data_n, 0, standardKey, 7, data_n.Length);
    var key = provider.ImportPublicKey(standardKey.AsBuffer(), CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey);

    var result = CryptographicEngine.Encrypt(key, dataToEncrypt, null);
    return result;          
}
于 2012-10-30T07:25:07.373 回答
0

这应该满足您的要求:

public static IBuffer RsaEncrypt(byte[] modulus, byte[] exponent, IBuffer data)
{
  var rsa = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha1);
  var keyBlob = modulus.Concat(exponent).ToArray().AsBuffer();
  var publicKey = rsa.ImportPublicKey(keyBlob, CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey);
  return CryptographicEngine.Encrypt(publicKey, data, null);
}

当然,如果需要,您仍然可以使用 base64 字符串作为输入/输出,但您已经知道如何做到这一点。:)

如果您深入研究RFC3447的第 61 页,您会发现公钥格式结构只是模数后跟指数,这就是我将它们连接起来的原因。

于 2012-11-03T04:31:04.760 回答