简体   繁体   English

RSA-SHA256 签名不匹配

[英]RSA-SHA256 Signature mismatches

I'm working on an implementation of EWP (Erasmus Without Papers), a set of API's for communication between universities world wide.我正在研究 EWP(没有论文的 Erasmus)的实现,这是一组用于世界各地大学之间通信的 API。 Every call must be signed with RSA-SHA256.每个调用都必须使用 RSA-SHA256 进行签名。 Every partner has a private and public key, the public keys are available in a registry with a keyId.每个合作伙伴都有一个私钥和公钥,公钥在带有 keyId 的注册表中可用。 A request has some headers: a digest of the body (sha256 hash), the host, date, x-request-id (random guid).请求有一些标头:正文的摘要(sha256 哈希)、主机、日期、x-request-id(随机 guid)。 These headers and their values are concatenated in a signing string, that is signed with the private key, the result being the signature that is also sent in the headers, along with the keyId and the other headers used for the signature.这些标头及其值连接在一个签名字符串中,该字符串使用私钥进行签名,结果是也在标头中发送的签名,以及用于签名的 keyId 和其他标头。 The server needs to check if the signature is valid, by creating the same signing string, looking up the public key in the registry and then checking if the signature in the request is indeed correct.服务器需要检查签名是否有效,方法是创建相同的签名字符串,在注册表中查找公钥,然后检查请求中的签名是否确实正确。

I have both the API as a client application that I use to test.我有两个 API 作为我用来测试的客户端应用程序。 I have access to 109 different partners to test, some of them are not ready yet (they show an error both in my client and the online validator, so I assume there is an error in that API server side, as it is a development environment), others are working fine.我可以访问 109 个不同的合作伙伴进行测试,其中一些还没有准备好(它们在我的客户端和在线验证器中都显示错误,所以我假设 API 服务器端存在错误,因为它是一个开发环境),其他人工作正常。 There is also a test API of EWP and there is an online validator you can use to send requests to any of these API's.还有一个 EWP 的测试 API 并且有一个在线验证器可用于向这些 API 中的任何一个发送请求。

Strange thing is, my client works with almost all of the partner API's, while some of them give me an error my signature is wrong (when the online validator works fine).奇怪的是,我的客户几乎可以使用所有合作伙伴 API,而其中一些给我一个错误,我的签名是错误的(当在线验证器工作正常时)。 Using my client on my own API, validation works fine.在我自己的 API 上使用我的客户端,验证工作正常。 Using the online validator, my validation does not work (invalid signature error).使用在线验证器,我的验证不起作用(无效签名错误)。 There are 2 partners where my client does not work and the online validator does, and 3 API's where my client works but the online validator doesn't (including my own API)有 2 个合作伙伴,我的客户端不工作而在线验证器可以工作,还有 3 个 API 在我的客户端工作但在线验证器不工作(包括我自己的 API)

Can anyone think of anything that could cause these issues?谁能想到可能导致这些问题的任何事情? Strange thing is, 2 weeks ago, the online validator did work on my API and the only thing that changed according to the EWP guy, is the key pair used by the online validator, but he claims I'm using the correct one now (I sent him my logs)奇怪的是,2 周前,在线验证器确实在我的 API 上工作,而根据 EWP 人的说法,唯一改变的是在线验证器使用的密钥对,但他声称我现在使用的是正确的(我给他发了我的日志)

Could it be some kind of character set issue?会不会是某种字符集问题? An error only happening when some character is used in the public key or something like that?仅当在公钥中使用某些字符或类似的东西时才会发生错误?

Here is my code for the RSA-SHA256 part:这是我的 RSA-SHA256 部分的代码:

Create a signature in the client request, with the private key:使用私钥在客户端请求中创建签名:

public string CreateSignature(string SigningString)
{
    byte[] message = Encoding.UTF8.GetBytes(SigningString);
    PemReader pr = new PemReader(new StringReader(privateKeyString));
    AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();

    RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair.Private);
    RSACng rsaCng = new RSACng();
    rsaCng.ImportParameters(rsaParams);
    byte[] signatureBytes = rsaCng.SignData(message, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

    return Convert.ToBase64String(signatureBytes);
}

Check if the received signature is correct:检查接收到的签名是否正确:

public bool IsRsaHashCorrect(string originalMessage, string hash, string stringPublicKey)
{
    string x509Pem = @"-----BEGIN PUBLIC KEY-----" + stringPublicKey + "-----END PUBLIC KEY-----";

    byte[] message = Encoding.UTF8.GetBytes(originalMessage);
    byte[] signature = Convert.FromBase64String(hash);

    byte[] Sha256Message = SHA256.Create().ComputeHash(message);

    PemReader pr = new PemReader(new StringReader(x509Pem));
    AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();

    RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
    RSACng rsaCng = new RSACng();
    rsaCng.ImportParameters(rsaParams);

    var result = rsaCng.VerifyHash(Sha256Message, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

    log.Info("check rsa-sha256 hash: " + result);

    return result;
}

So, long story short: above code is working fine sometimes, failing other times.所以,长话短说:上面的代码有时工作正常,有时失败。 Why oh why?为什么哦为什么?

Problem is fixed.问题已解决。 Turned out there was an issue with the format of the dates in the request headers.结果发现请求标头中的日期格式存在问题。 This date is also used in the signing string for the signature.此日期也用于签名的签名字符串中。 Different date formats means invalid signature.不同的日期格式意味着无效的签名。

The request sent by the online validator had the date Thu, 7 Jan 2021 14:01:58 GMT When fetching this date in my code, it was transformed into Thu, 07 Jan 2021 14:01:58 GMT (with a leading 0 in the day)在线验证器发送的请求的日期为 Thu, 7 Jan 2021 14:01:58 GMT 在我的代码中获取此日期时,它已转换为 Thu, 07 Jan 2021 14:01:58 GMT(前导 0 在那天)

requestContext.Date = request.Headers.GetValues("date").Last();

Now when first validation fails, I try again with an altered date where the leading zero is deleted.现在,当第一次验证失败时,我再次尝试更改日期,删除前导零。 Only if that fails too, the signature validation fails.只有当它也失败时,签名验证才会失败。 Turns out some other partners are using leading zero's in their dates too, that's why my client did work with some API's and not with others...结果发现其他一些合作伙伴也在他们的日期中使用前导零,这就是为什么我的客户确实使用了一些 API 而不是其他的......

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

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