我正致力于EWP (Erasmus无论文)的实现,这是一组API,用于在世界各地的大学之间进行通信。每个呼叫都必须用RSA-RSA 256签名。每个合作伙伴都有一个私钥和公钥,公钥在带有keyId的注册表中是可用的。请求有一些标题:主体摘要(sha256散列)、主机、日期、x请求id(随机guid)。这些标头及其值以签名字符串连接在一起,该字符串与私钥签名,其结果是在标头中也发送的签名,以及用于签名的keyId和其他标头。服务器需要检查签名是否有效,方法是创建相同的签名字符串,在注册表中查找公钥,然后检查请求中的签名是否确实正确。
我有两个API作为客户端应用程序来进行测试。我可以访问109个不同的合作伙伴进行测试,其中一些还没有准备好(它们在我的客户端和在线验证器中都显示了一个错误,所以我假设那个API服务器端有一个错误,因为它是一个开发环境),另外一些还可以正常工作。还有EWP的测试API,还有一个在线验证器,您可以使用它向这些API中的任何一个发送请求。
奇怪的是,我的客户端与几乎所有的合作伙伴API一起工作,而其中一些API给了我一个错误--我的签名是错误的(当在线验证器正常工作时)。在我自己的API上使用我的客户端,验证工作正常。使用联机验证程序,我的验证不起作用(无效签名错误)。有两个合作伙伴我的客户不工作,在线验证器工作,和3个API的地方,我的客户端工作,但在线验证器没有(包括我自己的API)
有人能想到什么会引起这些问题吗?奇怪的是,两周前,在线验证器确实在我的API上工作,根据EWP的说法,唯一改变的是在线验证器使用的密钥对,但他声称我现在使用的是正确的(我给他发送了日志)。
会不会是某种字符集的问题?只有当某个字符被用于公钥或类似的东西时,才会发生错误?
这是我的RSA- the 256部分的代码:
在客户端请求中使用私钥:创建签名
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);
}检查接收到的签名是否正确:
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;
}因此,长话短说:以上代码有时运行良好,有时失败。为什么?为什么?
发布于 2021-01-07 17:56:10
问题解决了!结果,请求标头中日期的格式出现了问题。签名字符串中也使用此日期。不同的日期格式意味着无效签名。
在线验证器发出的请求的日期是清华,2021年1月7日14:01:58格林尼治标准时间,在我的代码中获取这个日期时,它被转换为清华,01月7日14:01:58格林尼治时间(当天领先0)。
requestContext.Date = request.Headers.GetValues("date").Last();现在,当第一次验证失败时,我再次尝试删除前导零的更改日期。只有在失败的情况下,签名验证才会失败。原来其他的合作伙伴也在约会中使用领先的零值,这就是为什么我的客户确实使用了一些API而不是其他的.
https://stackoverflow.com/questions/65609565
复制相似问题