繁体   English   中英

如何在C#中使用带有ECDSA算法的SHA256创建数字签名

[英]How to create a digital signature using SHA256 with ECDSA algorithm in C#

我需要创建一个签名,这是一个消息的URL-Safe-Base-64编码的SHA256 + ECDSA签名。 这将用于使用远程REST服务。

我已经获得了一个HAL浏览器实现,它按预期连接到它们,并在SCALA中完成了一个测试实现。

    val token = generateToken() // Generates a random numeric token, different for each request
    val lines = line1 + "\n" + line2 + "\n" + line3 + "\n"
    val lineBytes = lines.getBytes()
    try {
        var sig = Signature.getInstance("SHA256withECDSA")
        sig.initSign(privateKey)
        sig.update(lineBytes)
        body.foreach { input => // If there is a body, sign it too
            input.reset()
            var bytes = new Array[Byte](1024)
            while (input.available() > 0) {
                val alloc = input.read(bytes)
                sig.update(bytes, 0, alloc)
            }
        }
        val encoder = new Base64(true)
        val sigString = encoder.encodeAsString(sig.sign()).replace("\r\n", "")
        val headerVal = "authentication.scheme.signed" + " username=" + username + "&token=" + token + "&signature=" + sigString

        request.addHeader("Authorization", headerVal)
    } catch {
        case e : NoSuchAlgorithmException =>
            throw new Error("No support for SHA256withECDSA! Check your Java installation.")
    }

我正在尝试使用C#生成相同的签名。

到目前为止,这是我的签名方法的样子

private byte[] SignData(byte[] hashedMessageToSign)
{
    CngKey pkey2 = CngKey.Open(@"C:\OpenSSL-Win64\bin\MyPrivateiKeyInPkcs8Format.pem");

    using (ECDsaCng dsa = new ECDsaCng(pkey2))
    {
        //dsa.HashAlgorithm = CngAlgorithm.ECDsaP256;
        //bob.key = dsa.Key.Export(CngKeyBlobFormat.EccPublicBlob);

        byte[] data = hashedMessageToSign;

        return dsa.SignData(data);
    }
}

我正在获取代码,但创建了无效的签名。 这是调用方法

        protected void btnLDiscover_Click(object sender, EventArgs e)
{
    HttpWebRequest request = WebRequest.Create("https://service.provider/path/") as HttpWebRequest;
    request.Method = "GET";
    request.ContentType = "application/bespoke.format+json; version=1";
    //request.Date = new DateTime(2015, 9, 3, 10, 40, 48);
    request.Date = new DateTime(2015, 9, 21, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
    request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
    request.Accept = "application/bespoke.format+json; version=1";
    request.KeepAlive = true;
    request.MaximumAutomaticRedirections = 99;
    //request.PreAuthenticate = true;

    string token = DateTime.Now.Ticks.ToString();
    string messageToSign = "GET /path/\n1\n" + token + "\n";

    string signatureString = Convert.ToBase64String(SignData(Encoding.ASCII.GetBytes(messageToSign)));
    //signatureString = RemoveControlCharacters(signatureString);
    //signatureString = HttpUtility.UrlEncode(signatureString);
    signatureString = signatureString
                        .Replace('+', '-')
                        .Replace('/', '_')
                        .Replace("=", string.Empty);

    request.Headers.Add("Authorization", "authentication.shceme.signed username=someuser&token=" + token + "&signature=" + signatureString);

    HttpWebResponse response = request.GetResponse() as HttpWebResponse;

    Encoding enc = System.Text.Encoding.GetEncoding(65001);
    StreamReader loResponseStream =
    new StreamReader(response.GetResponseStream(), enc);

    string responseString = loResponseStream.ReadToEnd();

    loResponseStream.Close();
    response.Close();

    resultTextBox.Text = responseString;
}

如果你不介意我将跳过你在一个代码片段中执行base 64编码而不在另一个代码片段中的部分。

与RSA PKCS#1 v1.5签名不同,ECDSA签名不是确定性的。 换句话说,它们依赖于随机数生成器来生成签名。 每次签名操作后,签名将具有不同的值。 只能通过使用公钥进行验证来测试这些签名值的正确性。

以防万一有人遇到类似的问题......事实证明,微软以与java一样的方式对上述签名进行编码。 对不起,如果我使用错误的术语,因为我已经离开这个空间一段时间了。 基本上我们必须尝试不同的签名类型,我们会在ac#和java应用程序中找到一个解码为相同值的签名类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM