簡體   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