Google Pay API, पेमेंट के तरीकों की जानकारी को हस्ताक्षर किए गए और एन्क्रिप्ट किए गए PaymentMethodToken पेलोड में दिखाता है. लौटाए गए पेमेंट के तरीके, पैन वाले कार्ड या टोकन वाले कार्ड होते हैं. टोकन वाले कार्ड में डिवाइस पैन और क्रिप्टोग्राम होते हैं.
पेलोड में protocolVersion नाम का एक फ़ील्ड होता है. इससे पेलोड पाने वाले व्यक्ति को यह पता चलता है कि कौनसे क्रिप्टोग्राफ़िक प्रिमिटिव इस्तेमाल किए जा रहे हैं और उनका फ़ॉर्मैट क्या है.
इस गाइड में, Google के हस्ताक्षर वाला और एन्क्रिप्ट (सुरक्षित) किया गया पेमेंट के तरीके का टोकन पाने का अनुरोध करने के लिए, सार्वजनिक कुंजी जनरेट करने का तरीका बताया गया है. साथ ही, टोकन की पुष्टि करने और उसे डिक्रिप्ट (सुरक्षित तरीके से बदलना) करने के लिए ज़रूरी चरणों के बारे में भी बताया गया है.
यह गाइड सिर्फ़ protocolVersion = ECv2 पर लागू होती है.
आपको पेमेंट कार्ड की जानकारी सीधे तौर पर मिलती है. इसलिए, पक्का करें कि आपका ऐप्लिकेशन पीसीआई डीएसएस के मुताबिक हो. साथ ही, आपके सर्वर के पास उपयोगकर्ता के पेमेंट क्रेडेंशियल को सुरक्षित तरीके से हैंडल करने के लिए ज़रूरी इंफ़्रास्ट्रक्चर हो.
Google Pay API ECv2 PaymentMethodToken पेलोड का इस्तेमाल करने के लिए, इंटिग्रेटर को यह तरीका अपनाना होगा:
- Google के रूट साइनिंग पासकोड फ़ेच करें.
- पुष्टि करें कि इंटरमीडिएट साइनिंग कुंजी का हस्ताक्षर, समयसीमा खत्म न हुई किसी भी रूट साइनिंग कुंजी से मान्य है.
- पुष्टि करें कि पेलोड की इंटरमीडिएट साइनिंग कुंजी की समयसीमा खत्म न हुई हो.
- पुष्टि करें कि इंटरमीडिएट साइनिंग कुंजी से पेलोड का हस्ताक्षर मान्य है.
- हस्ताक्षर की पुष्टि करने के बाद, पेलोड के कॉन्टेंट को डिक्रिप्ट करें.
- पुष्टि करें कि मैसेज की समयसीमा खत्म न हुई हो. इसके लिए, आपको यह देखना होगा कि मौजूदा समय, डिक्रिप्ट किए गए कॉन्टेंट में मौजूद
messageExpirationफ़ील्ड में दिए गए समय से कम हो. - डिक्रिप्ट किए गए कॉन्टेंट में मौजूद पेमेंट के तरीके का इस्तेमाल करके, शुल्क लेना.
हमारी Tink लाइब्रेरी में मौजूद सैंपल कोड, पहले से छठे चरण तक की प्रोसेस पूरी करता है.
पेमेंट के तरीके के टोकन का स्ट्रक्चर
Google से मिले PaymentData रिस्पॉन्स में मौजूद मैसेज, UTF-8 एन्कोड किया गया, क्रम से लगाया गया JSON ऑब्जेक्ट होता है. इसमें मौजूद कुंजियां, यहां दी गई टेबल में बताई गई हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
protocolVersion |
स्ट्रिंग | इस फ़ील्ड से, यह पता चलता है कि मैसेज को किस एन्क्रिप्शन या हस्ताक्षर करने की स्कीम के तहत बनाया गया है. इससे, ज़रूरत पड़ने पर प्रोटोकॉल में समय के साथ बदलाव किया जा सकता है. |
signature |
स्ट्रिंग | इससे यह पुष्टि की जाती है कि मैसेज Google से आया है. यह base64 में एन्कोड किया गया है. इसे ECDSA की मदद से, इंटरमीडिएट साइनिंग कुंजी ने बनाया है. |
intermediateSigningKey |
ऑब्जेक्ट | यह Google की इंटरमीडिएट साइनिंग कुंजी वाला JSON ऑब्जेक्ट है. इसमें signedKey के साथ keyValue, keyExpiration, और signatures शामिल हैं. इसे क्रम से लगाया जाता है, ताकि इंटरमीडिएट साइनिंग पासकोड के हस्ताक्षर की पुष्टि करने की प्रोसेस को आसान बनाया जा सके. |
signedMessage |
स्ट्रिंग | यह एक JSON ऑब्जेक्ट है, जिसे एचटीएमएल के लिए सुरक्षित स्ट्रिंग के तौर पर क्रम से लगाया गया है. इसमें encryptedMessage, ephemeralPublicKey, और tag शामिल हैं. इसे क्रम से लगाया जाता है, ताकि हस्ताक्षर की पुष्टि करने की प्रोसेस आसान हो जाए. |
उदाहरण
यहां JSON में पेमेंट के तरीके के टोकन का रिस्पॉन्स दिया गया है:
{ "protocolVersion":"ECv2", "signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d", "intermediateSigningKey":{ "signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}", "signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"] }, "signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}" }
इंटरमीडिएट साइनिंग पासकोड
intermediateSigningKey, UTF-8 में कोड किया गया, क्रम से लगाया गया JSON ऑब्जेक्ट है. इसमें ये वैल्यू शामिल होती हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
signedKey |
स्ट्रिंग | Base64 कोड में बदला गया मैसेज, जिसमें कुंजी के पेमेंट का ब्यौरा होता है. |
signatures |
स्ट्रिंग | इस कुकी से यह पुष्टि की जाती है कि इंटरमीडिएट साइनिंग कुंजी Google से मिली है. यह base64 में एन्कोड किया गया है और इसे ECDSA की मदद से बनाया गया है. |
साइन की गई कुंजी
signedKey, UTF-8 में कोड में बदला गया, क्रम से लगाया गया JSON ऑब्जेक्ट है. इसमें ये वैल्यू शामिल होती हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
keyValue |
स्ट्रिंग | ASN.1 टाइप में एन्कोड की गई कुंजी का base64 वर्शन. SubjectPublicKeyInfo को X.509 स्टैंडर्ड में तय किया गया है. |
keyExpiration |
स्ट्रिंग | यूटीसी के हिसाब से, इंटरमीडिएट कुंजी की समयसीमा खत्म होने की तारीख और समय. इसे epoch के बाद से मिलीसेकंड में दिखाया जाता है. इंटिग्रेटर, खत्म हो चुकी किसी भी कुंजी को अस्वीकार कर देते हैं. |
हस्ताक्षर किया गया मैसेज
signedMessage, UTF-8 में कोड में बदला गया, क्रम से लगाया गया JSON ऑब्जेक्ट है. इसमें ये वैल्यू शामिल होती हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
encryptedMessage |
स्ट्रिंग | base64-encoded एन्क्रिप्ट किया गया मैसेज. इसमें पेमेंट की जानकारी और कुछ अतिरिक्त सुरक्षा फ़ील्ड शामिल होते हैं. |
ephemeralPublicKey |
स्ट्रिंग | यह Base64 से कोड में बदली गई ऐसी सार्वजनिक कुंजी होती है जो निजी कुंजी से जुड़ी होती है. इसका इस्तेमाल, मैसेज को बिना कंप्रेस किए गए पॉइंट फ़ॉर्मैट में एन्क्रिप्ट करने के लिए किया जाता है. ज़्यादा जानकारी के लिए, एन्क्रिप्शन के लिए सार्वजनिक पासकोड का फ़ॉर्मैट देखें. |
tag |
स्ट्रिंग | encryptedMessage का base64 कोड में बदला गया MAC. |
एन्क्रिप्ट (सुरक्षित) किया गया मैसेज
डिक्रिप्ट किया गया encryptedMessage, UTF-8 में कोड किया गया, क्रम से लगाया गया JSON ऑब्जेक्ट होता है. JSON में दो लेवल होते हैं. आउटर लेवल में सुरक्षा के लिए शामिल किए गए मेटाडेटा और फ़ील्ड होते हैं. वहीं, इनर लेवल एक और JSON ऑब्जेक्ट होता है, जो पेमेंट के क्रेडेंशियल को दिखाता है.
encryptedMessage के बारे में ज़्यादा जानकारी के लिए, यहां दी गई टेबल और JSON ऑब्जेक्ट के उदाहरण देखें:
| नाम | टाइप | ब्यौरा |
|---|---|---|
messageExpiration |
स्ट्रिंग | Epoch के बाद से यूटीसी मिलीसेकंड के तौर पर, मैसेज के खत्म होने की तारीख और समय. इंटीग्रेटर को ऐसे मैसेज अस्वीकार करने चाहिए जिनकी समयसीमा खत्म हो गई है. |
messageId |
स्ट्रिंग | यह एक यूनीक आईडी होता है. अगर बाद में मैसेज को रद्द करना हो या उसे ढूंढना हो, तो इस आईडी का इस्तेमाल किया जाता है. |
paymentMethod |
स्ट्रिंग | पेमेंट क्रेडेंशियल का टाइप.
फ़िलहाल, सिर्फ़ CARD इस्तेमाल किया जा सकता है.
|
paymentMethodDetails |
ऑब्जेक्ट | पेमेंट क्रेडेंशियल. इस ऑब्जेक्ट का फ़ॉर्मैट, paymentMethod से तय होता है. इसकी जानकारी यहां दी गई टेबल में दी गई है. |
कार्ड
CARD पेमेंट के तरीके के लिए, पेमेंट क्रेडेंशियल में ये प्रॉपर्टी शामिल होती हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
pan |
स्ट्रिंग | जिस निजी खाते से शुल्क लिया गया है उसका नंबर. इस स्ट्रिंग में सिर्फ़ अंक हैं. |
expirationMonth |
नंबर | कार्ड के इस्तेमाल की समयसीमा खत्म होने का महीना. इसमें 1 का मतलब जनवरी, 2 का मतलब फ़रवरी वगैरह है. |
expirationYear |
नंबर | कार्ड के खत्म होने का चार अंकों वाला साल, जैसे कि 2020. |
authMethod |
स्ट्रिंग | कार्ड से किए गए लेन-देन की पुष्टि करने का तरीका. |
PAN_ONLY
नीचे दिया गया JSON स्निपेट, PAN_ONLY authMethod के साथ CARD paymentMethod
के लिए, पूरे encryptedMessage का उदाहरण है.
{ "paymentMethod": "CARD", "paymentMethodDetails": { "authMethod": "PAN_ONLY", "pan": "1111222233334444", "expirationMonth": 10, "expirationYear": 2025 }, "gatewayMerchantId": "some-merchant-id", "messageId": "some-message-id", "messageExpiration": "1759309000000" }
CRYPTOGRAM_3DS
CARD की पुष्टि 3-डी सिक्योर क्रिप्टोग्राम का इस्तेमाल करके की गई हो,
CRYPTOGRAM_3DS authMethod. इसमें ये अतिरिक्त फ़ील्ड शामिल होते हैं:
| नाम | टाइप | ब्यौरा |
|---|---|---|
cryptogram |
स्ट्रिंग | 3-D Secure क्रिप्टोग्राम. |
eciIndicator |
स्ट्रिंग | यह स्ट्रिंग हमेशा मौजूद नहीं होती. यह सिर्फ़ Android पर पुष्टि किए गए डिवाइस टोकन के लेन-देन (CRYPTOGRAM_3DS) के लिए दिखता है. यह वैल्यू, पेमेंट प्रोसेस करने के फ़्लो में पास की जानी चाहिए. |
नीचे दिया गया JSON स्निपेट, CRYPTOGRAM_3DS authMethod के साथ CARD paymentMethod के लिए पूरे encryptedMessage का उदाहरण है:
{
"paymentMethod": "CARD",
"paymentMethodDetails": {
"authMethod": "CRYPTOGRAM_3DS",
"pan": "1111222233334444",
"expirationMonth": 10,
"expirationYear": 2025,
"cryptogram": "AAAAAA...",
"eciIndicator": "eci indicator",
},
"messageId": "some-message-id",
"messageExpiration": "1759309000000"
}eciIndicator
कार्ड नेटवर्क, पुष्टि किए गए डिवाइस टोकन के लेन-देन (CRYPTOGRAM_3DS) के लिए eciIndicator दे सकता है.
आपको अनुमति वाले लेन-देन में eciIndicator वैल्यू को पास करना होगा. इसमें बदलाव नहीं किया जाना चाहिए और न ही इसे हार्डकोड किया जाना चाहिए. ऐसा न करने पर, लेन-देन पूरा नहीं होगा. इस टेबल में, eciIndicator की वैल्यू के बारे में बताया गया है.
| eciIndicator वैल्यू | कार्ड नेटवर्क | कानूनी तौर पर जवाबदेह पक्ष | authMethod |
|---|---|---|---|
""(empty) |
Mastercard | कारोबारी/अक्वायरर | CRYPTOGRAM_3DS |
02 |
Mastercard | कार्ड जारी करने वाला बैंक या कंपनी | CRYPTOGRAM_3DS |
06 |
Mastercard | कारोबारी/अक्वायरर | CRYPTOGRAM_3DS |
05 |
Visa | कार्ड जारी करने वाला बैंक या कंपनी | CRYPTOGRAM_3DS |
07 |
Visa | कारोबारी/अक्वायरर | CRYPTOGRAM_3DS |
""(empty) |
अन्य नेटवर्क | कारोबारी/अक्वायरर | CRYPTOGRAM_3DS |
वीज़ा और मास्टरकार्ड के लिए, इस टेबल में मौजूद ईसीआई वैल्यू के अलावा कोई अन्य ईसीआई वैल्यू नहीं दिखाई जाएगी.
हस्ताक्षर की पुष्टि करना
हस्ताक्षरों की पुष्टि करने के लिए, यहां दी गई चीज़ें ज़रूरी हैं. इनमें इंटरमीडिएट कुंजी और मैसेज के हस्ताक्षर शामिल हैं:
- सिग्नेचर बनाने के लिए इस्तेमाल किया गया एल्गोरिदम
- हस्ताक्षर बनाने के लिए इस्तेमाल की गई बाइट-स्ट्रिंग
- वह सार्वजनिक कुंजी जिसका इस्तेमाल हस्ताक्षर बनाने के लिए की गई निजी कुंजी से मेल खाता है
- हस्ताक्षर
हस्ताक्षर एल्गोरिदम
Google, मैसेज पर हस्ताक्षर करने के लिए Elliptic Curve Digital Signature Algorithm (ECDSA) का इस्तेमाल करता है. इसके लिए, इन पैरामीटर का इस्तेमाल किया जाता है: FIPS 186-4 में बताए गए तरीके के मुताबिक, SHA-256 को हैश फ़ंक्शन के तौर पर इस्तेमाल करके NIST P-256 पर ECDSA.
हस्ताक्षर
हस्ताक्षर, मैसेज के सबसे बाहरी लेवल में शामिल होता है. इसे ASN.1 बाइट फ़ॉर्मैट में base64 के साथ एन्कोड किया जाता है. ASN.1 के बारे में ज़्यादा जानकारी के लिए, IETF Tools Appendix A देखें. हस्ताक्षर में ECDSA पूर्णांक r और s शामिल होते हैं. ज़्यादा जानकारी के लिए, हस्ताक्षर जनरेट करने का एल्गोरिदम देखें.
यहां ASN.1 बाइट फ़ॉर्मैट का एक उदाहरण दिया गया है. यह Java Cryptography Extension (JCE) ECDSA के लागू करने से जनरेट होने वाला स्टैंडर्ड फ़ॉर्मैट है.
ECDSA-Sig-Value :: = SEQUENCE {
r INTEGER,
s INTEGER
}इंटरमीडिएट साइनिंग की के हस्ताक्षर के लिए बाइट-स्ट्रिंग बनाने का तरीका
पेमेंट के तरीके के सैंपल टोकन में, इंटरमीडिएट साइनिंग कुंजी के हस्ताक्षर की पुष्टि करने के लिए, signedStringForIntermediateSigningKeySignature को इस फ़ॉर्मूले के साथ बनाएं:
signedStringForIntermediateSigningKeySignature = length_of_sender_id || sender_id || length_of_protocol_version || protocol_version || length_of_signed_key || signed_key
"||" नोटेशन का मतलब है कि दो स्ट्रिंग को एक साथ जोड़ना. हर कॉम्पोनेंट—sender_id,
protocolVersion, signedKey—को UTF-8 में एन्कोड किया जाना चाहिए. signedKey, intermediateSigningKey.signedKey की स्ट्रिंग होनी चाहिए.
हर कॉम्पोनेंट की बाइट की लंबाई, लिटिल-एंडियन फ़ॉर्मैट में 4 बाइट होती है.
उदाहरण
इस उदाहरण में, पेमेंट के तरीके के इस सैंपल टोकन का इस्तेमाल किया गया है:
{
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}sender_id हमेशा Google होता है और protocol_version हमेशा ECv2 होता है.
अगर sender_id Google है, तो signedString इस उदाहरण में दिखाए गए तरीके से दिखेगा:
signedStringForIntermediateSigningKeySignature =
\x06\x00\x00\x00 || Google || | \x04\x00\x00\x00 || ECv2 || \xb5\x00\x00\x00 || {"keyExpiration":"1542323393147","keyValue":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\u003d\u003d"}signedStringForIntermediateSigningKeySignature पर मौजूद हस्ताक्षर की पुष्टि कैसे करें
जब इंटरमीडिएट साइनिंग पासकोड के सिग्नेचर के लिए साइन की गई स्ट्रिंग को असेंबल किया जाता है, तब स्टैंडर्ड ईसीडीएसए पुष्टि करने वाले एल्गोरिदम का इस्तेमाल किया जाता है. ECv2 प्रोटोकॉल के लिए, आपको intermediateSigningKey.signatures में मौजूद सभी हस्ताक्षर दोहराने होंगे. साथ ही, keys.json में मौजूद Google के ऐसे हस्ताक्षर करने वाले सभी कुंजी की पुष्टि करनी होगी जिनकी समयसीमा खत्म नहीं हुई है. अगर कम से कम एक हस्ताक्षर की पुष्टि हो जाती है, तो पुष्टि की प्रक्रिया पूरी मानी जाएगी. intermediateSigningKey.signedKey.keyValue की पुष्टि करने के लिए, बाद में intermediateSigningKey.signedKey.keyValue का इस्तेमाल करें.signedStringForMessageSignature Google का सुझाव है कि आप पुष्टि करने के लिए, अपने कोड के बजाय क्रिप्टोग्राफ़िक लाइब्रेरी का इस्तेमाल करें.
मैसेज के हस्ताक्षर के लिए बाइट-स्ट्रिंग बनाने का तरीका
पेमेंट के तरीके के सैंपल टोकन में मौजूद हस्ताक्षर की पुष्टि करने के लिए, signedStringForMessageSignature को इस फ़ॉर्मूले के हिसाब से बनाएं:
signedStringForMessageSignature = length_of_sender_id || sender_id || length_of_recipient_id || recipient_id || length_of_protocolVersion || protocolVersion || length_of_signedMessage || signedMessage
"||" नोटेशन का मतलब है कि दो स्ट्रिंग को एक साथ जोड़ना. हर कॉम्पोनेंट—sender_id, recipient_id, protocolVersion, signedMessage—को UTF-8 में एन्कोड किया जाना चाहिए. हर कॉम्पोनेंट की बाइट की लंबाई, लिटिल-एंडियन फ़ॉर्मैट में 4 बाइट होती है. बाइट स्ट्रिंग बनाते समय, signedMessage को पार्स या उसमें बदलाव न करें. उदाहरण के लिए, \u003d को = वर्ण से न बदलें.
उदाहरण
यहां पेमेंट के तरीके के टोकन का एक उदाहरण दिया गया है:
{
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}sender_id हमेशा Google होता है और recipient_id हमेशा merchant:merchantId होता है. merchantId की वैल्यू, प्रोडक्शन ऐक्सेस वाले कारोबारियों या कंपनियों के लिए Google Pay और Wallet Console में मौजूद वैल्यू से मेल खाती हो.
अगर sender_id Google है और recipient_id merchant:12345 है, तो signedString इस उदाहरण में दिखाए गए तरीके से दिखेगा:
signedStringForMessageSignature =
\x06\x00\x00\x00 || Google || \x0e\x00\x00\x00 || merchant:12345 || | \x04\x00\x00\x00 || ECv2 || \xd2\x00\x00\x00 || {"tag":"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\u003d","ephemeralPublicKey":"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\u003d","encryptedMessage":"mKOoXwi8OavZ"}signedStringForMessageSignature पर मौजूद हस्ताक्षर की पुष्टि कैसे करें
हस्ताक्षर की गई स्ट्रिंग को असेंबल करते समय, ईसीडीएसए की पुष्टि करने वाले स्टैंडर्ड एल्गोरिदम का इस्तेमाल किया जाता है. पिछले चरण में पुष्टि किए गए intermediateSigningKey.signedKey.keyValue का इस्तेमाल, signedMessage की पुष्टि करने के लिए किया जाता है. Google का सुझाव है कि आप पुष्टि करने के लिए, अपने कोड के बजाय क्रिप्टोग्राफ़िक लाइब्रेरी का इस्तेमाल करें.
एन्क्रिप्शन स्कीम की खास जानकारी
Google, Google Pay API के जवाब में मिले पेमेंट के तरीके के टोकन को सुरक्षित रखने के लिए, Elliptic Curve Integrated Encryption Scheme (ECIES) का इस्तेमाल करता है. एन्क्रिप्शन स्कीम में इन पैरामीटर का इस्तेमाल किया जाता है:
| पैरामीटर | परिभाषा |
|---|---|
| कुंजी को कैप्सूल में बदलने का तरीका | ईसीआईईएस-केईएम, जैसा कि आईएसओ 18033-2 में बताया गया है.
|
| की डेरिवेशन फ़ंक्शन | SHA-256 (
|
| सिमेट्रिक एन्क्रिप्शन एल्गोरिदम |
DEM2, जैसा कि ISO 18033-2 में बताया गया है एन्क्रिप्शन एल्गोरिदम: AES-256-CTR, जिसमें IV शून्य है और पैडिंग नहीं की गई है. |
| एमएसी एल्गोरिदम | HMAC_SHA256 का इस्तेमाल करके एन्क्रिप्ट (सुरक्षित) किया जाता है. यह 256-बिट की कुंजी, की डेरिवेशन फ़ंक्शन से मिलती है. |
एन्क्रिप्ट (सुरक्षित) करने के लिए इस्तेमाल होने वाली सार्वजनिक कुंजी का फ़ॉर्मैट
एन्क्रिप्शन की सार्वजनिक कुंजी और Google पेलोड में ephemeralPublicKey वापस भेजी गई कुंजियों को, बिना कंप्रेस किए गए पॉइंट फ़ॉर्मैट में कुंजी के base64 कोड में बदले गए फ़ॉर्मैट में फ़ॉर्मैट किया जाता है. इसमें ये दो एलिमेंट शामिल होते हैं:
- एक मैजिक नंबर, जो फ़ॉर्मैट (0x04) के बारे में बताता है.
- ये 32 बाइट के दो बड़े पूर्णांक होते हैं. ये एलिप्टिक कर्व में X और Y कोऑर्डिनेट दिखाते हैं.
इस फ़ॉर्मैट के बारे में ज़्यादा जानकारी के लिए, "Public Key Cryptography For The Financial Services Industry: The Elliptic Curve Digital Signature Algorithm (ECDSA)," ANSI X9.62, 1998 पढ़ें.
सार्वजनिक पासकोड जनरेट करने के लिए OpenSSL का इस्तेमाल करना
पहला चरण: निजी कुंजी जनरेट करना
यहां दिए गए उदाहरण में, NIST P-256 के साथ इस्तेमाल करने के लिए सही एलिप्टिक कर्व निजी पासकोड जनरेट किया गया है. साथ ही, इसे key.pem में लिखा गया है:
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
ज़रूरी नहीं: निजी और सार्वजनिक कुंजियां देखना
निजी और सार्वजनिक, दोनों कुंजियां देखने के लिए, यहां दिया गया निर्देश इस्तेमाल करें:
openssl ec -in key.pem -pubout -text -noout
इस कमांड से, यहां दिए गए आउटपुट जैसा आउटपुट मिलता है:
read EC key
Private-Key: (256 bit)
priv:
08:f4:ae:16:be:22:48:86:90:a6:b8:e3:72:11:cf:
c8:3b:b6:35:71:5e:d2:f0:c1:a1:3a:4f:91:86:8a:
f5:d7
pub:
04:e7:68:5c:ff:bd:02:ae:3b:dd:29:c6:c2:0d:c9:
53:56:a2:36:9b:1d:f6:f1:f6:a2:09:ea:e0:fb:43:
b6:52:c6:6b:72:a3:f1:33:df:fa:36:90:34:fc:83:
4a:48:77:25:48:62:4b:42:b2:ae:b9:56:84:08:0d:
64:a1:d8:17:66
ASN1 OID: prime256v1
दूसरा चरण: Base64 से कोड में बदली गई सार्वजनिक कुंजी जनरेट करना
पिछले ज़रूरी नहीं है चरण के उदाहरण में जनरेट की गई निजी और सार्वजनिक पासकोड, हेक्साडेसिमल में कोड की गई है. बिना कंप्रेस किए गए पॉइंट फ़ॉर्मैट में, Base64 से कोड में बदली गई सार्वजनिक कुंजी पाने के लिए, यह कमांड इस्तेमाल करें:
openssl ec -in key.pem -pubout -text -noout 2> /dev/null | grep "pub:" -A5 | sed 1d | xxd -r -p | base64 | paste -sd "\0" - | tr -d '\n\r ' > publicKey.txt
इस कमांड से एक publicKey.txt फ़ाइल जनरेट होती है. इसका कॉन्टेंट, बिना कंप्रेस किए गए पॉइंट फ़ॉर्मैट में मौजूद कुंजी का base64 वर्शन होता है. यह इस तरह दिखता है:
BOdoXP+9Aq473SnGwg3JU1aiNpsd9vH2ognq4PtDtlLGa3Kj8TPf+jaQNPyDSkh3JUhiS0KyrrlWhAgNZKHYF2Y=
फ़ाइल के कॉन्टेंट में, ज़रूरत से ज़्यादा खाली जगह या नई लाइन शुरू करने का निशान नहीं होना चाहिए. इसकी पुष्टि करने के लिए, Linux या MacOS में यह कमांड चलाएं:
od -bc publicKey.txt
तीसरा चरण: PKCS #8 फ़ॉर्मैट में base64-encoded निजी पासकोड जनरेट करना
Tink लाइब्रेरी को आपकी निजी कुंजी की ज़रूरत होती है. यह कुंजी, PKCS #8 फ़ॉर्मैट में base64-एन्कोड की गई होनी चाहिए. पहले चरण में जनरेट की गई निजी कुंजी से, इस फ़ॉर्मैट में निजी कुंजी जनरेट करने के लिए, यहां दिया गया निर्देश इस्तेमाल करें:
openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -nocrypt | base64 | paste -sd "\0" -
इस कमांड से, यहां दिए गए आउटपुट जैसा आउटपुट मिलता है:
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWV4oK8c/MZkCLk4qSCNjW0Zm6H0CBCtSYxkXkC9FBHehRANCAAQPldOnhO2/oXjdJD1dwlFPiNs6fcdoRgFu3/Z0iKj24SjTGyLRGAtYWLGXBZcDdPj3T2bJRHRVhE8Bc2AjkT7n
पेमेंट के तरीके के टोकन को डिक्रिप्ट करने का तरीका
टोकन को डिक्रिप्ट करने के लिए, यह तरीका अपनाएं:
- अपनी निजी कुंजी और दिए गए
ephemeralPublicKeyका इस्तेमाल करके, 512 बिट लंबी शेयर की गई कुंजी बनाएं. यह कुंजी ECIES-KEM का इस्तेमाल करती है. इन पैरामीटर का इस्तेमाल करें: - एलिप्टिक कर्व: NIST P-256, जिसे OpenSSL में prime256v1 के नाम से भी जाना जाता है.
CheckMode,OldCofactorMode,SingleHashMode, औरCofactorMode,0हैं.- एन्कोडिंग फ़ंक्शन: बिना कंप्रेस किया गया पॉइंट फ़ॉर्मैट.
- मुख्य डेरिवाइशन फ़ंक्शन: RFC 5869 में बताए गए तरीके के मुताबिक HKDFwithSHA256, इन पैरामीटर के साथ:
- नमक नहीं दिया जाना चाहिए. RFC के मुताबिक, यह 32 शून्य वाले बाइट के सॉल्ट के बराबर होना चाहिए.
- जनरेट की गई कुंजी को 256 बिट की दो कुंजियों में बांटें:
symmetricEncryptionKeyऔरmacKey. पुष्टि करें कि
tagफ़ील्ड,encryptedMessageके लिए मान्य MAC है.अनुमानित एमएसी जनरेट करने के लिए, SHA256 हैश फ़ंक्शन के साथ एचएमएसी (RFC 5869) का इस्तेमाल करें. साथ ही, दूसरे चरण में मिला
macKeyइस्तेमाल करें.एईएस-256-सीटीआर मोड का इस्तेमाल करके
encryptedMessageको डिक्रिप्ट करें. साथ ही, इन चीज़ों का इस्तेमाल करें:- शून्य आईवी.
- पैडिंग नहीं की गई है.
symmetricEncryptionKey, जिसे दूसरे चरण में निकाला गया है.
कुंजी मैनेजमेंट
कारोबारी या कंपनी के लिए एन्क्रिप्ट (सुरक्षित) करने की कुंजियां
कारोबारी या कंपनियां, एन्क्रिप्शन स्कीम की खास जानकारी में बताई गई खास बातों के मुताबिक, सार्वजनिक कुंजी जनरेट करती हैं.
Google की रूट साइनिंग कुंजियां
लेख पढ़ें.Google, फ़िलहाल मान्य रूट साइनिंग की सार्वजनिक कुंजियों का सेट पब्लिश करता है. इसे सार्वजनिक यूआरएल से फ़ेच किया जा सकता है. कुंजियां तब तक मान्य रहती हैं, जब तक यूआरएल से मिले एचटीटीपी कैश हेडर मान्य रहते हैं. ये तब तक कैश मेमोरी में सेव रहते हैं, जब तक इनकी समयसीमा खत्म नहीं हो जाती. इनकी समयसीमा keyExpiration फ़ील्ड से तय होती है. हमारा सुझाव है कि फ़ेच करने की अवधि खत्म होने पर, सार्वजनिक यूआरएल से कुंजियां फिर से फ़ेच करें, ताकि आपको मान्य कुंजियों की मौजूदा सूची मिल सके.
ECv2 प्रोटोकॉल के लिए अपवाद: अगर आपको रनटाइम में Google से कुंजियां नहीं मिल रही हैं, तो हमारे प्रोडक्शन यूआरएल से keys.json फ़ेच करें, इसे अपने सिस्टम में सेव करें, और समय-समय पर इसे मैन्युअल तरीके से रीफ़्रेश करें. आम तौर पर, Google सबसे ज़्यादा समय तक इस्तेमाल की जा सकने वाली रूट साइनिंग की की समयसीमा खत्म होने से पांच साल पहले, ECv2 के लिए नई रूट साइनिंग की जारी करता है. अगर किसी मुख्य कुंजी से समझौता किया जाता है, तो Google सभी कारोबारियों या कंपनियों को इसकी सूचना देता है. यह सूचना, सेल्फ-सर्विस पोर्टल में दी गई संपर्क जानकारी के ज़रिए दी जाती है. इससे, keys.json को तुरंत रिलोड करने का अनुरोध किया जा सकता है. यह पक्का करने के लिए कि आपको नियमित रोटेशन का फ़ायदा मिलता रहे, हमारा सुझाव है कि जिन कारोबारियों या कंपनियों ने Google की कुंजियों को keys.json के कॉन्टेंट में सेव करने का विकल्प चुना है वे हर साल अपनी कुंजी को रोटेट करें.
सार्वजनिक यूआरएल के ज़रिए दी गई कुंजियों को इस फ़ॉर्मैट में मैप किया जाता है:
{ "keys": [ { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"2000000000000" }, { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"3000000000000" } ] }
keyValue, ASN.1 टाइप SubjectPublicKeyInfo में कोड में बदली गई कुंजी का base64 वर्शन है. इसे X.509 स्टैंडर्ड में तय किया गया है. इसे रैप या पैड नहीं किया गया है. Java में, रेफ़र किए गए ASN.1 एन्कोडिंग को X509EncodedKeySpec क्लास के ज़रिए दिखाया जाता है.
इसे ECPublicKey.getEncoded() के साथ इस्तेमाल किया जा सकता है.
टेस्ट और प्रोडक्शन एनवायरमेंट, दोनों के लिए यूआरएल यहां दिए गए हैं:
- टेस्ट:
https://payments.developers.google.com/paymentmethodtoken/test/keys.json - प्रोडक्शन:
https://payments.developers.google.com/paymentmethodtoken/keys.json
डेटा सुरक्षित करने वाली कुंजी का नया वर्शन बनाना
अगर आपने सीधे इंटिग्रेशन की मदद से, पेमेंट के तरीके के टोकन को सीधे अपने सर्वर पर डिक्रिप्ट किया है, तो आपको हर साल कुंजियां बदलनी होंगी.
एन्क्रिप्शन कुंजियों को रोटेट करने के लिए, यह तरीका अपनाएं:
- OpenSSL का इस्तेमाल करके, नई कुंजी का जोड़ा जनरेट करें.
- Google Pay और Wallet Console खोलें. इसके लिए, उस Google खाते का इस्तेमाल करें जिससे आपने Google Pay के लिए डेवलपर के तौर पर साइन अप किया था.
- Google Pay API टैब में, सीधे तौर पर इंटिग्रेट करना पैनल में जाकर, अपनी मौजूदा सार्वजनिक पासकोड के बगल में मौजूद, मैनेज करें पर क्लिक करें. दूसरी कुंजी जोड़ें पर क्लिक करें.
- सार्वजनिक एन्क्रिप्शन कुंजी टेक्स्ट इनपुट फ़ील्ड चुनें और अपनी नई जनरेट की गई सार्वजनिक कुंजी जोड़ें. यह कुंजी, बिना कंप्रेस किए गए पॉइंट फ़ॉर्मैट में Base64-एन्कोड की गई होनी चाहिए.
- एन्क्रिप्शन की सेव करें पर क्लिक करें.
कुंजी रोटेशन को बिना किसी रुकावट के पूरा करने के लिए, कुंजियों को बदलते समय नई और पुरानी, दोनों निजी कुंजियों से डिक्रिप्ट करने की सुविधा चालू रखें.
अगर टोकन को डिक्रिप्ट करने के लिए, Tink लाइब्रेरी का इस्तेमाल किया जाता है, तो एक से ज़्यादा निजी कुंजियों के साथ काम करने के लिए, यहां दिया गया Java कोड इस्तेमाल करें:
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .addRecipientPrivateKey(newPrivateKey) .addRecipientPrivateKey(oldPrivateKey);
पक्का करें कि डिक्रिप्ट करने का कोड, प्रोडक्शन में डिप्लॉय किया गया हो. साथ ही, यह भी पक्का करें कि डिक्रिप्ट करने की प्रोसेस सही तरीके से हो रही हो.
अपने कोड में इस्तेमाल की गई सार्वजनिक पासकोड बदलें.
PaymentMethodTokenizationSpecificationparametersप्रॉपर्टी में मौजूदpublicKeyएट्रिब्यूट की वैल्यू बदलें:const tokenizationSpecification = { "type": "DIRECT", "parameters": { "protocolVersion": "ECv2", "publicKey": "BOdoXP1aiNp.....kh3JUhiSZKHYF2Y=" } }
- चौथे चरण में मिले कोड को प्रोडक्शन में डिप्लॉय करें. कोड को डिप्लॉय करने के बाद, एन्क्रिप्ट (सुरक्षित) करने और डिक्रिप्ट (सुरक्षित नहीं) करने के लेन-देन के लिए, नए पासकोड के जोड़े का इस्तेमाल किया जाता है.
पुष्टि करें कि पुरानी सार्वजनिक कुंजी का इस्तेमाल अब किसी भी लेन-देन को एन्क्रिप्ट (सुरक्षित) करने के लिए नहीं किया जाता है.
- पुरानी निजी कुंजी हटाएं.
- Google Pay और Wallet Console खोलें. इसके लिए, उस Google खाते से साइन इन करें जिसका इस्तेमाल आपने पहले Google Pay के साथ डेवलपर के तौर पर साइन अप करने के लिए किया था.
- Google Pay API टैब में, सीधे तौर पर इंटिग्रेट करना पैनल में जाकर, अपनी मौजूदा सार्वजनिक पासकोड के बगल में मौजूद, मैनेज करें पर क्लिक करें. अपनी पुरानी सार्वजनिक पासकोड के बगल में मौजूद, मिटाएं पर क्लिक करें. इसके बाद, सुरक्षा कुंजियां सेव करें पर क्लिक करें.
Google, PaymentMethodTokenizationSpecification parameters ऑब्जेक्ट में मौजूद publicKey प्रॉपर्टी में दिए गए कुंजी का इस्तेमाल करता है. इसका उदाहरण यहां दिया गया है:
{
"protocolVersion": "ECv2",
"publicKey": "BOdoXP+9Aq473SnGwg3JU1..."
}एन्क्रिप्ट (सुरक्षित) किए गए रिस्पॉन्स को मैनेज करने के लिए, Tink लाइब्रेरी का इस्तेमाल करें
सिग्नेचर की पुष्टि करने और मैसेज को डिक्रिप्ट करने के लिए, Tink paymentmethodtoken लाइब्रेरी का इस्तेमाल करें. यह लाइब्रेरी सिर्फ़ Java में उपलब्ध है. इसका इस्तेमाल करने के लिए, यह तरीका अपनाएं:
अपनी
pom.xmlफ़ाइल में, Tinkpaymentmethodtokenऐप्लिकेशन को डिपेंडेंसी के तौर पर जोड़ें:<dependencies> <!-- other dependencies ... --> <dependency> <groupId>com.google.crypto.tink</groupId> <artifactId>apps-paymentmethodtoken</artifactId> <version>1.9.1</version> <!-- or latest version --> </dependency> </dependencies>सर्वर शुरू होने पर, Google की साइनिंग कुंजियों को प्रीफ़ेच करें, ताकि कुंजी मेमोरी में उपलब्ध हो. इससे डिक्रिप्ट करने की प्रोसेस के दौरान, कुंजियां फ़ेच करते समय उपयोगकर्ता को नेटवर्क की किसी भी तरह की देरी नहीं दिखती.
GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION.refreshInBackground();
इस मैसेज को डिक्रिप्ट करने के लिए, यहां दिया गया कोड इस्तेमाल करें. इसमें यह माना गया है कि
paymentMethodTokenकोencryptedMessageवैरिएबल में सेव किया गया है. साथ ही, अपने इस्तेमाल के हिसाब से बोल्ड किए गए सेक्शन बदलें.नॉन-प्रोडक्शन टेस्ट के लिए,
INSTANCE_PRODUCTIONकी जगहINSTANCE_TESTका इस्तेमाल करें. अगर आपका इंटिग्रेशन चालू नहीं है या उसमें एन्क्रिप्शन कुंजी कॉन्फ़िगर नहीं की गई है, तो [YOUR MERCHANT ID] की जगह12345678901234567890का इस्तेमाल करें.- चालू है
- DIRECT इंटिग्रेशन की सुविधा चालू है
- जिसमें एन्क्रिप्शन की कॉन्फ़िगर की गई हो
[YOUR MERCHANT ID] को न बदलें.
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .fetchSenderVerifyingKeysWith( GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION) .recipientId("merchant:[YOUR MERCHANT ID]") // This guide applies only to protocolVersion = ECv2 .protocolVersion("ECv2") // Multiple private keys can be added to support graceful // key rotations. .addRecipientPrivateKey(PrivateKey1) .addRecipientPrivateKey(PrivateKey2) .build() .unseal(encryptedMessage);
PrivateKey1को उस सही निजी कुंजी की वैल्यू से बदलें जो Google के साथ रजिस्टर की गई सार्वजनिक कुंजी की वैल्यू से जुड़ी है. इसके लिए, अपने पासकोड तैयार करना और उन्हें Google पर रजिस्टर करना लेख पढ़ें. बाद में, एक से ज़्यादा अन्य निजी पासकोड वैल्यू जोड़ी जा सकती हैं. ऐसा तब किया जाता है, जब आपको Google के साथ कुंजियां रोटेट करनी हों. वैरिएबल, base64 कोड में बदली गई PKCS8 स्ट्रिंग याECPrivateKeyऑब्जेक्ट हो सकते हैं. base64-encoded PKCS8 निजी पासकोड बनाने के तरीके के बारे में ज़्यादा जानने के लिए, अपने पासकोड तैयार करना और उन्हें Google पर रजिस्टर करना लेख पढ़ें.अगर कुंजियों को डिक्रिप्ट करते समय, Google सर्वर को हर बार कॉल नहीं किया जा सकता, तो यहां दिए गए कोड का इस्तेमाल करके डिक्रिप्ट करें. साथ ही, अपने हिसाब से बोल्ड किए गए सेक्शन बदलें.
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .addSenderVerifyingKey("ECv2 key fetched from test or production url") .recipientId("merchant:[YOUR MERCHANT ID]") // This guide applies only to protocolVersion = ECv2 .protocolVersion("ECv2") // Multiple private keys can be added to support graceful // key rotations. .addRecipientPrivateKey(PrivateKey1) .addRecipientPrivateKey(PrivateKey2) .build() .unseal(encryptedMessage);
प्रोडक्शन एनवायरमेंट में मौजूद मौजूदा कुंजी, सामान्य परिस्थितियों में 14/04/2038 तक मान्य है. हालांकि, अगर कुंजी से समझौता किया जाता है, तो यह मान्य नहीं होगी. अगर किसी मुख्य कुंजी से समझौता किया जाता है, तो Google सभी कारोबारियों या कंपनियों को इसकी सूचना देता है. इसके लिए, वह सेल्फ़-सर्विस पोर्टल में दी गई संपर्क जानकारी का इस्तेमाल करता है. इससे,
keys.jsonको तुरंत रीलोड करने का अनुरोध किया जा सकता है.यह कोड स्निपेट, सुरक्षा से जुड़ी इन बातों का ध्यान रखता है, ताकि आप पेलोड के इस्तेमाल पर ध्यान दे सकें:
- Google की साइनिंग कुंजियां, मेमोरी में फ़ेच और कैश की जाती हैं
- हस्ताक्षर की पुष्टि करना
- डिक्रिप्शन