При использовании Google Wallet API можно предоставить URL -адрес обратного вызова, это будет указывать, был ли проход был добавлен или удален из пользователя. Криптография данных и адаптация с помощью Google Wallet API - добавить и удалить обратные вызовы. < /p>
Ниже приведен код, который я написал до сих пор. Обратите внимание, что VerifyInterMediateSignature () уже возвращает отрицательный результат.
Любая помощь очень ценится!public bool VerifyCallbackSignatures(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;
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... -signature