2 पॉइंट द्वारा GN⁺ 2023-10-29 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Seattle Public Library और King County Library System के plastic cards कम करने के लक्ष्य के चलते, iPhone Wallet pass की JSON, image और signature संरचना को सीधे संभालना पड़ा
  • Wallet केवल QR code, PDF417, Aztec Code और Code 128 ही support करता है, इसलिए library card के Codabar को default barcode के रूप में नहीं जोड़ा जा सका; असली scan के लिए barcode को image के तौर पर workaround किया गया
  • pass को Apple द्वारा trusted key से sign करना जरूरी था, लेकिन सालाना 99 डॉलर वाली Apple Developer membership लेने के बजाय, offline generation कर सकने वाले iOS pass app में certificate और key ढूंढकर इस्तेमाल किए गए
  • storeCard layout, अलग-अलग resolution के logos, Codabar strip.png, और खाली PKBarcodeFormatCode128 item को मिलाकर screen पर image barcode दिखाया गया, फिर भी iOS का screen brightness बढ़ाने वाला behavior कायम रखा गया
  • तैयार .pkpass manifest generation, openssl smime signature, और ZIP packaging से बनाया जा सका; असली library test से पहले भी एक अलग scanner ने phone screen पर barcode पढ़ लिया

लक्ष्य: plastic card के बिना library barcode इस्तेमाल करना

  • Seattle Public Library और King County Library System loan account से जुड़े barcode-printed plastic cards जारी करते हैं
  • 2023 तक Seattle library की ज्यादातर सुविधाएं self-service हैं, और आमतौर पर library barcode manually enter किया जा सकता है
  • फिर भी barcode तुरंत दिखाना कहीं ज्यादा सुविधाजनक है, इसलिए लक्ष्य था कि कम इस्तेमाल होने वाला plastic card wallet में रखने के बजाय iPhone Wallet app में रखा जाए

Wallet pass JSON, images और signature से बना होता है

  • Wallet app अभी payment cards, IDs, keys आदि संभालता है, लेकिन 2012 में Passbook launch के समय यह सिर्फ “passes” manage करता था
  • Apple के pass documentation के अनुसार pass एक self-contained ZIP file है जिसे email या web के जरिए distribute किया जा सकता है, और इसके अंदर JSON और PNG होते हैं
  • .pkpass file की मुख्य संरचना सरल है
    • pass.json: image नहीं, बल्कि pass की content describe करता है
    • manifest.json: दूसरी files के SHA-1 checksums की list
    • signature: manifest.json content पर S/MIME signature
    • supported image files

Codabar support न होना पहली बाधा

  • Wallet pass सिर्फ चार तरह के barcodes support करता है
    • QR code
    • PDF417
    • Aztec Code
    • Code 128
  • Library card Codabar format में था, जो libraries में व्यापक रूप से इस्तेमाल होता है
  • संभव है कि library barcode scanners दूसरे linear barcodes भी support करते हों, लेकिन सभी branches में पक्का चलेगा ऐसा format केवल Codabar ही माना जा सकता था
  • आखिरकार Wallet के default barcode feature के बजाय, scan करने योग्य Codabar image बनाकर pass में डालनी पड़ी

Pass signing certificate की समस्या

  • Wallet pass के लिए cryptographic signature जरूरी है, और उसे Apple certificate authorities में से किसी एक द्वारा trusted key से sign होना चाहिए
  • Airline ticket में gate change या seat change जैसे vendor द्वारा pass auto-update करने के use case में signature कुछ हद तक उचित है
  • अगर आप Apple developer हैं तो pass signing key अपेक्षाकृत आसानी से मिल सकती है, लेकिन इस काम के लिए सालाना 99 डॉलर देने का इरादा नहीं था

मौजूदा pass generation apps सही क्यों नहीं थे

  • पहले से Apple developers द्वारा बनाए गए कई pass design apps मौजूद थे, लेकिन वे जरूरी स्तर का control नहीं देते थे
  • Logo size control

    • Apple pass के top-left logo के लिए अधिकतम 50 device-independent pixels height allow करता है
    • text के दाईं ओर लगने वाले square logo के लिए करीब 40px height सबसे ठीक थी
    • developer को logo.png, logo@2x.png, logo@3x.png अलग-अलग देने होते हैं, लेकिन apps आमतौर पर सिर्फ single logo selection allow करते हैं और scale control नहीं देते
  • Screen brightness behavior

    • normal supported barcode वाला pass खोलने पर scanner contrast के लिए screen bright हो जाती है
    • असल में काम न करने वाला barcode display किए बिना भी iOS से screen bright करवाने के लिए pass.json को सीधे edit करना जरूरी था
    • मुफ्त में download किए जा सकने वाले apps भी Wallet में save किए जा सकने वाले passes की संख्या सीमित करके payment मांगते थे

Offline generation app में signing key ढूंढना

  • कई free-start pass generation apps download किए गए और देखा गया कि offline भी pass generation होता है या नहीं
  • airplane mode और Wi-Fi disabled स्थिति में test करने पर, कम से कम एक app offline pass बना सकता था
  • key revoke होने से बचाने के लिए उस app का specific नाम नहीं बताया गया
  • प्रक्रिया उम्मीद से सरल थी
    • Apple silicon Mac पर iOS apps चल सकते हैं, इसलिए app को Mac पर download किया गया
    • wrapped iOS app bundle के अंदर एक दिखने वाली .p12 file मिली
    • PKCS#12 file को import password चाहिए होता है, इसलिए main binary पर strings चलाकर password जैसा दिखने वाला string खोजा गया
  • openssl pkcs12 से certificate information check करने पर issuer Apple Worldwide Developer Relations Certification Authority दिखा
  • certificate chain भी जरूरी होती है; intermediate certificate app bundle के अंदर हो सकता है और X.509 extension field में दिए URL से भी download किया जा सकता है

Pass layout configuration

  • Pass style में boarding pass, coupon, event ticket, generic, store card में से एक चुनना होता है
  • बड़ी horizontal image डालने के लिए strip image support करने वाला layout चाहिए था
    • candidates थे coupon, event ticket, store card
    • physical library card से सबसे मिलता-जुलता होने के कारण store card चुना गया
  • pass.json में ये values जाती हैं
    • passTypeIdentifier
    • teamIdentifier
    • formatVersion
    • serialNumber
    • organizationName
    • logoText
    • description
    • storeCard
    • backgroundColor
    • foregroundColor
    • sharingProhibited
  • passTypeIdentifier और teamIdentifier को Apple certificate subject के UID, OU fields से क्रमशः match करना होता है
  • एक ही passTypeIdentifier से बनाए गए हर pass के लिए unique serialNumber चाहिए
  • Images use case के हिसाब से तैयार की गईं
    • icon.png जरूरी है, लेकिन pass में खुद display नहीं होता
    • logo.png top-left में दिखने वाला logo है
    • 40×40 logo.png, 80×80 logo@2x.png, 120×120 logo@3x.png generate किए गए
    • logo@3x.png को icon.png के रूप में copy किया गया
    • पहले से generate किया गया barcode strip.png में डाला गया

Codabar barcode image बनाना

  • iOS strip.png को device screen के box के हिसाब से scale और crop करता है, इसलिए strip.png को अलग-अलग resolution में 3 variants बनाने की जरूरत नहीं थी
  • दोनों library cards start और end symbols के रूप में A और D इस्तेमाल करते हैं
  • start/end symbols barcode scanner होने पर सबसे आसानी से verify किए जा सकते हैं, और scanner न हो तो Wikipedia की Codabar encoding table से आंखों से compare किए जा सकते हैं
  • online तुरंत इस्तेमाल करने लायक Codabar generators ज्यादा नहीं थे, लेकिन format खुद implement करना आसान था
  • prototype में Rust के लिए Barcoders library से SVG बनाया गया, SVG adjust किया गया, फिर PNG में export किया गया
  • final layout scanability और iOS में shrink display को ध्यान में रखकर तय किया गया
    • barcode height को start/end symbols सहित कुल symbols की संख्या के 2 गुना units पर set किया गया
    • उदाहरण के लिए 13-digit barcode number में 15 symbols होते हैं, इसलिए height 30 units बनाई गई
    • start से पहले और end के बाद 15 units quiet space रखा गया
    • barcode के ऊपर-नीचे 50 units padding रखा गया
    • हर unit को 8 pixels तक expand किया गया ताकि iOS हमेशा image को shrink करे
    • उदाहरण वाले 15-symbol barcode में final image height 1040 pixels है और barcode की अपनी height 240 pixels है
  • ऊपर वाले layout का Codabar BMP बनाने और sips से PNG में convert करने के लिए 69-line shell script लिखी गई
  • script output को strip.png के रूप में save करने पर pass में डालने के लिए barcode image तैयार हो जाती है

Barcode number display और screen brightness workaround

  • Barcode number को secondaryFields के रूप में barcode के नीचे display किया गया
    • key: number
    • label: CARD NUMBER
    • value: card number
  • iOS barcode वाला pass select करने पर scanner की मदद के लिए screen bright कर देता है
  • सिर्फ image के रूप में डाले गए Codabar से iOS यह नहीं मानता कि barcode मौजूद है
  • pass.json के top level पर खाली barcode item specify करके इस behavior का workaround किया गया
    • message खाली string है
    • format PKBarcodeFormatCode128 है
    • messageEncoding iso-8859-1 है
  • इस तरीके से pass के bottom में barcode दिखाए बिना भी iPhone ने screen को ऐसे bright किया जैसे pass में barcode हो

Signing और packaging

  • सभी files तैयार होने के बाद manifest.json generate करना होता है
  • manifest.json एक object है जिसमें filename key और SHA-1 checksum value होता है
  • sha1sum, jq को combine करके PNG files और pass.json का manifest generate किया गया
  • manifest signing openssl smime command से की गई
    • signer certificate
    • private key
    • Apple WWDR intermediate certificate
    • input manifest.json
    • output signature
  • openssl smime के -attime option से desired signing time specify किया जा सकता है
    • option value UNIX epoch होती है
    • Apple से मिला या खोजा गया certificate expire हो चुका हो, तब भी उस समय के हिसाब से sign किया जा सकता है
  • अंत में इन files को ZIP करके .pkpass बनाया गया
    • PNG images
    • pass.json
    • manifest.json
    • signature

Test results और खटकने वाली बातें

  • macOS में pass preview tool है, जिससे check किया जा सकता है कि pass valid है और आम तौर पर सही दिख रहा है
  • invalid होने पर Console.app में errors मिल सकते हैं
  • preview tool 100% accurate नहीं है, लेकिन इसमें iCloud के जरिए iPhone पर भेजने वाला button है
  • तैयार pass अभी असली library में test नहीं किया गया था
  • अलग barcode scanner phone screen पर barcode को असली plastic card की तरह पढ़ सका
    • हालांकि screen brightness maximum करने पर यह अच्छी तरह read हुआ
    • खाली barcode workaround से बढ़ी brightness से भी ज्यादा bright set किया गया था
  • अच्छा है कि pass specification 10 साल में लगभग नहीं बदला, लेकिन PNG और JSON वाले harmless pass को sign करने के लिए सालाना 99 डॉलर Apple Developer membership चाहिए होना खटकता है
  • कुछ pass features के लिए signature जरूरी मानी जा सकती है, लेकिन इस काम में जो किया गया उसके लिए signature जरूरी नहीं होनी चाहिए
  • अगर Apple Wallet में Codabar support जोड़ दे, तो library system के सभी scanners Code 128 support करते हैं या नहीं इसका audit किए बिना भी digital library cards support किए जा सकते हैं

1 टिप्पणियां

 
GN⁺ 2023-10-29
Hacker News की राय
  • अगली बार ORCA कार्ड भी कवर करें तो अच्छा होगा। Seattle अमेरिका के तकनीकी केंद्रों में से एक है, लेकिन subway/public transit खुद भी खास नहीं है, और तकनीकी रूप से भी मेरे इस्तेमाल किए हुए लगभग सभी बड़े शहरों के public transit से पीछे है
    यूरोप के किसी भी शहर, CDMX, Denver से तुलना करें तो वे Seattle से काफी आगे हैं, और निजी तौर पर मुझे लगता है Denver सबसे अच्छा था
    ORCA चलाने वाली एजेंसियों में से एक ने कभी Android ऐप में NFC सपोर्ट जोड़ने पर ब्लॉग पोस्ट डाली थी, लेकिन वह पोस्ट अब गायब है और कई साल बाद भी वह फीचर नहीं है

    • कुछ दिन पहले पोस्ट आया कि Google Wallet जल्द ही इसे सपोर्ट करेगा: https://blog.google/products/google-pay/commute-around-the-w...
    • हमारे इलाके के transit system ने हाल ही में tap payment जोड़ा है, जिससे कोई भी credit card, Apple Pay/Google Pay इस्तेमाल किया जा सकता है
      अगर वही कार्ड इस्तेमाल करें तो transfer, कुछ दिनों वाले pass जैसी चीजें भी seamless तरीके से संभल जाती हैं, और किसी तय अवधि में एक निश्चित संख्या से ज्यादा rides लेने पर आगे charge नहीं करते—इस तरह सही fare अपने-आप लागू हो जाता है
    • सोचता हूं कि ज्यादातर public transit systems अगर free rides पर शिफ्ट हो जाएं तो उनकी funding का सिर्फ एक हिस्सा ही घटेगा; उसकी तुलना में fare collection system को बनाए रखने में कितना खर्च आता होगा?
    • इससे जुड़ा सवाल: rooted Android से NFC card cloning करने का कोई तरीका नहीं है क्या?
      हमारे office का door NFC card से खुलता है, इसलिए मैंने देखा था कि iOS पर यह संभव है या नहीं; याद है कि Apple सामान्य PassKit की तुलना में NFC hardware को ज्यादा सख्ती से control करता है, इसलिए सामान्य apps से मुश्किल लगता है
    • https://info.myorca.com/news/can-i-use-my-phone-to-pay-for-a...
      ORCA ने कहा था कि 2023 के अंदर tap payment आएगा, तो सच होने के लिए अब करीब दो महीने बचे हैं
      Google ने पोस्ट किया है कि Google Wallet में ORCA जल्द support होगा, इसलिए मैं optimistic हूं
  • अगर Android users को यह बात पसंद नहीं कि Google Wallet, Apple Passbook की तरह कोई भी barcode जोड़ने नहीं देता, तो F-Droid पर Loyalty Card Keychain नाम का बेहतरीन app है: https://f-droid.org/en/packages/protect.card_locker/
    आप number manually डाल सकते हैं या मौजूदा barcode scan कर सकते हैं, और Codabar समेत कई barcode formats में से एक चुनकर save कर सकते हैं। app की main screen पर item tap करने पर generated barcode दिखता है और screen brightness भी बढ़ जाती है
    शायद इसलिए कि barcode दिखाने के अलावा यह ज्यादा कुछ नहीं करता, app बहुत जल्दी खुलता है। इसका सिर्फ एक काम है, लेकिन शायद यह मेरा सबसे पसंदीदा app है
    आजकल लगता है Catima इस्तेमाल करने को कहा जाता है; मैंने थोड़ी देर इस्तेमाल किया तो वह भी उतना ही simple लगा और उसी codebase पर आधारित दिखा

    • Apple पर मैं Pass4Wallet से ‘card’ बनाकर Apple Wallet में import करके इस्तेमाल करता हूं
      असुविधाजनक है, लेकिन काम हो जाता है, और privacy policy भी अच्छी है
    • Google Wallet में मनचाहा barcode डालने देने वाला app भी है: https://play.google.com/store/apps/details?id=color.dev.com....
  • मुझे समझ नहीं आता कि pass को cryptographically signed होना और Apple certificate authority को ज्ञात key से signed होना क्यों जरूरी समझा जाए। ऐसी updates के लिए पहले से अच्छी तरह supported HTTPS है
    शायद Apple चाहता हो कि pass केवल update के समय ही नहीं, बल्कि phone पर offline भी verify हो सके, लेकिन फिर भी यह अजीब है। malicious actor pass को update करने के बजाय सीधे replace कर सकता है

    • शुरुआती pass में update की अनुमति देने वाली public key specify कर देना ही काफी है
      इसे Apple developer account से जोड़ने से update वाली समस्या में कैसे मदद मिलती है, यह मुझे बिल्कुल नहीं समझ आता
      Apple-approved entity होने की requirement का जो कारण दिमाग में आता है, वह fake tickets बेचना है। “Concert X ticket” नाम की pkpass file असली है या नहीं, यह उस requirement के साथ भी जानने का कोई तरीका नहीं है
      fraud report आने पर उस developer account को cancel करके response देने की कोशिश हो सकती है, लेकिन यह भी solution जैसा नहीं लगता। developer account की cost पकड़े जाने से पहले fraud से कमाए जा सकने वाले पैसे से कहीं कम होने की संभावना है
  • मैं तो library card number वाला barcode PNG खुद को email कर देता हूं, और kiosk के सामने Photos या Gmail app में खोलकर इस्तेमाल करता हूं

    • Wallet pass में वह location और time range define की जा सकती है जहां/जब वह pass “relevant” के रूप में दिखे
      मैंने MakePass app से StarBucks membership code वाला pass बनाया, और जब मैं अक्सर जाने वाले store के पास पहुंचता हूं तो phone lock screen पर StarBucks pass अपने-आप suggest करता है
      event tickets के लिए भी इसी तरह location और time range सेट कर दें तो venue पर पहुंचने पर pass ढूंढने की जरूरत नहीं पड़ती, वह अपने-आप suggest हो जाता है। event खत्म होने के बाद वह suggest नहीं करता और “Expired Passes” section में चला जाता है, जिससे main screen clutter नहीं होती
      MakePass: https://pvieito.com
    • article को skim करते हुए मैं यही खोज रहा था कि उन्होंने बस photo क्यों नहीं खींची
  • अच्छा blog post था, लेकिन अंत में “अभी इस pass को असली library में test नहीं किया है” लिखा था
    समझता हूं कि यह मजे के लिए किया गया project था, लेकिन result share करने से पहले final solution test करने में लगने वाले 10 minutes क्यों नहीं लगाए, यह समझ नहीं आया

    • उस हिस्से की वजह से पूरे लेख का असर कम हो गया। ऐसा लगा जैसे “running के दौरान oxygen loss पर मेरे पास एक शानदार scientific theory है। मानता हूं, अभी jogging शुरू नहीं की है, लेकिन…”
    • आखिरकार यह scan होने वाले barcode को दर्शाने वाला pixels का एक समूह ही तो है। अगर सही से display हो रहा है, तो क्या गलत हो सकता है?
    • हो सकता है library Saturday को open न हो
  • बारकोड बनाते समय मैं व्यक्तिगत रूप से PostScript में बने बारकोड जनरेटर को पसंद करता हूँ
    https://bwipp.terryburton.co.uk/

  • इस समस्या को लाइब्रेरी कार्ड की फोटो खींचकर हल कर लिया। किताब उधार लेते समय फोटो खोलकर स्कैनर के सामने रख देना होता है

    • बारकोड इमेज को लोकेशन-आधारित रिमाइंडर में डाल दिया है, इसलिए मोहल्ले की लाइब्रेरी पहुँचने पर नोटिफिकेशन आ जाता है
    • अगर बारकोड static है, तो सिर्फ फोटो होना काफी है। उसे Wallet में डालने का फायदा बहुत बड़ा नहीं है
      फोन के फोटो एल्बम में अपने सभी ID कार्ड सेव रखता हूँ
  • Android पर ऐसा ही कुछ करना हो, तो Google Play और F-Droid पर Catima उपलब्ध है। यह कई तरह के बारकोड सपोर्ट करता है
    https://catima.app/

    • Google Pay या Samsung Pay भी इस्तेमाल कर सकते हैं
  • सस्ते laser-based 1D barcode scanners स्क्रीन से बारकोड नहीं पढ़ पाते। eInk शायद काम कर जाए
    जिस supermarket में मैं अक्सर जाता हूँ, उसका membership card बारकोड-आधारित है, इसलिए असुविधा होती है; लेकिन अच्छी बात है कि barcode reader keyboard की नकल करता है, इसलिए code को सीधे keyboard से टाइप किया जा सकता है

    • मेरी समझ के मुताबिक, पुराने systems digital image sensor से scan नहीं करते, बल्कि घूमती हुई laser beam और simple photodiode के जरिए सफेद/काले barcode areas से reflect होने वाली brightness में बदलाव पढ़ते हैं
      camera-based scanners को फर्क नहीं पड़ता कि barcode की lighting ambient light से है, अपनी LED से है या backlit screen से; लेकिन laser-based systems अपनी ही रोशनी के reflection पर निर्भर करते हैं, इसलिए active backlit screen पर बिल्कुल काम नहीं करते
      सोचता हूँ कि e-ink या passive LCD display पर ये काम करते हैं या नहीं
    • Bluetooth MCU और E-ink display से एक सस्ता barcode display बनाया था, और 1D-only barcode scanners पर वे सभी ठीक से काम करते हैं
    • Costco के handheld scanner को membership card पर बहुत संकरे और छोटे प्रिंट किए गए membership barcode को जितनी तेजी और आसानी से पढ़ते देखता हूँ, हर बार हैरानी होती है
      देखने में यह एक साधारण red-line 2D type जैसा लगता है, लेकिन लगता है hardware भी सच में मायने रखता है
  • KCLS account number तो बस याद कर लिया। याद करने में करीब 30 सेकंड ही लगने चाहिए; व्यक्ति पर निर्भर है, लेकिन मुझे लगता है यह तरीका ज्यादा तेज होगा
    इसके बाद barcode scan करने के बजाय account number डालना होता है, और संभव है कि इसमें फोन निकालकर तैयार करने से कम समय लगे
    SPL में भी यही तरीका है या नहीं, पता नहीं। Seattle में नहीं रहता, इसलिए जाँच नहीं कर सकता

    • याद नहीं रखना चाहते, तो अपनी पसंद के password manager में सेव कर सकते हैं