首页 > 解决方案 > 需要能够从 C#(dotnet-core)代码中获得与 openssl rsautl -sign -inkey 相同的签名

问题描述

对于 ac# dotnet-core 应用程序(windows 和 linux)和 Chef.io API 之间的通信,我需要能够在 c# dotnet core 中创建与 openssl 可执行文件调用相同的签名:

openssl rsautl -in encryption.txt -sign -inkey chefprivatekey.pem | openssl enc -base64

第一个实现(dotnet 框架)基于此 https://github.com/mattberther/dotnet-chef-api

        byte[] input = Encoding.UTF8.GetBytes(canonicalHeader);

        var pemReader = new PemReader(new StringReader(privateKey));
        AsymmetricKeyParameter key = ((AsymmetricCipherKeyPair)pemReader.ReadObject()).Private;

        ISigner signer = new RsaDigestSigner(new NullDigest());
        signer.Init(true, key);
        signer.BlockUpdate(input, 0, input.Length);
        _signature = Convert.ToBase64String(signer.GenerateSignature());

nuget 包 dotnet-chef-api 还包含旧版本的 BouncyCastle.Crypto.dll。只要我使用这个 dll 一切都可以正常工作,但是如果我通过为此使用 nuget-package 将 dll 更新到较新的版本,那么就没有任何效果了。作为一种解决方法,我已经实现了 openssl 可执行文件的系统调用,以获取 API 的正确签名。这工作正常。但我需要摆脱系统调用。我现在所做的是将 openssl exe 的系统调用结果与我从任何签名算法(如 BouncyCastle lib)获得的结果进行比较。我无法获得与上述调用 openssl-exe 相同的结果。对于 Windows 和 Linux,实现需要是 dotnet-core。只要 openssl exe 和任何 c# 实现之间的结果不一样,我就不需要测试 chef-api。如何从 C# 中的文件加载 RSA 公钥。使用此代码,我可以从 pem 文件中获取 RSACryptoServiceProvider 类型的对象。

        RSACryptoServiceProvider provider = PemKeyUtils.GetRSAProviderFromPemFile(pemFile);
        var trial1 = Convert.ToBase64String(provider.SignData(Convert.FromBase64String("test"), new SHA1CryptoServiceProvider()));

“trial1”的内容与“_signature”相同,但与openssl.exe不同我做错了什么?

“openssl rsautl”默认使用 PKCS#1 v1.5 这可能是个问题吗?

标签: c#.net-coreopensslchef-infrabouncycastle

解决方案


我自己找到了解决方案。我查看了 BouncyCastle 的单元测试,现在将其作为一个可行的解决方案:

public string Sign(byte[] input, string privateKeyPath)
    {
        asymmetricKeyParameter AsymmetricKeyParameterFromPrivateKeyInPemFile
        // Sign the hash

        IBufferedCipher c = CipherUtilities.GetCipher("RSA//PKCS1Padding");

        c.Init(true, asymmetricKeyParameter);

        var outBytes = c.DoFinal(input);
        return Convert.ToBase64String(outBytes);
    }

    public AsymmetricKeyParameter AsymmetricKeyParameterFromPrivateKeyInPemFile(string privateKeyPath)
    {
        using (TextReader privateKeyTextReader = new StringReader(File.ReadAllText(privateKeyPath)))
        {
            PemReader pr = new PemReader(privateKeyTextReader);
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
            return keyPair.Private;
        }
    }

推荐阅读