我需要创建一个签名,这是一个消息的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;
}
答案 0 :(得分:2)
如果您不介意我会跳过您在一个代码片段中执行base 64编码但不在另一个代码片段中执行的部分。
与RSA PKCS#1 v1.5签名不同,ECDSA签名不具有确定性。换句话说,它们依赖于随机数生成器来生成签名。每次签名操作后,签名将具有不同的值。只能通过使用公钥进行验证来测试这些签名值的正确性。
答案 1 :(得分:1)
以防有人遇到类似的问题...... 事实证明,微软编码上述签名的方式与java的方式略有不同。对不起,如果我使用错误的术语,因为我已经离开这个空间一段时间了。 基本上我们必须尝试不同的签名类型,我们会在c#和java应用程序中找到一个解码为相同值的签名类型。