[英]How to verify signature authenticity that was signed using google KMS (Asymmetric sign, Elliptic Curve P-256 key SHA256 Digest) in C#
I have some string data which I signed with google key defined by Algorithm: Elliptic Curve P-256 key, SHA256 Digest.我有一些字符串数据,我用算法定义的谷歌密钥签名:椭圆曲线 P-256 密钥,SHA256 摘要。 I wrote a program that should verify that the data and the signature (that was returned from KMS after the signing) and the public key are valid.
我编写了一个程序来验证数据和签名(签名后从 KMS 返回)和公钥是否有效。
The problem is that I always get false.问题是我总是弄错。
For convenience, here is the code that signs the data using google KMS.为方便起见,这里是使用 google KMS 对数据进行签名的代码。 I use Google.Cloud.Kms.V1,
KeyManagementServiceClient
and call method AsymmetricSign
that returns the signature:我使用 Google.Cloud.Kms.V1、
KeyManagementServiceClient
并调用返回签名的方法AsymmetricSign
:
public byte[] SignAsymmetric(string keyId, string message)
{
//Create the client.
KeyManagementServiceClient client;
GoogleCredential credential = CredentialManager.GetCredential();
if (credential != null)
{
client = new KeyManagementServiceClientBuilder { ChannelCredentials = credential.ToChannelCredentials() }.Build();
}
else
{
client = new KeyManagementServiceClientBuilder().Build();
}
//get key enabled version
CryptoKeyName name = new CryptoKeyName(_projectId, _locationId, _keyRingId, keyId);
string cryptoKeyVersionId = client.ListCryptoKeyVersions(name).Where(s => s.State == CryptoKeyVersionState.Enabled).First().CryptoKeyVersionName.CryptoKeyVersionId;
// Build the key version name.
CryptoKeyVersionName keyVersionName = new CryptoKeyVersionName(_projectId, _locationId, _keyRingId, keyId, cryptoKeyVersionId);
// Convert the message into bytes. Cryptographic plaintexts and
// ciphertexts are always byte arrays.
byte[] plaintext = Encoding.ASCII.GetBytes(message);
// Calculate the digest.
SHA256 sha256 = SHA256.Create();
byte[] hash = sha256.ComputeHash(plaintext);
// Build the digest.
//
// Note: Key algorithms will require a varying hash function. For
// example, EC_SIGN_P384_SHA384 requires SHA-384.
Digest digest = new Digest
{
Sha256 = ByteString.CopyFrom(hash),
};
// Call the API.
AsymmetricSignResponse result = client.AsymmetricSign(keyVersionName, digest);
// Get the signature.
byte[] signature = result.Signature.ToByteArray();
// Return the result.
return signature;
}
Now here is the code which verify the authenticity of the signature and always returns false:现在这里是验证签名真实性并始终返回 false 的代码:
public bool VerifyAsymmetricSignature(string keyId ,string message, byte[] signature = null)
{
// Create the client.
KeyManagementServiceClient client;
GoogleCredential credential = CredentialManager.GetCredential();
if (credential != null)
{
client = new KeyManagementServiceClientBuilder { ChannelCredentials = credential.ToChannelCredentials() }.Build();
}
else
{
client = new KeyManagementServiceClientBuilder().Build();
}
//get key enabled version
CryptoKeyName name = new CryptoKeyName(_projectId, _locationId, _keyRingId, keyId);
string cryptoKeyVersionId = client.ListCryptoKeyVersions(name).Where(s => s.State == CryptoKeyVersionState.Enabled).First().CryptoKeyVersionName.CryptoKeyVersionId;
// Build the key version name.
CryptoKeyVersionName keyVersionName = new CryptoKeyVersionName(_projectId, _locationId, _keyRingId, keyId, cryptoKeyVersionId);
// Get the public key.
//KeyManagementServiceClient client = KeyManagementServiceClient.Create();
PublicKey publicKey = client.GetPublicKey(keyVersionName);
// Split the key into blocks and base64-decode the PEM parts.
string[] blocks = publicKey.Pem.Split("-", StringSplitOptions.RemoveEmptyEntries);
byte[] pem = Convert.FromBase64String(blocks[1]);
ECDsa eCDsa = ECDsa.Create();
eCDsa.ImportSubjectPublicKeyInfo(pem, out _);
// Convert the message into bytes. Cryptographic plaintexts and
// ciphertexts are always byte arrays.
//byte[] plaintext = Encoding.ASCII.GetBytes(message);
SHA256 sha256 = SHA256.Create();
byte[] digest = sha256.ComputeHash(Encoding.UTF8.GetBytes(message));
// Verify the signature.
bool verified = eCDsa.VerifyData(digest, signature, HashAlgorithmName.SHA256);
// Return the result.
return verified;
}
I'm using:我正在使用:
.Net Core 5 System.Security.Cryptography.ECDsa .Net Core 5 System.Security.Cryptography.ECDsa
What am I doing wrong?我究竟做错了什么?
It is not working because Cloud KMS returns signatures in DER-encoded format.它不起作用,因为 Cloud KMS 以 DER 编码格式返回签名。 DER is part of the ITU-T Recommendation X.690 , and .NET requires signatures to be in IEEE 1363 format .
DER 是ITU-T Recommendation X.690 的一部分,.NET 要求签名采用IEEE 1363 格式。
Before the verification, you need to convert to IEEE 1363 using DSAConvertSignatureFormat .在验证之前,您需要使用DSAConvertSignatureFormat转换为 IEEE 1363。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.