При использовании 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
Как проверить подпись обратного вызова Google Wallet? ⇐ C#
Место общения программистов C#
-
Anonymous
1750855233
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;
}
[b] edit 1-добавлен код, который следует запустить [/b]
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}");
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79654749/how-to-verify-google-wallets-callback-signature[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия