从PEM文件获取带有DSA私钥的字符串的SHA1符号

时间:2016-12-22 06:36:52

标签: c# bouncycastle sha1 pem dsa

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

由于某种原因,我总是从我的合作伙伴API获取Signature Invalid表单。这意味着标志的格式不是很好。

我的合作伙伴提议我使用bouncycastle进行c#但是我找不到任何如何使用外部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;


    }

2 个答案:

答案 0 :(得分:2)

我使用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;
    }

答案 1 :(得分:1)

此处DSA签名失败的原因是您根本不进行DSA。您使用密钥文件的内容作为HMAC密钥来执行HMAC-SHA-1。

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

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

    1. 填充DSA对象。
    2. 如果你使用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. 签署数据
      2. 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获得~keyize / 2位安全性;因此,最低(通常支持的)ECDSA密钥大小(基于NIST P-256 / secp256r1的密钥)获得128位安全性,NIST对2031 +的评分为好。

        RSA也是比DSA更好的选择,因为它对NIST认为安全的签名有更好的支持。

        但是,如果您符合协议,我猜不会有很多选择。