Как проверить подпись обратного вызова Google Wallet?C#

Место общения программистов C#
Ответить
Anonymous
 Как проверить подпись обратного вызова Google Wallet?

Сообщение Anonymous »

При использовании Google Wallet API можно предоставить URL -адрес обратного вызова, это будет указывать, был ли проход был добавлен или удален из пользователя. Криптография данных и адаптация с помощью Google Wallet API - добавить и удалить обратные вызовы. < /p>
Ниже приведен код, который я написал до сих пор. Обратите внимание, что VerifyInterMediateSignature () уже возвращает отрицательный результат.
Любая помощь очень ценится!public bool VerifyCallbackSignature(CallbackBody? callbackBody)
{
if (callbackBody == null)
return false;

// BUILD INTERMEDIATE SIGNATURE
// signedStringForIntermediateSigningKeySignature =
// length_of_sender_id || sender_id || length_of_protocol_version || protocol_version || length_of_signed_key || signed_key

// JsonCanonicalizer.Canonicalize() returns the same string given as input, just in the right order. (I tried also without it).
string signedKeyString = JsonCanonicalizer.Canonicalize(callbackBody.IntermediateSigningKey.SignedKey);

string senderId = "GooglePayPasses"; // Fixed
byte[] signedStringForIntermediateSigningKeySignature =
[
.. GetLengthRepresentation(senderId),
.. Encoding.UTF8.GetBytes(senderId),
.. GetLengthRepresentation(callbackBody.ProtocolVersion),
.. Encoding.UTF8.GetBytes(callbackBody.ProtocolVersion),
.. GetLengthRepresentation(signedKeyString),
.. Encoding.UTF8.GetBytes(signedKeyString),
];

// COMPARE INTERMEDIATE SIGNATURE
bool result = VerifyIntermediateSignature(callbackBody, signedStringForIntermediateSigningKeySignature);

if (result == false)
return false;

// signedStringForMessageSignature =
// length_of_sender_id || sender_id || length_of_recipient_id || recipient_id || length_of_protocolVersion || protocolVersion || length_of_signedMessage || signedMessage

string signedMessageString = JsonCanonicalizer.Canonicalize(callbackBody.SignedMessage);

byte[] signedStringForMessageSignature =
[
.. GetLengthRepresentation(senderId),
.. Encoding.UTF8.GetBytes(senderId),
.. GetLengthRepresentation(Constants.IssuerId),
.. Encoding.UTF8.GetBytes(Constants.IssuerId),
.. GetLengthRepresentation(callbackBody.ProtocolVersion),
.. Encoding.UTF8.GetBytes(callbackBody.ProtocolVersion),
.. GetLengthRepresentation(signedMessageString),
.. Encoding.UTF8.GetBytes(signedMessageString)
];

result = VerifyMessageSignature(callbackBody, signedStringForMessageSignature);
if (result == false)
return false;

return true;
}

// --------------------------------------------------------------------------------------

private bool VerifyIntermediateSignature(CallbackBody callbackBody, byte[] dataBytes)
{
foreach (GooglePublicKey googleKey in _googleKeys.Keys)
{
// Parse the public key from base64
byte[] publicKeyBytes = Convert.FromBase64String(googleKey.KeyValue);

using ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
ecdsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _);

foreach (string internalSignature in callbackBody.IntermediateSigningKey.Signatures)
{
// Get the signature from the callback body (assuming it's base64 encoded)
byte[] signatureBytes = Convert.FromBase64String(internalSignature);

if (ecdsa.VerifyData(dataBytes, signatureBytes, HashAlgorithmName.SHA256))
{
return true;
}

}
}
return false;
}

private bool VerifyMessageSignature(CallbackBody callbackBody, byte[] dataBytes)
{
byte[] keyBytes = Convert.FromBase64String(callbackBody.IntermediateSigningKey.SignedKeyObject.KeyValue);
using ECDsa ecdsa = ECDsa.Create();
ecdsa.ImportSubjectPublicKeyInfo(keyBytes, out _);

byte[] signatureBytes = Convert.FromBase64String(callbackBody.Signature);

return ecdsa.VerifyData(dataBytes, signatureBytes, HashAlgorithmName.SHA256);
}

///
/// Transforms integer length into the desired representation: 4 bytes in little endian format.
///
///

///
private byte[] GetLengthRepresentation(string str)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] bytes = BitConverter.GetBytes(strBytes.Length);

return bytes;
}

edit 1-добавлен код, который следует запустить
public class GoogleSecurityChecker
{
public static void Main(string[] args)
{
GooglePublicKeysWrapper keys = new GooglePublicKeysWrapper()
{
Keys =
[
new GooglePublicKey()
{
KeyValue = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEs/J7ghdwu4/b6NvqzQebS+Z80FEP8ZlGdAdWDUjfPeBKaV+YOWW0l6U/4IGXnfY9NrsND1fwxAqRq0unR/LCIg==",
ProtocolVersion = "ECv2SigningOnly",
KeyExpiration = "1749736782391"
}
]
};

Checker = new GoogleSecurityChecker();
Checker._googleKeys = keys;

CallbackBody callback = new CallbackBody()
{
Signature = "MEUCIQDLQY9YBdOyjjAbnTgWnn/yQtsISYqnlr9WR1Leo91JvQIgXNU2XNdBaXgliN/Mwt8inDZWpUwHr6ucC7goFhOc/Ug=",
IntermediateSigningKey = new IntermediateSigningKey()
{
SignedKey = "{\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEotqPyf8h3Z88ydn/Zx6d1pAmOp7EFaMTgcuUmjO8HrJDv+ixXcQiaMHxOReI3RoIwjOvxvEwL/x/EI60DTt4/A==\",\"keyExpiration\":\"1748697059000\"}",
Signatures =
[
"MEUCIQDzPGD+5Ppg5xic3POIYkwpUr7YJJ5CkHP4vSLFsPR0MwIgATeTCAi+0/rK/+bYntv0Q/e3kDAEsHG747mV+NTgxgI="
]
},
ProtocolVersion = "ECv2SigningOnly",
SignedMessage = "{\"classId\":\"3388000000022891807.my-test-unibz\",\"objectId\":\"3388000000022891807.1\",\"eventType\":\"save\",\"expTimeMillis\":1748018479599,\"count\":1,\"nonce\":\"68a290e7-e1ec-4130-978a-28ff30ea6ab2\"}"
};

bool result = Checker.VerifyCallbackSignature(callback);
Console.WriteLine($"Result: {result}");
}
}


Подробнее здесь: https://stackoverflow.com/questions/796 ... -signature
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»