【问题标题】:How to unwrap a key using RSA in Bouncy castle c#?如何在 Bouncy castle c# 中使用 RSA 解包密钥?
【发布时间】:2018-01-13 16:59:17
【问题描述】:

如何在 Bouncy Castle 中使用 RSA 私钥解包密钥?我收到使用 RSA 公钥包装的已包装密钥。我有 RSA 密钥对。我只是在 C# Bouncy Castle 中找不到可以用来解包它的 api。

C# 源代码 (https://github.com/bcgit/bc-csharp) 中的这段代码目前已被注释掉。 RSA 的注释行正是我所需要的,但是当我尝试使用它们时,它似乎已被删除或从未实现

Key key = cipher.unwrap(wrappedKey, "RSA", IBufferedCipher.PRIVATE_KEY);

上面的行正是我所需要的。为什么被注释掉了? WrapTest.cs 中的完整功能如下:

public ITestResult Perform()
{
    try
        {
//              IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/PKCS5Padding");
            IWrapper cipher = WrapperUtilities.GetWrapper("DES/ECB/PKCS5Padding");

            IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA");
            fact.Init(
                new RsaKeyGenerationParameters(
                    BigInteger.ValueOf(0x10001),
                    new SecureRandom(),
                    512,
                    25));

            AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair();

            AsymmetricKeyParameter priKey = keyPair.Private;
            AsymmetricKeyParameter pubKey = keyPair.Public;

            byte[] priKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey).GetDerEncoded();

            CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator("DES");

//              Key wrapKey = keyGen.generateKey();
            byte[] wrapKeyBytes = keyGen.GenerateKey();
            KeyParameter wrapKey = new DesParameters(wrapKeyBytes);

//              cipher.Init(IBufferedCipher.WRAP_MODE, wrapKey);
            cipher.Init(true, wrapKey);
//              byte[] wrappedKey = cipher.Wrap(priKey);
            byte[] wrappedKey = cipher.Wrap(priKeyBytes, 0, priKeyBytes.Length);

//              cipher.Init(IBufferedCipher.UNWRAP_MODE, wrapKey);
            cipher.Init(false, wrapKey);

//              Key key = cipher.unwrap(wrappedKey, "RSA", IBufferedCipher.PRIVATE_KEY);
            byte[] unwrapped = cipher.Unwrap(wrappedKey, 0, wrappedKey.Length);

            //if (!Arrays.AreEqual(priKey.getEncoded(), key.getEncoded()))
            if (!Arrays.AreEqual(priKeyBytes, unwrapped))
            {
                return new SimpleTestResult(false, "Unwrapped key does not match");
            }

            return new SimpleTestResult(true, Name + ": Okay");
        }
        catch (Exception e)
        {
            return new SimpleTestResult(false, Name + ": exception - " + e.ToString());
        }

}

【问题讨论】:

  • 你说的是Java,对吧?这段代码到底在哪里被注释掉了,你为什么要依赖它?你可以在你的代码中使用它。
  • 能否请您提供更多代码?目前我们甚至不知道cipher 变量的类型。 @ArtjomB。嗯,里面有IBufferedCipher,感觉有点C#-ish。
  • @MaartenBodewes 我已经用更好的解释和更多代码更新了这个问题。
  • @ArtjomB。它是 C# 中的 Bouncy Castle 实现
  • unwrap 方法以小写形式指定,表示复制代码时出现问题或从 Java 复制。这可能会解释混乱。 我们不知道为什么它被注释掉了(我的水晶球随着索伦的毁灭而坏掉了);当您尝试运行它时它会失败吗? 你被困在哪里了?

标签: c# encryption rsa bouncycastle


【解决方案1】:

我并不完全清楚您需要什么,但您可以使用 RSA 密钥在 Bouncycastle 中打包和解包 AES 密钥。下面是一个 Java 示例,它创建一个 RSA 密钥对,将私钥保存到一个文件中,然后保存一个封装在公钥中的 AES 密钥。

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

public class Main {

    private static final SecureRandom rand = new SecureRandom();

    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024, rand);
        KeyPair kp = kpg.generateKeyPair();
        // Write out private key to file, PKCS8-encoded DER
        Files.write(Paths.get("privkey.der"), kp.getPrivate().getEncoded());
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(256, rand);
        SecretKey aesKey = kg.generateKey();

        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        c.init(Cipher.WRAP_MODE, kp.getPublic(), rand);
        byte[] wrappedKey = c.wrap(aesKey);

        // Write out wrapped key
        Files.write(Paths.get("wrappedkey"), wrappedKey);
    }
}

这是一个 C# 示例,它使用 Java 示例的输出并解包 AES 密钥。

using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;

namespace RSADecryptWithBouncy
{
    class MainClass
    {

        private static KeyParameter Unwrap(byte [] key, AsymmetricKeyParameter privKeyParam) {
            var wrapper = WrapperUtilities.GetWrapper("RSA/NONE/PKCS1PADDING");
            wrapper.Init(false, privKeyParam);
            var aesKeyBytes = wrapper.Unwrap(key, 0, key.Length);
            return new KeyParameter(aesKeyBytes);
        }

        public static void Main(string[] args)
        {
            var privKeyBytes = File.ReadAllBytes("../../privkey.der");
            var seq = Asn1Sequence.GetInstance(privKeyBytes);
            var rsaKeyParams = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(seq));
            var wrappedKey = File.ReadAllBytes("../../wrappedKey");
            var aesKey2 = Unwrap(wrappedKey, rsaKeyParams);
        }
    }
}

您必须根据自己的需要进行调整。

【讨论】:

  • 据我了解,问题在于这需要在缺少特殊包装模式的 C# 中。
  • 谢谢大家,我正在修复我的测试以确保其他一切都按预期工作,这样当我得到修复时,我可以正确验证。测试完成后,我将尝试@MaartenBodewes 的建议,尝试加密和解包,对于 AES 应该没问题。
  • @JamesKPolk 我会试试的
  • 好的,很酷。现在希望使用 PKCS#1 v1.5 填充,并且包装的 AES 密钥只是一些字节,而不是某种 PKCS#11 模板。
  • @MaartenBodewes:谢谢。顺便说一句,当我用“OAEPWithSHA-256AndMGF1Padding”替换“PKCS1PADDING”时,Bouncy C# 代码引发了“数据哈希错误”异常。
猜你喜欢
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 2012-07-05
相关资源
最近更新 更多