【问题标题】:Get SHA1 sign of string with DSA private key from PEM file使用 PEM 文件中的 DSA 私钥获取字符串的 SHA1 符号
【发布时间】:2017-05-07 17:21:14
【问题描述】:

我有一个 PEM 文件,其中包含我的 DSA 私钥,我需要使用此私钥签署一个字符串,以将其发送到我的合作伙伴 API。 (附代码)

出于某种原因,我总是从我的合作伙伴 API 收到签名无效。这意味着该标志的格式不正确。

我的合作伙伴让我在 c# 中使用 bouncycastle,但我找不到任何关于如何从外部 PEM 文件中使用 DSA 对字符串进行签名的示例。

我可以在这里找到任何例子吗?

谢谢。

我尝试使用我编写的方法对字符串进行签名:

 public string ComputeSignature(string method, string path,string client_id, string timestamp, string username)
        {


        var data = String.Concat(method, path, client_id, timestamp);
        if (!string.IsNullOrEmpty(username))
        {
            data = data + username;
        }


        string sig;
        var encoding = new ASCIIEncoding();
        byte[] dataInBytes = encoding.GetBytes(data);
        using (System.Security.Cryptography.HMAC Hmac = new HMACSHA1())
        {
            Hmac.Key = encoding.GetBytes(privateKeyClean);

            byte[] hash = Hmac.ComputeHash(dataInBytes, 0, dataInBytes.Length);
            sig = Convert.ToBase64String(hash, 0, hash.Length);
        }
        return sig;


    }

【问题讨论】:

    标签: c# bouncycastle sha1 pem dsa


    【解决方案1】:

    我使用 bouncycastle 解决了这个问题:

        private static string ComputeSignature()
        {
            AsymmetricCipherKeyPair asymmetricCipherKeyPair;
            using (TextReader textReader = new StreamReader("myprivatekey.pem"))
            {
                asymmetricCipherKeyPair = (AsymmetricCipherKeyPair)new PemReader(textReader).ReadObject();
            }
            DsaPrivateKeyParameters parameters = (DsaPrivateKeyParameters)asymmetricCipherKeyPair.Private;
            string text = TEXTTOENC;
            if (!string.IsNullOrEmpty(userName))
            {
                text += userName;
            }
            Console.Out.WriteLine("Data: {0}", text);
            byte[] bytes = Encoding.ASCII.GetBytes(text);
            DsaDigestSigner dsaDigestSigner = new DsaDigestSigner(new DsaSigner(), new Sha1Digest());
            dsaDigestSigner.Init(true, parameters);
            dsaDigestSigner.BlockUpdate(bytes, 0, bytes.Length);
            byte[] inArray = dsaDigestSigner.GenerateSignature();
            string text2 = Convert.ToBase64String(inArray);
            Console.WriteLine("Signature: {0}", text2);
            return text2;
        }
    

    【讨论】:

      【解决方案2】:

      这里 DSA 签名失败的原因是您根本没有进行 DSA。您正在使用密钥文件的内容作为 HMAC 密钥来执行 HMAC-SHA-1。

      1. 从文件中读取 DSA 关键参数。

      .NET 没有对读取 PEM 密钥文件的内在支持。但是您的标题提到了 BouncyCastle,因此您可以将接受的对How to read a PEM RSA private key from .NET 的答案调整为 DSA(使用 PemReader)。

      或者,您可以使用 OpenSSL 根据此密钥制作自签名证书,并将 cert+key 放入 PFX。 .NET 可以很好地加载 PFX。

      1. 填充 DSA 对象。

      如果你走 PFX 路线,cert.GetDSAPrivateKey() 会做正确的事 (.NET 4.6.2)。在 4.6.2 之前的版本上,您可以使用 cert.PrivateKey as DSA,它仅适用于与 FIPS 186-2 兼容的 DSA(DSA 已在 FIPS 186-3 中升级)。

      如果您使用 BouncyCastle 读取 PEM 关键参数,则可以继续使用 BouncyCastle 或执行using (DSA dsa = DSA.Create()) { dsa.ImportParameters(parametersFromTheFile); /* other stuff here */ } 之类的操作。 (DSA.Create() 将在 .NET Framework 上提供限制为 FIPS-186-2 的对象,但它可以在 .NET Core 上执行 FIPS-186-3)。

      1. 签署数据

      FIPS-186-2 仅允许 SHA-1 作为哈希算法,FIPS-186-3 允许 SHA-2 系列(SHA256、SHA384、SHA512)。我们假设您使用的是 FIPS-186-2/SHA-1(如果不是,那么需要的替换很明显)。

      BouncyCastle:但是他们计算签名。 (抱歉,我不熟悉他们的 API)

      .NET 4.6.1 或更早版本:

      using (SHA1 hash = SHA1.Create())
      {
          signature = dsa.CreateSignature(hash.ComputeHash(dataInBytes));
      }
      

      .NET 4.6.2 或更新版本:

      signature = dsa.SignData(dataInBytes, HashAlgorithmName.SHA1);
      

      肥皂盒

      然后,一旦这一切都说完了(或者,也许是之前):问问自己“我为什么要使用 DSA?”。在 FIPS 186-2(和更早版本)中,DSA 被限制为 1024 位密钥大小和 SHA-1 哈希。 NIST SP800-57 将 SHA-1 和 DSA-1024 分类为具有 80 位安全性(表 2 和表 3)。 NIST 将 80 位安全性分类为 2011-2013 年的“已弃用”和 2014 年及以后的“不允许”(表 4)。 DSA 的现代使用(适用于受 NIST 建议的实体)需要 FIPS-186-3 支持。

      ECDSA 获得 ~keysize/2 位安全性;因此最低(通常支持)的 ECDSA 密钥大小(基于 NIST P-256/secp256r1 的密钥)具有 128 位的安全性,NIST 认为 2031+ 的安全性很好。

      RSA 也是比 DSA 更好的选择,因为它对仍然被 NIST 认为安全的签名提供更广泛的支持。

      不过,如果您要遵守协议,我想没有太多选择。

      【讨论】:

      • 嘿,首先 - 感谢您的详细回答。现在,我还没有找到解决方案,但似乎你帮助我到达那里只需要更多的方向。我认为现在缺少的部分是如何从 PEM 私钥文件创建 DSA 对象。我看到了很多 RSA 的例子,但不是 DSA 的例子。我尝试从公钥生成 DSACryptoServiceProvider 并导入参数,它也给我带来了相同的签名无效错误。使用 DSA 而不是 RSA - 这不取决于我... :\
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-07
      • 2018-09-24
      • 1970-01-01
      • 2011-11-05
      相关资源
      最近更新 更多