【问题标题】:C# (.NET) RSACryptoServiceProvider import/export x509 public key blob and PKCS8 private key blobC# (.NET) RSACryptoServiceProvider 导入/导出 x509 公钥 blob 和 PKCS8 私钥 blob
【发布时间】:2017-04-10 00:15:16
【问题描述】:

首先让我声明我不是加密专家,但我知道基础知识。

我希望能够:

  1. 从 X509 公钥 blob 中获取 RSACryptoServiceProvider 实例
  2. 从 PKCS8 私钥 blob 中获取 RSACryptoServiceProvider 实例
  3. 将 RSACryptoServiceProvider 实例中的公钥导出为 x509 公钥 blob
  4. 将私钥从 RSACryptoServiceProvider 实例导出为 PKCS8 blob

【问题讨论】:

  • 你用私钥加密,用公钥解密。这称为数字签名,在 Java 和 C# 中有特定的方法。真的是你想做的吗?通常使用公钥进行加密,使用私钥进行解密。
  • 还要注意,导入 RSA 公钥并非易事。stackoverflow.com/questions/18091460/rsa-read-publickey
  • @pedrofb 我已经参与其中。我必须将二进制 asn.1 X509PKInfo 解析为 RSAParameters 对象。完成后我会提供代码解决方案。
  • 感谢您让我走上正轨@pedrofb

标签: c# cryptography rsa public-key-encryption


【解决方案1】:

在环顾了一整天后,我找到了这个repository (thanks a lot jrnker),并选择了实现目标 1、2 和 3 所需的代码。

由于 Jrnker 仅提供从 PKCS1 blob 中获取 RSACryptoServiceProvider 的方法(而我需要的是从 PKCS8 blob 中获取 RSACryptoServiceProvider),因此我一直在努力实现目标 4。然后我找到了 Michel Gallant's "opensslkey.cs" 并选择了需要代码来实现目标 4。

然后我开始编译一个包含所需方法和类的类。

这是我的演示课:

using System;

namespace RSAKeyTests
{
    class Demo
    {
        static void Main(string[] args)
        {
            //EXPORTED KEYS
            string importedPublicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhbVC4aUR+XRCepBcPlod69wruXqwW9yL/YJYvuaQ33QxUoAehQ0z4SuphHwEPxQp/qLqucmE6XKlEeTksFAmaGM88uuGessqMZmdu9WFhc07MWLTCifR43IRtGEeWeFSWjUI6mNRrShP3QQ3+Z6e7w+HRA2RpmgNgEhJRvECHAKpcpHvP9o5Sq6q/dIAyR6NEjRFhfud27rFtnWrLj+ZmIsScemvks4vh8V3n8EzxxRE8nzVuZYr4v4NNH+q95XgIadHZ1Y6ICXJgX2NfacNRQl9+SEv0Wo8lbmFSIO3jHqyiWuSugv7R3/rQPRXHT6HJAtw0tBiPOBitMkTzqOvIwIDAQAB";
            string importedPrivateKeyBase64 = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCFtULhpRH5dEJ6kFw+Wh3r3Cu5erBb3Iv9gli+5pDfdDFSgB6FDTPhK6mEfAQ/FCn+ouq5yYTpcqUR5OSwUCZoYzzy64Z6yyoxmZ271YWFzTsxYtMKJ9HjchG0YR5Z4VJaNQjqY1GtKE/dBDf5np7vD4dEDZGmaA2ASElG8QIcAqlyke8/2jlKrqr90gDJHo0SNEWF+53busW2dasuP5mYixJx6a+Szi+HxXefwTPHFETyfNW5livi/g00f6r3leAhp0dnVjogJcmBfY19pw1FCX35IS/RajyVuYVIg7eMerKJa5K6C/tHf+tA9FcdPockC3DS0GI84GK0yRPOo68jAgMBAAECggEAJ/Dalr8RnHvPM/+Vnoaa847kfNaaggZixwq96eDEHAwAg82D0Gj+O2AolkvZlOI4HTmbdn4tNvMpPiwq6EQ5BOvIFCSpGltAMmraBHcnGK4S5ZDIy/rTJuc3RLPSNjUpvYqkLCgZCOnG2ZXeBrIMdgskc/69qIDir5RoV0m9QJJYU7pfrfErWYr/eqb1t7eZtTBAg+LAjKUMUq68WoJiBSBRPbAvlyFoc6tyk0ftngsF4OPVbwZQyYC2vLmxVrr1/YQbEgjpuJwQ0bONL6G9PAH6O+h10ILk9nyJY2c9gOXU0tz+foJ47naM12wCJETEy9JGeAiN4NLz5wRKTZzZwQKBgQDCOEJGDgtmSM0bDv4vPuxbacFgGTgRAKTs6sG9E1Cf3LNBLDP9OhfRkXFc192PmQRAktaZAN89zXeGxK1tLbJ3003qKXw05K3KOksVjJ7AH4Yhurv3VWmFZB8pryUsxIp+rm/5GLf4LfptUmBO6R4+jTfJVRBtK4A9KmkbY7BjgwKBgQCwPWayTgd0fmDqJxptWfPThcUw3/cG6EWTpnx1dSOdaBHzewRwq/8/i4vs314/onLggXgZTIkPU7y8ylTmz5KcaPIQkmRSSSL0Y2yzMGcHnylj7ysgBLw23k/PVzGSsMZ6ly7lE03SNQ3tyg6u0lc3pbT8ZLHf/x913stxSSiT4QKBgQChdgnKmZRqhS1WSGGSP3pZCJNFY9HTeLijaQqFOFB3hg/Tp37VDv2MMKCQsbi0z13UnP4glrQAehbbCBixQiMzMIx+ldx3UIEWNN4E3TGAwPROiCIJnY0q4rBxg/SgwgftBvF5oU4X2YluZuQ/1ddZ4ya0jq4oQ9jJgL9+kKKsJwKBgQCndbBfPEVZK7xqwT0bKp3EHxd/mU/gAFQcN9WKxgNRTdHAyOMvLD8c4jvSl2u2i2UcbejwIQkaxzZPLPH/XrywYgegN3mbtmLAVLi0iwla9KEfk+ImSlmMyTCMkw1HlTECyySEBhOr6T2S9Kt+8d5twcZ3DDb34DLEjS5CNoGYAQKBgDCEyhrg2lwyYwrL26ohNNuzgiabC5IKCgHlMpsUQjoCid9awCSb2iROf7iZIBoDyzXqgEQWTAf2clpJxgHz0necVw2sXP8wGcJXJ+e/lXNfPaC4z2QRnQ6i2iV88jRlWLK+S403hGnK0L/SDu9LtBhHwy6r/qRGT14ourqS6x7O";
            byte[] importedPublicKeyBytes = Convert.FromBase64String(importedPublicKeyBase64);
            byte[] importedPrivateKeyBytes = Convert.FromBase64String(importedPrivateKeyBase64);

            //PRINT INFO
            Console.WriteLine("------   IMPORTED KEY PAIR:   ------\n");
            Console.WriteLine("PUBLIC KEY:\n"+importedPublicKeyBase64+"\n\n");
            Console.WriteLine("PRIVATE KEY:\n" + importedPrivateKeyBase64 + "\n\n");

            //GENERATING RSACRYPTOSERVICEPROVIDER FROM X509 PUBLIC KEY BLOB
            using (var providerFromX509pubKey = RSAKeyUtils.DecodePublicKey(importedPublicKeyBytes))
            {
                providerFromX509pubKey.PersistKeyInCsp = false; //DO NOT STORE IN KEYSTORE

                //EXPORT TO X509 PUBLIC KEY BLOB
                byte[] x509pubKeyBytes = RSAKeyUtils.PublicKeyToX509(providerFromX509pubKey.ExportParameters(false));

                //CONVERT TO BASE64
                string x509pubKeyBase64 = Convert.ToBase64String(x509pubKeyBytes);

                //PRINT INFO
                Console.WriteLine("------   PUBLIC KEY TO EXPORT   ------");
                Console.WriteLine("Public key to export matches imported? "+importedPublicKeyBase64.Equals(x509pubKeyBase64));
                Console.WriteLine(x509pubKeyBase64+"\n\n");
            }

            //GENERATING RSACRYPTOSERVICEPROVIDER FROM PKCS8 PRIVATE KEY BLOB
            using (var providerFromPKCS8privKey = RSAKeyUtils.DecodePrivateKeyInfo(importedPrivateKeyBytes))
            {
                providerFromPKCS8privKey.PersistKeyInCsp = false; //DO NOT STORE IN KEYSTORE

                //EXPORT TO PKCS8 PRIVATE KEY BLOB
                byte[] pkcs8privKeyBytes = RSAKeyUtils.PrivateKeyToPKCS8(providerFromPKCS1privKey.ExportParameters(true));

                //CONVERT TO BASE64
                string pkcs8privKeyBase64 = Convert.ToBase64String(pkcs8privKeyBytes);

                //PRINT INFO
                Console.WriteLine("------   PRIVATE KEY TO EXPORT   ------");
                Console.WriteLine("Private key to export matches imported? " + importedPrivateKeyBase64.Equals(pkcs8privKeyBase64));
                Console.WriteLine(pkcs8privKeyBase64);
            }

                //PREVENTS THE PROGRAM FROM EXITING
                Console.ReadKey();
        }
    }
}

Here's the "RSAKeyUtils" class i've compiled.

我希望这对其他人有用。

【讨论】:

  • 您的 RSAKeyUtils 非常有帮助,非常感谢。
【解决方案2】:

首先,Java 中的 byte 与 .Net 中的 byte 不同。 Java 只有有符号整数,所以 Java byte 的范围从 -128 到 127,而 .Net byte 的范围从 0 到 255。但我不确定,如果这是问题所在,因为 Base64 字符串依赖在位模式上。尝试在其正数范围内使用较大的类型,并仅使用低 8 位。

其次,有关错误提供程序版本的消息可能表明上述原因,或者可能只是一个误导性文本,这并没有真正的帮助。我记得我曾经遇到过同样的错误信息,并且很难找到真正的原因。几分钟前的快速搜索也没有成功。就我而言,我的情况完全不同,因此我无法直接指出您的问题。相反,我建议检查填充、加密模式、base64 转换和围绕 RSA 算法的相关内容,并尝试找到一种替代方法来实现与您之前想要的相同的效果。在去那里的路上,您可能会偶然发现实际问题。

【讨论】:

  • 填充、加密模式和 base64 转换都很好,因为我很久以前就依赖它们并且从来没有遇到过问题。问题肯定出在关键表示中......
猜你喜欢
  • 1970-01-01
  • 2016-08-16
  • 2018-12-25
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 2011-05-11
  • 2013-05-18
  • 2019-05-28
相关资源
最近更新 更多