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

मैट स्केल

Chrome 50 से पहले, पुश मैसेज में कोई भी पेलोड डेटा नहीं हो सकता था. जब आपके सर्विस वर्कर में 'पुश' इवेंट फ़ायर हुआ, तो आपको बस इतना पता था कि सर्वर आपको कुछ बताने की कोशिश कर रहा था, न कि वह क्या हो सकता है. इसके बाद, आपको सर्वर से फ़ॉलो-अप करने का अनुरोध करना पड़ा और सूचना दिखाने के लिए जानकारी लेनी पड़ी. नेटवर्क खराब होने पर, इस सूचना की जानकारी मिल सकती है.

अब Chrome 50 (और डेस्कटॉप पर Firefox के मौजूदा वर्शन में) में, पुश के साथ कुछ आर्बिट्रेरी डेटा भेजा जा सकता है, ताकि क्लाइंट ज़्यादा अनुरोध करने से बच सके. हालांकि, ज़्यादा क्षमता होने पर ज़िम्मेदारी भी बढ़ जाती है, इसलिए सारा पेलोड डेटा एन्क्रिप्ट (सुरक्षित) किया जाना चाहिए.

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

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

क्लाइंट-साइड परिवर्तन

अगर आपने पहले ही पेलोड के बिना पुश नोटिफ़िकेशन लागू किए हैं, तो क्लाइंट-साइड पर आपको सिर्फ़ दो छोटे बदलाव करने हैं.

सबसे पहले, अपने बैकएंड सर्वर पर सदस्यता की जानकारी भेजते समय आपको कुछ और जानकारी की ज़रूरत होती है. अगर आपने PushSubscription ऑब्जेक्ट पर, JSON.stringify() का इस्तेमाल करके उसे अपने सर्वर पर भेजने के लिए, क्रम से लगाया है, तो आपको कुछ भी बदलने की ज़रूरत नहीं है. सदस्यता में अब कुंजियों की प्रॉपर्टी में कुछ ज़्यादा डेटा होगा.

> JSON.stringify(subscription)
{"endpoint":"https://android.googleapis.com/gcm/send/f1LsxkKphfQ:APA91bFUx7ja4BK4JVrNgVjpg1cs9lGSGI6IMNL4mQ3Xe6mDGxvt_C_gItKYJI9CAx5i_Ss6cmDxdWZoLyhS2RJhkcv7LeE6hkiOsK6oBzbyifvKCdUYU7ADIRBiYNxIVpLIYeZ8kq_A",
"keys":{"p256dh":"BLc4xRzKlKORKWlbdgFaBrrPK3ydWAHo4M0gs0i1oEKgPpWC5cW8OCzVrOQRv-1npXRWk8udnW3oYhIO4475rds=",
"auth":"5I2Bu2oKdyy9CwL8QVF0NQ=="}}

p256dh और auth, Base64 के वैरिएंट से कोड में बदली गई हैं. इसे URL-Safe Base64 कहा जाएगा.

इसके बजाय, अगर आपको डेटा का सही डेटा इकट्ठा करना है, तो सदस्यता पर उस नए getKey() तरीके का इस्तेमाल करें जो पैरामीटर को ArrayBuffer के तौर पर दिखाता है. आपको auth और p256dh दो पैरामीटर की ज़रूरत होगी.

> new Uint8Array(subscription.getKey('auth'));
[228, 141, 129, ...] (16 bytes)

> new Uint8Array(subscription.getKey('p256dh'));
[4, 183, 56, ...] (65 bytes)

दूसरा बदलाव push इवेंट के सक्रिय होने पर नई डेटा प्रॉपर्टी है. इसमें मिले डेटा को पार्स करने के कई तरीके हैं, जैसे कि .text(), .json(), .arrayBuffer(), और .blob().

self.addEventListener('push', function(event) {
  if (event.data) {
    console.log(event.data.json());
  }
});

सर्वर साइड से जुड़े बदलाव

सर्वर साइड पर, चीज़ें थोड़ी ज़्यादा बदल जाती हैं. बुनियादी प्रोसेस में यह है कि पेलोड को एन्क्रिप्ट (सुरक्षित) करने के लिए, क्लाइंट से मिली एन्क्रिप्शन कुंजी की जानकारी का इस्तेमाल किया जाता है. इसके बाद, इस जानकारी को पोस्ट अनुरोध के मुख्य हिस्से के तौर पर सदस्यता में मौजूद एंडपॉइंट पर भेजा जाता है. साथ ही, इसमें कुछ और एचटीटीपी हेडर भी जोड़े जाते हैं.

ब्यौरा उतना ही मुश्किल है. एन्क्रिप्शन से जुड़ी किसी भी चीज़ की तरह, अपनी लाइब्रेरी को रोल करने के बजाय, पहले से डेवलप की गई लाइब्रेरी का इस्तेमाल करना बेहतर होता है. Chrome की टीम ने Node.js के लिए एक लाइब्रेरी पब्लिश की है. जल्द ही, अन्य भाषाओं और प्लैटफ़ॉर्म पर भी यह लाइब्रेरी उपलब्ध कराई जाएगी. यह एन्क्रिप्ट (सुरक्षित) करने के तरीके और वेब पुश प्रोटोकॉल, दोनों को हैंडल करता है, ताकि किसी Node.js सर्वर से पुश मैसेज भेजना webpush.sendWebPush(message, subscription) जितना आसान हो.

हालांकि, हम लाइब्रेरी का इस्तेमाल करने का सुझाव देते हैं, लेकिन यह एक नई सुविधा है. कई ऐसी लोकप्रिय भाषाएं हैं जिनमें अब तक कोई लाइब्रेरी नहीं है. अगर आपको यह तरीका खुद लागू करना है, तो यहां इस बारे में जानकारी दी गई है.

मैं नोड-फ़्लेवर वाली JavaScript का इस्तेमाल करके एल्गोरिदम की इमेज दिखाऊँगी, लेकिन इसके बुनियादी सिद्धांत किसी भी भाषा में एक जैसे होने चाहिए.

इनपुट

किसी मैसेज को एन्क्रिप्ट (सुरक्षित) करने के लिए, हमें सबसे पहले उस सदस्यता ऑब्जेक्ट से दो चीज़ें हासिल करनी होंगी जो हमें क्लाइंट से मिली थी. अगर आपने क्लाइंट पर JSON.stringify() का इस्तेमाल किया है और उसे अपने सर्वर पर ट्रांसमिट किया है, तो क्लाइंट की सार्वजनिक कुंजी keys.p256dh फ़ील्ड में सेव होती है, जबकि शेयर किया गया, पुष्टि करने वाला सीक्रेट keys.auth फ़ील्ड में होता है. ये दोनों यूआरएल के हिसाब से सुरक्षित होंगे जैसा कि ऊपर बताया गया है, Base64 कोड में बदले गए. क्लाइंट सार्वजनिक कुंजी का बाइनरी फ़ॉर्मैट, बिना कंप्रेस किया हुआ P-256 इलिप्टिकल कर्व पॉइंट होता है.

const clientPublicKey = new Buffer(subscription.keys.p256dh, 'base64');
const clientAuthSecret = new Buffer(subscription.keys.auth, 'base64');

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

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

हमें कुछ नया डेटा भी जनरेट करना होगा. हमें क्रिप्टोग्राफ़िक तरीके से सुरक्षित रैंडम सॉल्ट और एलिप्टिक कर्व की एक सार्वजनिक/निजी जोड़ी की ज़रूरत है. पुश एन्क्रिप्शन स्पेसिफ़िकेशन में इस्तेमाल किए जाने वाले खास कर्व को P-256 या prime256v1 कहा जाता है. सबसे अच्छी सुरक्षा के लिए, किसी मैसेज को एन्क्रिप्ट (सुरक्षित) करते समय, हर बार स्क्रैच से कुंजी जनरेट होनी चाहिए. साथ ही, आपको नमक का दोबारा इस्तेमाल नहीं करना चाहिए.

ECDH

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

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

const crypto = require('crypto');

const salt = crypto.randomBytes(16);

// Node has ECDH built-in to the standard crypto library. For some languages
// you may need to use a third-party library.
const serverECDH = crypto.createECDH('prime256v1');
const serverPublicKey = serverECDH.generateKeys();
const sharedSecret = serverECDH.computeSecret(clientPublicKey);

25

एक और चीज़ के लिए समय बचा है. मान लें कि आपके पास कुछ गुप्त डेटा है जिसका इस्तेमाल आप एन्क्रिप्शन कुंजी के तौर पर करना चाहते हैं, लेकिन वह क्रिप्टोग्राफ़िक तौर पर सुरक्षित नहीं है. एचएमएसी आधारित की डेरिवेशन फ़ंक्शन (एचकेडीएफ़) का इस्तेमाल करके, कम सुरक्षा वाले सीक्रेट को अच्छी सुरक्षा वाले तरीके में बदला जा सकता है.

इसके काम करने के तरीके का एक नतीजा यह है कि इसकी मदद से आप चाहे भी कुछ भी बिट का सीक्रेट बना सकें, लेकिन 255 गुना तक किसी भी साइज़ का दूसरा सीक्रेट जनरेट कर सकें. ऐसा तब किया जा सकता है, जब किसी भी हैशिंग एल्गोरिदम से बने हैशिंग एल्गोरिदम से कोई हैश बनाया जा रहा हो. पुश के लिए, खास जानकारी के लिए हमें SHA-256 का इस्तेमाल करना पड़ता है, जिसकी हैश लंबाई 32 बाइट (256 बिट) है.

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

मैंने नीचे नोड वर्शन के लिए कोड शामिल किया है, लेकिन आरएफ़सी 5869 में पता लगाया जा सकता है कि यह असल में कैसे काम करता है.

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

// Simplified HKDF, returning keys up to 32 bytes long
function hkdf(salt, ikm, info, length) {
  if (length > 32) {
    throw new Error('Cannot return keys of more than 32 bytes, ${length} requested');
  }

  // 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);
}

एन्क्रिप्ट (सुरक्षित) करने के पैरामीटर पाना

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

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

अब हम फ़ाइनल कॉन्टेंट एन्क्रिप्शन की बनाते हैं और एक nonce बनाते हैं, जिसे साइफ़र में भेजा जाता है. इन्हें हर एक के लिए एक आसान डेटा स्ट्रक्चर बनाकर बनाया जाता है, इसे एक जानकारी के रूप में बताया जाता है. इसमें मैसेज के सोर्स की पुष्टि करने के लिए, इलिप्टिकल कर्व, मैसेज भेजने वाले और जानकारी पाने वाले की खास जानकारी होती है. इसके बाद, सही साइज़ की कुंजी और नॉन्स निकालने के लिए, हम पीआरके, अपने सॉल्ट, और जानकारी के साथ HKDF का इस्तेमाल करते हैं.

कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने के लिए, जानकारी का टाइप 'aesgcm' है. यह उस साइफ़र का नाम है जिसे पुश एन्क्रिप्शन के लिए इस्तेमाल किया जाता है.

const authInfo = new Buffer('Content-Encoding: auth\0', 'utf8');
const prk = hkdf(clientAuthSecret, sharedSecret, authInfo, 32);

function createInfo(type, clientPublicKey, serverPublicKey) {
  const len = type.length;

  // The start index for each element within the buffer is:
  // value               | length | start    |
  // -----------------------------------------
  // 'Content-Encoding: '| 18     | 0        |
  // type                | len    | 18       |
  // nul byte            | 1      | 18 + len |
  // 'P-256'             | 5      | 19 + len |
  // nul byte            | 1      | 24 + len |
  // client key length   | 2      | 25 + len |
  // client key          | 65     | 27 + len |
  // server key length   | 2      | 92 + len |
  // server key          | 65     | 94 + len |
  // For the purposes of push encryption the length of the keys will
  // always be 65 bytes.
  const info = new Buffer(18 + len + 1 + 5 + 1 + 2 + 65 + 2 + 65);

  // The string 'Content-Encoding: ', as utf-8
  info.write('Content-Encoding: ');
  // The 'type' of the record, a utf-8 string
  info.write(type, 18);
  // A single null-byte
  info.write('\0', 18 + len);
  // The string 'P-256', declaring the elliptic curve being used
  info.write('P-256', 19 + len);
  // A single null-byte
  info.write('\0', 24 + len);
  // The length of the client's public key as a 16-bit integer
  info.writeUInt16BE(clientPublicKey.length, 25 + len);
  // Now the actual client public key
  clientPublicKey.copy(info, 27 + len);
  // Length of our public key
  info.writeUInt16BE(serverPublicKey.length, 92 + len);
  // The key itself
  serverPublicKey.copy(info, 94 + len);

  return info;
}

// Derive the Content Encryption Key
const contentEncryptionKeyInfo = createInfo('aesgcm', clientPublicKey, serverPublicKey);
const contentEncryptionKey = hkdf(salt, prk, contentEncryptionKeyInfo, 16);

// Derive the Nonce
const nonceInfo = createInfo('nonce', clientPublicKey, serverPublicKey);
const nonce = hkdf(salt, prk, nonceInfo, 12);

पैडिंग (जगह)

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

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

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

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

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

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

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

अब हमारे पास एन्क्रिप्ट (सुरक्षित) करने के लिए, सब कुछ है. वेब पुश के लिए, GCM का इस्तेमाल करके AES128 को साइफ़र करना ज़रूरी है. हम कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी का इस्तेमाल, कुंजी के तौर पर और नॉन्स को इनिशलाइज़ेशन वेक्टर (IV) के तौर पर करते हैं.

इस उदाहरण में हमारा डेटा एक स्ट्रिंग है, लेकिन यह कोई बाइनरी डेटा हो सकता है. हर पोस्ट के लिए ज़्यादा से ज़्यादा 4078 बाइट से लेकर 4096 बाइट तक के पेलोड भेजे जा सकते हैं. इसमें एन्क्रिप्शन की जानकारी के लिए 16-बाइट और पैडिंग के लिए कम से कम 2 बाइट का होना चाहिए.

// Create a buffer from our data, in this case a UTF-8 encoded string
const plaintext = new Buffer('Push notification payload!', 'utf8');
const cipher = crypto.createCipheriv('id-aes128-GCM', contentEncryptionKey,
nonce);

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

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

वेब पुश

वाह! अब आपके पास एन्क्रिप्ट (सुरक्षित) किया गया पेलोड है, तो आपको उपयोगकर्ता की सदस्यता से बताए गए एंडपॉइंट पर, एक आसान एचटीटीपी पोस्ट अनुरोध भेजना होगा.

आपको तीन हेडर सेट करने होंगे.

Encryption: salt=<SALT>
Crypto-Key: dh=<PUBLICKEY>
Content-Encoding: aesgcm

<SALT> और <PUBLICKEY>, सॉल्ट और सर्वर की सार्वजनिक कुंजी हैं. इनका इस्तेमाल एन्क्रिप्ट (सुरक्षित) करने के लिए किया जाता है. इन्हें यूआरएल के हिसाब से सुरक्षित Base64 कोड में बदला जाता है.

वेब पुश प्रोटोकॉल का इस्तेमाल करते समय, POST का मुख्य हिस्सा एन्क्रिप्ट (सुरक्षित) किए गए मैसेज का सिर्फ़ रॉ बाइट होता है. हालांकि, जब तक Chrome और Firebase क्लाउड मैसेज सेवा, प्रोटोकॉल के साथ काम नहीं करती, तब तक अपने मौजूदा JSON पेलोड में डेटा को इस तरह आसानी से शामिल किया जा सकता है.

{
    "registration_ids": [ "…" ],
    "raw_data": "BIXzEKOFquzVlr/1tS1bhmobZ…"
}

rawData प्रॉपर्टी की वैल्यू, एन्क्रिप्ट (सुरक्षित) किए गए मैसेज का base64 कोड फ़ॉर्मैट होना चाहिए.

डीबग करना / पुष्टि करने वाला

पीटर बेवरलू उन Chrome इंजीनियर में से एक हैं जिन्होंने इस सुविधा को लागू किया है. उन्होंने इस सुविधा पर काम करने वाले लोगों में से एक हैं. पीटर बेवरलू ने इस सुविधा को लागू करने के लिए, एक पुष्टि करने वाला टूल बनाया है.

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