वेब पुश प्रोटोकॉल

हमने देखा है कि पुश मैसेज को ट्रिगर करने के लिए कैसे लाइब्रेरी का इस्तेमाल किया जा सकता है, लेकिन क्या ये लाइब्रेरी काम कर रही हैं?

वे नेटवर्क अनुरोध कर रहे हैं और यह सुनिश्चित कर रहे हैं कि सही फ़ॉर्मैट. इस नेटवर्क अनुरोध को परिभाषित करने वाली शर्त है वेब पुश प्रोटोकॉल.

आपके सर्वर से पुश मैसेज को पुश पर भेजने का डायग्राम
सेवा

यह सेक्शन बताता है कि सर्वर, ऐप्लिकेशन के साथ खुद की पहचान कैसे कर सकता है सर्वर कुंजियां क्या हैं और एन्क्रिप्ट किया गया पेलोड और उससे जुड़ा डेटा कैसे भेजा जाता है.

यह वेब पुश की सुविधा नहीं है और मुझे एन्क्रिप्ट (सुरक्षित) करने का कोई तरीका नहीं पता है. हालांकि, आइए जानते हैं कि क्योंकि उससे यह पता किया जा सकता है कि ये लाइब्रेरी क्या काम कर रही हैं.

ऐप्लिकेशन सर्वर कुंजियां

किसी उपयोगकर्ता को सदस्यता लेने पर, हम applicationServerKey भेजते हैं. यह कुंजी है पुश सेवा को पास किया जाता है और इसका इस्तेमाल यह जांचने के लिए किया जाता है कि सदस्यता लेने वाले ऐप्लिकेशन ने उपयोगकर्ता एक ऐसा ऐप्लिकेशन भी है जो पुश मैसेज ट्रिगर कर रहा है.

जब हम कोई पुश मैसेज ट्रिगर करते हैं, तो हेडर का एक सेट हम उसे भेजते हैं पुश सेवा को ऐप्लिकेशन की पुष्टि करने की अनुमति दें. (यह परिभाषित किया गया है VAPID की खास बातों में बताया जाएगा.)

इन सब का क्या मतलब है और असल में क्या होता है? इसलिए, आपकी जानकारी के लिए ऐप्लिकेशन सर्वर ऑथेंटिकेशन:

  1. ऐप्लिकेशन सर्वर, अपनी निजी ऐप्लिकेशन कुंजी से JSON की कुछ जानकारी पर साइन करता है.
  2. हस्ताक्षर की गई यह जानकारी पुश सेवा को, पोस्ट अनुरोध में हेडर के तौर पर भेजी जाती है.
  3. पुश सेवा, सेव की गई सार्वजनिक कुंजी का इस्तेमाल करती है. यह कुंजी उसे आपने जो जानकारी शेयर की है उसकी पुष्टि करने के लिए, pushManager.subscribe() सार्वजनिक पासकोड से जुड़ी निजी कुंजी होती है. याद रखें: सार्वजनिक पासकोड applicationServerKey ने सदस्यता लेने के लिए कॉल में पास किया.
  4. अगर हस्ताक्षर की गई जानकारी मान्य है, तो पुश सेवा पुश उपयोगकर्ता को कोई मैसेज न मिले.

जानकारी के इस फ़्लो का एक उदाहरण नीचे दिया गया है. (यह बताने के लिए नीचे बाईं ओर मौजूद लेजेंड को नोट करें सार्वजनिक और निजी पासकोड.)

इस इलस्ट्रेशन में दिखाया गया है कि
मैसेज

"हस्ताक्षर की गई जानकारी" अनुरोध के हेडर में एक JSON वेब टोकन जोड़ा गया है.

JSON वेब टोकन

JSON वेब टोकन (या कम शब्दों में JWT) किसी तीसरे पक्ष को मैसेज भेजना, ताकि पाने वाला व्यक्ति किसने भेजा है.

जब तीसरे पक्ष को कोई मैसेज मिलता है, तो उसे मैसेज भेजने वाले लोगों की जानकारी चाहिए होती है सार्वजनिक पासकोड दबाएं और JWT के हस्ताक्षर की पुष्टि करने के लिए इसका इस्तेमाल करें. अगर हस्ताक्षर मान्य है फिर JWT पर मेल खाने वाले हस्ताक्षर होने चाहिए निजी कुंजी होनी चाहिए, इसलिए इसे भेजने वाले की ओर से भेजा जाना चाहिए.

https://jwt.io/ पर ऐसी कई लाइब्रेरी मौजूद हैं जिन्हें आपके लिए साइन इन कर सकता/सकती हूं और मेरा सुझाव है कि आप वहीं से ऐसा करें कर सकते हैं. आइए, देखते हैं कि हस्ताक्षर की गई JWT कैसे मैन्युअल तरीके से बनाई जाती है.

वेब पुश और साइन किए गए JWT

साइन की गई JWT सिर्फ़ एक स्ट्रिंग होती है. हालांकि, ऐसा माना जा सकता है कि तीन स्ट्रिंग जुड़ी हुई हैं बिंदुओं से.

JSON वेब में स्ट्रिंग की इमेज
टोकन

पहली और दूसरी स्ट्रिंग (JWT की जानकारी और JWT का डेटा) ये हैं JSON जिसे base64 कोड में बदला गया है. इसका मतलब है कि इसे सार्वजनिक तौर पर पढ़ा जा सकता है.

पहली स्ट्रिंग में JWT के बारे में जानकारी होती है. इससे पता चलता है कि कौनसा एल्गोरिदम का इस्तेमाल हस्ताक्षर बनाने के लिए किया गया था.

वेब पुश के लिए JWT की जानकारी में नीचे दी गई जानकारी होनी चाहिए:

{
  "typ": "JWT",
  "alg": "ES256"
}

दूसरी स्ट्रिंग JWT डेटा है. यह JWT के ईमेल भेजने वाले के बारे में जानकारी देता है, जो इसका लक्ष्य क्या है और यह कितने समय तक मान्य है.

वेब पुश के लिए, डेटा का फ़ॉर्मैट ऐसा होगा:

{
  "aud": "https://some-push-service.org",
  "exp": "1469618703",
  "sub": "mailto:example@web-push-book.org"
}

aud वैल्यू "ऑडियंस" होती है. इसका मतलब है कि JWT किसके लिए है. वेब के लिए ऑडियंस, पुश सेवा है, इसलिए हम इसे पुश की शुरुआत की जगह पर सेट करते हैं सेवा.

exp वैल्यू, JWT की समयसीमा खत्म हो जाती है. यह स्नूपर को वे किसी JWT को बाधित कर सकते हैं. समयसीमा खत्म होने की तारीख, टाइमस्टैंप है सेकंड और 24 घंटे से ज़्यादा का नहीं होना चाहिए.

Node.js में समयसीमा खत्म होने की तारीख, इन चीज़ों का इस्तेमाल करके सेट की जाती है:

Math.floor(Date.now() / 1000) + 12 * 60 * 60;

24 घंटे के बजाय 12 घंटे बचे हैं भेजने वाले ऐप्लिकेशन और पुश सेवा के बीच घड़ी के अंतर की कोई भी समस्या.

आखिर में, sub वैल्यू को कोई यूआरएल या mailto ईमेल पता होना चाहिए. ऐसा इसलिए किया जाता है, ताकि अगर भेजने वाले से संपर्क करने के लिए पुश सेवा की ज़रूरत पड़े, तो वह से संपर्क जानकारी मिलेगी. (इसलिए वेब-पुश लाइब्रेरी को ईमेल पता).

JWT की जानकारी की तरह, JWT डेटा को यूआरएल के हिसाब से सुरक्षित base64 के तौर पर एन्कोड किया जाता है स्ट्रिंग.

तीसरी स्ट्रिंग, हस्ताक्षर, पहली दो स्ट्रिंग को लेने का नतीजा है (JWT Info और JWT डेटा). "बिना हस्ताक्षर वाला टोकन" को कॉल करें और उस पर हस्ताक्षर करें.

हस्ताक्षर करने की प्रोसेस में, "साइन नहीं किए गए टोकन" को एन्क्रिप्ट (सुरक्षित) करना ज़रूरी होता है ES256 का इस्तेमाल करके. JWT के मुताबिक spec में, ES256, P-256 कर्व का इस्तेमाल करके "ECDSA" का छोटा रूप और SHA-256 हैश एल्गोरिदम" का इस्तेमाल किया जाएगा. वेब क्रिप्टो का इस्तेमाल करके, इस तरह से सिग्नेचर बनाया जा सकता है:

// Utility function for UTF-8 encoding a string to an ArrayBuffer.
const utf8Encoder = new TextEncoder('utf-8');

// The unsigned token is the concatenation of the URL-safe base64 encoded
// header and body.
const unsignedToken = .....;

// Sign the |unsignedToken| using ES256 (SHA-256 over ECDSA).
const key = {
  kty: 'EC',
  crv: 'P-256',
  x: window.uint8ArrayToBase64Url(
    applicationServerKeys.publicKey.subarray(1, 33)),
  y: window.uint8ArrayToBase64Url(
    applicationServerKeys.publicKey.subarray(33, 65)),
  d: window.uint8ArrayToBase64Url(applicationServerKeys.privateKey),
};

// Sign the |unsignedToken| with the server's private key to generate
// the signature.
return crypto.subtle.importKey('jwk', key, {
  name: 'ECDSA', namedCurve: 'P-256',
}, true, ['sign'])
.then((key) => {
  return crypto.subtle.sign({
    name: 'ECDSA',
    hash: {
      name: 'SHA-256',
    },
  }, key, utf8Encoder.encode(unsignedToken));
})
.then((signature) => {
  console.log('Signature: ', signature);
});

पुश सेवा, सार्वजनिक ऐप्लिकेशन सर्वर कुंजी का इस्तेमाल करके JWT की पुष्टि कर सकती है ताकि हस्ताक्षर को डिक्रिप्ट किया जा सके. साथ ही, यह पक्का किया जा सके कि डिक्रिप्ट की गई स्ट्रिंग वही हो "बिना हस्ताक्षर वाले टोकन" के तौर पर (जैसे, JWT की पहली दो स्ट्रिंग).

हस्ताक्षर किया गया JWT (यानी बिंदु से जोड़ी गई सभी तीन स्ट्रिंग), वेब पर भेजा जाता है पुश सेवा को Authorization हेडर के तौर पर जोड़ने के लिए, WebPush को पहले जोड़ा जाता है, जैसे:

Authorization: 'WebPush [JWT Info].[JWT Data].[Signature]';

वेब पुश प्रोटोकॉल यह भी बताता है कि सार्वजनिक ऐप्लिकेशन सर्वर कुंजी को इसे Crypto-Key हेडर में, यूआरएल के हिसाब से सुरक्षित base64 कोड में बदली गई स्ट्रिंग के तौर पर भेजा गया है. p256ecdsa= उससे पहले जोड़ा गया.

Crypto-Key: p256ecdsa=[URL Safe Base64 Public Application Server Key]

पेलोड एन्क्रिप्ट (सुरक्षित) करने का तरीका

आइए देखते हैं कि हम पुश मैसेज के साथ पेलोड कैसे भेज सकते हैं, ताकि जब हमारा वेब ऐप्लिकेशन को एक पुश मैसेज मिलता है, तो वह उसे मिलने वाले डेटा को ऐक्सेस कर सकता है.

अन्य पुश सेवाओं का उपयोग करने वाले लोगों में एक आम सवाल यह उठता है कि वेब क्या पेलोड को एन्क्रिप्ट (सुरक्षित) करना है? खास ऐप्लिकेशन की मदद से, पुश मैसेज से डेटा को सादे टेक्स्ट के तौर पर भेजा जा सकता है.

वेब पुश की खूबसूरती का एक हिस्सा यह भी है कि सभी पुश सेवाएं एक ही एपीआई (वेब पुश प्रोटोकॉल) के बिना, डेवलपर को इस बात की परवाह नहीं करनी होती कि पुश सर्विस है. हम सही फ़ॉर्मैट में अनुरोध कर सकते हैं. साथ ही, पुश मैसेज भेजने के लिए कहें. इसका नकारात्मक पहलू यह है कि डेवलपर ताकि किसी ऐसी पुश सेवा पर मैसेज भेजे जा सकें जो भरोसेमंद नहीं है. इन्होंने बदलाव किया है पेलोड को एन्क्रिप्ट (सुरक्षित) करने पर, पुश सेवा, भेजे गए डेटा को पढ़ नहीं सकती. सिर्फ़ ब्राउज़र इस जानकारी को डिक्रिप्ट कर सकता है. इससे उपयोगकर्ता की डेटा शामिल है.

पेलोड को एन्क्रिप्ट (सुरक्षित) करने का तरीका, मैसेज एन्क्रिप्शन में बताया गया है खास जानकारी.

पुश मैसेज पेलोड को एन्क्रिप्ट (सुरक्षित) करने के खास तरीके देखने से पहले, हमें कुछ ऐसी तकनीकों के बारे में बताना होगा जिनका इस्तेमाल एन्क्रिप्ट (सुरक्षित) करने के दौरान किया जाएगा प्रोसेस. (पुश पर उनके शानदार लेख के लिए, मैट स्केल्स को हैट की सलाह देता है) encryption.)

ईसीडीएच और एचकेडीएफ़

ECDH और HKDF दोनों का इस्तेमाल, एन्क्रिप्ट (सुरक्षित) करने की पूरी प्रोसेस में किया जाता है. इससे का मकसद जानकारी को एन्क्रिप्ट करना है.

ईसीडीएच: एलिप्टिक कर्व डिफ़ी-हेलमैन की एक्सचेंज

मान लें कि आपको जानकारी शेयर करनी है, ऐलिस और बॉब. अभिषेक और गुंजन, दोनों के पास अपनी सार्वजनिक और निजी कुंजियां हैं. एलिस और बॉब एक-दूसरे के साथ अपनी सार्वजनिक कुंजियां शेयर करें.

ईसीडीएच से जनरेट की गई कुंजियों का यह फ़ायदा होता है कि ऐलिस उनका इस्तेमाल करके, अपनी सीक्रेट वैल्यू 'X' बनाने के लिए निजी पासकोड और बॉब की सार्वजनिक कुंजी का इस्तेमाल करें. बॉब यह कर सकते हैं वह भी, अपनी निजी कुंजी और ऐलिस की सार्वजनिक कुंजी को स्वतंत्र रूप से वही मान 'X' बनाएं. इससे 'X' बन जाता है एक शेयर किया हुआ सीक्रेट साथ ही, ऐलिस और बॉब को सिर्फ़ अपनी सार्वजनिक कुंजी शेयर करनी पड़ी. अब बॉब और ऐलिस 'X' का उपयोग कर सकते हैं का इस्तेमाल किया जा सके, ताकि मैसेज को एन्क्रिप्ट (सुरक्षित) और डिक्रिप्ट किया जा सके.

मेरी जानकारी के मुताबिक ECDH, कर्व के उन गुणों को तय करता है जो इस "फ़ीचर" को अनुमति देते हैं कि एक शेयर गुप्त 'X' बनाया जा सकता है.

ईसीडीएच के बारे में यह खास जानकारी है. अगर आपको इस बारे में ज़्यादा जानना है, तो मेरा सुझाव है कि आप यह वीडियो देखें.

अगर कोड का इस्तेमाल किया जाए, तो; ज़्यादातर भाषाओं / प्लैटफ़ॉर्म में लाइब्रेरी की सुविधा मौजूद होती है, ऐसी चाबियों को जनरेट करना आसान है.

नोड में हमें ये काम करने होंगे:

const keyCurve = crypto.createECDH('prime256v1');
keyCurve.generateKeys();

const publicKey = keyCurve.getPublicKey();
const privateKey = keyCurve.getPrivateKey();

HKDF: एचएमएसी आधारित की डेरिवेशन फ़ंक्शन

Wikipedia में HKDF के बारे में कम शब्दों में जानकारी दी गई है:

HKDF, एचएमएसी पर आधारित एक 'की डेरिवेशन फ़ंक्शन' है, जो किसी भी कमज़ोर कुंजी को बदल देता है को क्रिप्टोग्राफ़िक तौर पर मज़बूत बनाया गया है. इसका इस्तेमाल इन कामों के लिए किया जा सकता है उदाहरण के लिए, डिफ़ी हेलमैन ने साझा रहस्यों का इस्तेमाल अहम सामग्री में किया, एन्क्रिप्शन, इंटिग्रिटी जांच या पुष्टि करने के लिए इस्तेमाल किया जा सकता है.

दरअसल, HKDF वह इनपुट लेगा जो ज़्यादा सुरक्षित नहीं है. इससे उसे ज़्यादा सुरक्षित बनाया जा सकता है.

इस एन्क्रिप्शन की खास बात के लिए, हैश एल्गोरिदम के तौर पर SHA-256 का इस्तेमाल करना ज़रूरी है और वेब पुश में HKDF के नतीजे के तौर पर मिलने वाली कुंजियां 256 बिट से ज़्यादा नहीं होनी चाहिए (32 बाइट).

नोड में यह इस तरह लागू किया जा सकता है:

// Simplified HKDF, returning keys up to 32 bytes long
function hkdf(salt, ikm, info, length) {
  // Extract
  const keyHmac = crypto.createHmac('sha256', salt);
  keyHmac.update(ikm);
  const key = keyHmac.digest();

  // Expand
  const infoHmac = crypto.createHmac('sha256', key);
  infoHmac.update(info);

  // A one byte long buffer containing only 0x01
  const ONE_BUFFER = new Buffer(1).fill(1);
  infoHmac.update(ONE_BUFFER);

  return infoHmac.digest().slice(0, length);
}

इस उदाहरण कोड के लिए मैट स्केल के लेख के लिए हैट टिप.

इसमें ECDH के नियमों में आम तौर पर शामिल किया गया है और HKDF.

ECDH, सार्वजनिक कुंजियों को शेयर करने और शेयर किए गए सीक्रेट जनरेट करने का एक सुरक्षित तरीका है. एचकेडीएफ़ बेहतरीन विकल्प है को सुरक्षित बनाया जा सकता है और उसे सुरक्षित बनाया जा सकता है.

इसका इस्तेमाल हमारे पेलोड को एन्क्रिप्ट (सुरक्षित) करने के दौरान किया जाएगा. चलिए, अब देखते हैं कि हम कैसे एन्क्रिप्ट करें.

इनपुट

जब हम पेलोड वाले किसी उपयोगकर्ता को पुश मैसेज भेजना चाहते हैं, तो हमें तीन इनपुट की ज़रूरत होती है:

  1. पेलोड.
  2. PushSubscription से मिला auth सीक्रेट.
  3. PushSubscription से मिला p256dh बटन.

हमने देखा है कि auth और p256dh वैल्यू, PushSubscription से वापस लाई जा रही हैं, लेकिन याद रखें, आपको जिस सदस्यता की ज़रूरत है उसे देखते हुए हमें इन वैल्यू की ज़रूरत होगी:

subscription.toJSON().keys.auth;
subscription.toJSON().keys.p256dh;

subscription.getKey('auth');
subscription.getKey('p256dh');

auth की वैल्यू को सीक्रेट माना जाना चाहिए. इसे आपके ऐप्लिकेशन के बाहर शेयर नहीं किया जाना चाहिए.

p256dh कुंजी एक सार्वजनिक कुंजी है. इसे कभी-कभी क्लाइंट सार्वजनिक कुंजी भी कहा जाता है. यहां हम p256dh को सदस्यता की सार्वजनिक कुंजी मानेंगे. सदस्यता की सार्वजनिक कुंजी जनरेट होती है ब्राउज़र से. ब्राउज़र निजी कुंजी को गोपनीय रखेगा और उसका उपयोग पेलोड.

इन तीन मानों, auth, p256dh, और payload को इनपुट के रूप में और इस तरह के नतीजे के रूप में ज़रूरी एन्क्रिप्शन प्रक्रिया में एन्क्रिप्ट किया गया पेलोड, सॉल्ट वैल्यू, और सिर्फ़ डेटा को एन्क्रिप्ट करने में मदद करता है.

साल्ट

सॉल्ट का रैंडम डेटा 16 बाइट होना चाहिए. NodeJS में, सॉल्ट बनाने के लिए हमें ये काम करने होंगे:

const salt = crypto.randomBytes(16);

सार्वजनिक / निजी कुंजियां

सार्वजनिक और निजी पासकोड, P-256 एलिप्टिक कर्व का इस्तेमाल करके जनरेट किए जाने चाहिए, जिसे हम नोड में करेंगे, जैसा:

const localKeysCurve = crypto.createECDH('prime256v1');
localKeysCurve.generateKeys();

const localPublicKey = localKeysCurve.getPublicKey();
const localPrivateKey = localKeysCurve.getPrivateKey();

हम इन कुंजियों को "लोकल बटन" कहेंगे. इनका इस्तेमाल सिर्फ़ एन्क्रिप्ट (सुरक्षित) करने के लिए किया जाता है. ऐप्लिकेशन सर्वर कुंजियों के साथ कुछ भी नहीं करना.

इनपुट के तौर पर पेलोड, पुष्टि करने वाले सीक्रेट, और सदस्यता सार्वजनिक पासकोड के साथ और नए जनरेट किए गए और स्थानीय कुंजियों के सेट हैं, तो हम वास्तव में कुछ एन्क्रिप्शन करने के लिए तैयार हैं.

शेयर किया गया सीक्रेट

पहला चरण है, सदस्यता की सार्वजनिक कुंजी और हमारी नई निजी पासकोड (याद रखें कि ऐलिस और बॉब के साथ ईसीडीएच के बारे में जानकारी क्या है? बस ऐसे ही).

const sharedSecret = localKeysCurve.computeSecret(
  subscription.keys.p256dh,
  'base64',
);

इसका इस्तेमाल, अगले चरण में स्यूडो रैंडम की (पीआरके) को कैलकुलेट करने के लिए किया जाता है.

बदली हुई पहचान करने वाली कुंजी

बदली हुई पहचान करने की कुंजी (पीआरके), पुश सदस्यता की पुष्टि करने वाली तकनीक का मिला-जुला रूप होती है और वे राज़ हैं जो हमने अभी-अभी बनाए हैं.

const authEncBuff = new Buffer('Content-Encoding: auth\0', 'utf8');
const prk = hkdf(subscription.keys.auth, sharedSecret, authEncBuff, 32);

आपको लग रहा होगा कि Content-Encoding: auth\0 स्ट्रिंग का क्या मकसद है. कम शब्दों में कहें, तो इसका कोई साफ़ मकसद नहीं है, हालांकि ब्राउज़र आने वाले मैसेज को डिक्रिप्ट करें. साथ ही, कॉन्टेंट को उस कोड में बदलने की प्रोसेस देखें जिस पर उम्मीद की जा सकती है. \0, बफ़र के आखिर में 0 वैल्यू वाली एक बाइट जोड़ता है. यह है ब्राउज़र, उस संदेश को डिक्रिप्ट करते हुए अपेक्षित रूप से इतने बाइट की उम्मीद करेंगे को, कॉन्टेंट को कोड में बदलने के लिए, एक बाइट है. इसकी वैल्यू 0 है और इसके बाद, एन्क्रिप्ट (सुरक्षित) किया गया डेटा है.

हमारी बदली हुई रैंडम कुंजी सिर्फ़ पुष्टि, शेयर किया गया सीक्रेट और एन्कोडिंग जानकारी का एक हिस्सा चला रही है HKDF के ज़रिए उपलब्ध कराया जाएगा. इसका मतलब है कि इसे क्रिप्टोग्राफ़िक तौर पर मज़बूत बनाया जा सकता है.

संदर्भ

"कॉन्टेक्स्ट" बाइट का एक सेट है, जिसका इस्तेमाल बाद में एन्क्रिप्शन में दो वैल्यू को कैलकुलेट करने के लिए किया जाता है ब्राउज़र खोलें. यह ज़रूरी बाइट का वह कलेक्शन है जिसमें सदस्यता की सार्वजनिक कुंजी और स्थानीय सार्वजनिक कुंजी है.

const keyLabel = new Buffer('P-256\0', 'utf8');

// Convert subscription public key into a buffer.
const subscriptionPubKey = new Buffer(subscription.keys.p256dh, 'base64');

const subscriptionPubKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = subscriptionPubKey.length;

const localPublicKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = localPublicKey.length;

const contextBuffer = Buffer.concat([
  keyLabel,
  subscriptionPubKeyLength.buffer,
  subscriptionPubKey,
  localPublicKeyLength.buffer,
  localPublicKey,
]);

आखिरी संदर्भ बफ़र एक लेबल होता है, यानी सदस्यता सार्वजनिक कुंजी में कितनी बाइट, कुंजी के बाद, बाइट की संख्या स्थानीय सार्वजनिक कुंजी और उसके बाद कुंजी वह भी ऐसा कर सकता है.

इस कॉन्टेक्स्ट वैल्यू की मदद से, हम नॉन्स और कॉन्टेंट एन्क्रिप्शन की कुंजी बनाने में इसका इस्तेमाल कर सकते हैं (सीईके).

कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने की कुंजी और नॉन्स

nonce ऐसी वैल्यू है जो रीप्ले को रोकती है क्योंकि इसका इस्तेमाल सिर्फ़ एक बार किया जाना चाहिए.

कॉन्टेंट एन्क्रिप्ट करने की कुंजी (सीईके) ऐसी कुंजी है जिसका इस्तेमाल हमारे पेलोड को एन्क्रिप्ट करने के लिए किया जाएगा.

सबसे पहले हमें नॉन्स और सीईके के लिए डेटा की बाइट बनानी होंगी, जो कि सिर्फ़ एक कॉन्टेंट है एन्कोडिंग स्ट्रिंग के बाद अभी-अभी हमारे द्वारा परिकलित संदर्भ बफ़र:

const nonceEncBuffer = new Buffer('Content-Encoding: nonce\0', 'utf8');
const nonceInfo = Buffer.concat([nonceEncBuffer, contextBuffer]);

const cekEncBuffer = new Buffer('Content-Encoding: aesgcm\0');
const cekInfo = Buffer.concat([cekEncBuffer, contextBuffer]);

यह जानकारी HKDF के ज़रिए सॉल्ट और PRK को nonceInfo और cekInfo के साथ जोड़कर चलाया जाता है:

// The nonce should be 12 bytes long
const nonce = hkdf(salt, prk, nonceInfo, 12);

// The CEK should be 16 bytes long
const contentEncryptionKey = hkdf(salt, prk, cekInfo, 16);

इससे हमें नॉन्स और कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने की कुंजी मिलती है.

एन्क्रिप्ट (सुरक्षित) करें

अब हमारे पास कॉन्टेंट एन्क्रिप्ट करने की कुंजी मौजूद है, इसलिए हम पेलोड को एन्क्रिप्ट (सुरक्षित) कर सकते हैं.

हमने कॉन्टेंट एन्क्रिप्ट करने की कुंजी का इस्तेमाल करके, AES128 साइफ़र बनाया है और नॉन्स एक इनिशलाइज़ेशन वेक्टर है.

नोड में यह ऐसा किया जाता है:

const cipher = crypto.createCipheriv(
  'id-aes128-GCM',
  contentEncryptionKey,
  nonce,
);

अपने पेलोड को एन्क्रिप्ट (सुरक्षित) करने से पहले, हमें यह तय करना होगा कि हमें कितनी पैडिंग (जगह) चाहिए डिवाइस को पेलोड के सामने जोड़ने के लिए. हम पैडिंग (जगह) को क्यों जोड़ना चाहेंगे इससे चुपचाप पता लगाने वाले लोगों को पता चल जाता है कि "टाइप" मैसेज दिखाए जा सकते हैं.

किसी अतिरिक्त पैडिंग (जगह) की लंबाई के बारे में बताने के लिए, आपको दो बाइट पैडिंग (जगह) जोड़नी होंगी.

उदाहरण के लिए, अगर आपने कोई पैडिंग नहीं जोड़ी है, तो आपके पास 0 वैल्यू वाली दो बाइट होंगी, यानी कोई पैडिंग मौजूद नहीं है. इन दो बाइट के बाद, आप पेलोड को पढ़ रहे होंगे. अगर आपने पांच बाइट की पैडिंग (जगह) जोड़ी है, तो पहले दो बाइट की वैल्यू 5 होगी. इसका मतलब है कि उपभोक्ता पांच बाइट और पढ़ने के बाद पेलोड को पढ़ना शुरू कर देगा.

const padding = new Buffer(2 + paddingLength);
// The buffer must be only zeros, except the length
padding.fill(0);
padding.writeUInt16BE(paddingLength, 0);

इसके बाद, हम इस साइफ़र की मदद से अपनी पैडिंग (जगह) और पेलोड को रन करते हैं.

const result = cipher.update(Buffer.concat(padding, payload));
cipher.final();

// Append the auth tag to the result -
// https://nodejs.org/api/crypto.html#crypto_cipher_getauthtag
const encryptedPayload = Buffer.concat([result, cipher.getAuthTag()]);

अब हमारे पास एन्क्रिप्ट किया गया पेलोड है. वाह!

बस यह तय करना है कि इस पेलोड को पुश सेवा को कैसे भेजा जाए.

एन्क्रिप्ट किए गए पेलोड हेडर और शरीर

एन्क्रिप्ट किए गए इस पेलोड को पुश सेवा पर भेजने के लिए, हमें कुछ अलग-अलग हेडर का इस्तेमाल करें.

एन्क्रिप्ट (सुरक्षित) करने का हेडर

'एन्क्रिप्ट (सुरक्षित) करने का तरीका' हेडर में, पेलोड को एन्क्रिप्ट (सुरक्षित) करने के लिए इस्तेमाल किया जाने वाला साल्ट होना चाहिए.

16 बाइट वाला सॉल्ट, base64 यूआरएल की सुरक्षा वाले कोड में बदलना चाहिए और उसे एन्क्रिप्ट करने के हेडर में जोड़ा जाना चाहिए. जैसे:

Encryption: salt=[URL Safe Base64 Encoded Salt]

क्रिप्टो-की हेडर

हमने देखा कि Crypto-Key हेडर का इस्तेमाल 'ऐप्लिकेशन सर्वर कुंजियां' में किया जाता है सेक्शन में, ऐप्लिकेशन के सर्वर की सार्वजनिक कुंजी शामिल करें.

इस हेडर का इस्तेमाल, उस लोकल सार्वजनिक पासकोड को शेयर करने के लिए भी किया जाता है जिसका इस्तेमाल एन्क्रिप्ट (सुरक्षित) करने के लिए किया जाता है को लोड कर सकें.

नतीजे के तौर पर मिला हेडर कुछ ऐसा दिखेगा:

Crypto-Key: dh=[URL Safe Base64 Encoded Local Public Key String]; p256ecdsa=[URL Safe Base64 Encoded Public Application Server Key]

कॉन्टेंट का टाइप, अवधि, और एन्कोडिंग हेडर

Content-Length हेडर, एन्क्रिप्ट (सुरक्षित) किए गए कॉन्टेंट में मौजूद बाइट की संख्या है पेलोड. 'कॉन्टेंट का टाइप' और 'कॉन्टेंट-एन्कोडिंग' हेडर, तय किए गए मान होते हैं. इसे नीचे दिखाया गया है.

Content-Length: [Number of Bytes in Encrypted Payload]
Content-Type: 'application/octet-stream'
Content-Encoding: 'aesgcm'

इन हेडर को सेट करने के बाद, हमें एन्क्रिप्ट (सुरक्षित) किए गए पेलोड को मुख्य हिस्से के तौर पर भेजना होगा हमारा अनुरोध है. ध्यान दें कि Content-Type application/octet-stream. इसकी वजह यह है कि एन्क्रिप्ट (सुरक्षित) किया गया पेलोड ऐसा होना चाहिए बाइट की स्ट्रीम के रूप में भेजा जाता है.

NodeJS में, हम यह काम इस तरह करेंगे:

const pushRequest = https.request(httpsOptions, function(pushResponse) {
pushRequest.write(encryptedPayload);
pushRequest.end();

क्या आपको ज़्यादा हेडर चाहिए?

हमने JWT / ऐप्लिकेशन सर्वर कुंजियों के लिए उपयोग किए जाने वाले हेडर के बारे में बताया है (यानी हमने एन्क्रिप्ट (सुरक्षित) की गई फ़ाइलें भेजने के लिए इस्तेमाल किए जाने वाले हेडर के बारे में भी बताया है पेलोड.

कुछ और हेडर भी हैं, जो सेवाओं को पुश करने वाली सेवाओं का इस्तेमाल करते हैं. इससे, भेजे गए मैसेज. इनमें से कुछ हेडर ज़रूरी हैं, जबकि दूसरे ज़रूरी नहीं हैं.

TTL हेडर

ज़रूरी है

TTL (या लाइव होने में लगने वाला समय) एक पूर्णांक है, जो सेकंड की संख्या बताता है आपका पुश मैसेज, पुश मैसेज शुरू होने से पहले लाइव हो जाए डिलीवर हो गया. TTL की समयसीमा खत्म होने पर, मैसेज को पुश सर्विस लिस्ट नहीं बनाई जाती और वह डिलीवर नहीं होता.

TTL: [Time to live in seconds]

अगर आप TTL की वैल्यू शून्य पर सेट करते हैं, तो पुश सेवा तो तुरंत मैसेज भेजें, लेकिन अगर डिवाइस तक पहुंचा नहीं जा सकता, तो आपका मैसेज को तुरंत पुश सेवा सूची से हटा दिया जाएगा.

तकनीकी रूप से पुश सेवा से पुश मैसेज के TTL को कम किया जा सकता है, अगर यह चाहता है. TTL हेडर की जांच करके यह बताया जा सकता है कि ऐसा हुआ है या नहीं CANNOT TRANSLATE

विषय

ज़रूरी नहीं

विषय ऐसी स्ट्रिंग होती हैं जिनका इस्तेमाल करके अटके हुए मैसेज को नया मैसेज तब दिखेगा, जब उनमें विषय के नाम से मेल खाते होंगे.

यह उन स्थितियों में उपयोगी होता है जब एक से अधिक संदेश भेजे जाते हैं डिवाइस ऑफ़लाइन है और आप वाकई में एक उपयोगकर्ता को केवल नवीनतम डिवाइस चालू होने पर एक मैसेज दिखाई देगा.

अत्यावश्यकता

ज़रूरी नहीं

अगर मैसेज को प्राथमिकता देनी है, तो इससे पता चलता है कि लोगों के लिए मैसेज कितना ज़रूरी है. यह पुश सेवा का उपयोग करके उपयोगकर्ता के डिवाइस की बैटरी लाइफ़ बचाने के लिए बैटरी कम होने पर महत्वपूर्ण संदेशों के लिए जागना.

हेडर का मान नीचे दिखाए गए तरीके से तय किया गया है. डिफ़ॉल्ट वैल्यू normal है.

Urgency: [very-low | low | normal | high]

सब कुछ एक साथ

अगर इन सभी के काम करने के तरीके के बारे में आपका कोई और सवाल है, तो देखें कि लाइब्रेरी कैसे ट्रिगर होती हैं web-push-libs org पर मैसेज पुश करना.

आपके पास एन्क्रिप्ट किया गया पेलोड और ऊपर दिए गए हेडर मौजूद होने के बाद, आपको सिर्फ़ एक पोस्ट अनुरोध करना होगा PushSubscription में endpoint तक.

हम इस पोस्ट अनुरोध के जवाब का क्या करते हैं?

पुश सेवा से जवाब

पुश सेवा से अनुरोध करने के बाद, आपको स्टेटस कोड की जांच करनी होगी जिससे आपको पता चलेगा कि अनुरोध पूरा हुआ या नहीं या नहीं.

स्थिति कोड ब्यौरा
201 बनाया गया. पुश मैसेज भेजने का अनुरोध मिल गया है और उसे स्वीकार कर लिया गया है.
429 बहुत सारे अनुरोध मिले हैं. इसका मतलब है कि आपके ऐप्लिकेशन सर्वर की दर पूरी हो गई है सीमा तक लगाना पड़ता है. पुश सेवा में 'फिर से कोशिश करें' शामिल होना चाहिए हेडर का इस्तेमाल करें. इससे पता चलता है कि दूसरा अनुरोध करने में कितना समय लगेगा.
400 अनुरोध अमान्य है. आम तौर पर इसका मतलब है कि आपका कोई एक हेडर अमान्य है या का फ़ॉर्मैट सही नहीं है.
404 नहीं मिला. इससे पता चलता है कि आपकी सदस्यता खत्म हो गई है इसका इस्तेमाल नहीं किया जा सकता. इस मामले में, आपको `PushSubscription` को मिटा देना चाहिए और उपयोगकर्ता के फिर से सदस्यता लेने तक क्लाइंट का इंतज़ार करें.
410 हो गया. सदस्यता अब मान्य नहीं है और इसे हटा दिया जाना चाहिए ऐप्लिकेशन सर्वर से. इसे कॉल करके फिर से बनाया जा सकता है `PushSubscription` पर `unsubscribe()`.
413 पेलोड का साइज़ बहुत बड़ा है. पुश सेवा के लिए पेलोड का कम से कम साइज़ सहायता 4096 बाइट है (या 4 केबी).

आगे कहां जाना है

कोड लैब