问题
I have a requirement to create a signature which is a URL-Safe-Base-64-encoded SHA256+ECDSA signature of a message. This will be used to consume a remote REST service.
I have been given a HAL browser implementation which connects to them as expected and a test implementation done in 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.")
}
I am trying to generate the same signature using C#.
So far this is what my Signing method looks like
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);
}
}
I am getting the code building but creating an invalid signature. Here is the calling method
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;
}
回答1:
If you don't mind I'm going to skip the part where you perform base 64 encoding in one code fragment but not in the other.
Unlike RSA PKCS#1 v1.5 signatures, ECDSA signatures are not deterministic. In other words, they depend on a random number generator to generate the signatures. The signatures will have a different value after each signing operation. The correctness of the value of these signatures can only be tested by verifying with the public key.
回答2:
Just in case someone is having a similar issue... It turned out that Microsoft encodes the above signature in a slightly different way to how java does it. Sorry if I'm using the wrong terminology as I have been out of this space for a little while. Essentially we had to try different signature types will we found one that decoded to the same value in both a c# and java application.
来源:https://stackoverflow.com/questions/32692748/how-to-create-a-digital-signature-using-sha256-with-ecdsa-algorithm-in-c-sharp