2 पॉइंट द्वारा GN⁺ 2023-10-24 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Base64 एनकोडिंग binary data को ASCII text में बदलने का तरीका है, जिससे storage और transmission के दौरान data के गलत interpret होने की संभावना कम होती है
  • यह encryption नहीं, बल्कि representation format में बदलाव है, इसलिए encoded data को आसानी से वापस मूल text या file data में बदला जा सकता है
  • 64 characters को 6 bits में represent किया जा सकता है, इसलिए Base64 का एक character 6-bit data रखता है, और 3 bytes (24 bits) चार Base64 characters में बदल जाते हैं
  • HTML के Data URLs, email में binary transmission, और text-centric networks या URLs जैसे environments में यह उपयोगी है, जहां raw binary समस्या पैदा कर सकता है
  • Ruby, C#, PHP, JavaScript, terminal का base64 command आदि कई languages और tools encoding/decoding functionality देते हैं

Base64 क्या बदलता है

  • Base64 एनकोडिंग binary data को text में, और अधिक सटीक रूप से ASCII text में convert करती है
  • result केवल नीचे दिए गए 64 characters का उपयोग करता है
    • A-Z
    • a-z
    • 0-9
    • +
    • /
  • यह character set <, >, \n जैसे characters के पुराने computers या programs में गलत interpret होने की स्थितियों से बचने के लिए safe character set के रूप में इस्तेमाल होता है
  • "Ruby on Rails" को Base64 में encode करने पर UnVieSBvbiBSYWlscw== बनता है
  • Base64 encryption नहीं है
    • encoded data को मूल text में आसानी से वापस बदला जा सकता है
    • यह data को छिपाता नहीं, केवल data की representation बदलता है

Base64 इस्तेमाल करने की स्थितियां

  • Data URLs image जैसे file data को सीधे HTML के अंदर रखने देते हैं, और इसके लिए Base64-encoded text का उपयोग होता है
  • example format data:[<mime type>][;charset=<charset>][;base64],<encoded data> है
  • email में, ऐसे environment में भी जहां servers line breaks बदल सकते हैं, binary data को सुरक्षित रूप से रखने के लिए Base64 का उपयोग होता रहा है
  • HTML source में image data सीधे डालते समय < और > जैसे characters tags के रूप में interpret न हों, इसके लिए encoding जरूरी होती है
  • text या US-ASCII data process करने के लिए design किए गए networks के जरिए binary data store या transmit करते समय भी इसका उपयोग किया जा सकता है
  • URL में डालने में कठिन characters वाले data को भेजते समय भी Base64 इस्तेमाल किया जा सकता है
  • Base-family encodings objects को text editor से handle करने योग्य बनाती हैं, इसलिए कई applications में उनका उपयोग होता है

एनकोडिंग algorithm

  • Base64 encoding निम्न क्रम में होती है
    • text को binary representation में convert करना
    • bits को 6-bit groups में बांटना
    • हर 6-bit group को 0 से 63 तक के decimal number में convert करना
    • इस number को Base64 alphabet के corresponding character में बदलना
  • अगर आखिरी group में bits कम हों, तो = या == को padding के रूप में जोड़ा जा सकता है
  • 64 characters को represent करने के लिए 6 bits चाहिए
    • 2^6 = 64
    • एक Base64 number 6-bit data को दर्शाता है
  • byte 8 bits का होता है, और 8 और 6 का सबसे नजदीकी common multiple 24 है
    • 24 bits 3 bytes होते हैं
    • 24 bits को चार 6-bit Base64 numbers से represent किया जाता है

“Akshay” encoding example

  • "Akshay" में हर character को ASCII number में बदलकर फिर binary में convert करने पर यह मिलता है
    • 01000001 01101011 01110011 01101000 01100001 01111001
  • इसे 6-bit groups में बांटने पर यह मिलता है
    • 010000 010110 101101 110011 011010 000110 000101 111001
  • हर group को decimal में बदलने पर ये values मिलती हैं
    • 16 22 45 51 26 6 5 57
  • Base64 alphabet में convert करने पर ये characters बनते हैं
    • Q W t z a G F 5
  • इसलिए "Akshay" का Base64 representation QWtzaGF5 है
  • इसी तरह image, PDF, text, video जैसी files को भी binary में बदलकर Base64 में encode करने पर ASCII text के रूप में store या transmit किया जा सकता है

Languages और tools में उपयोग

  • Ruby Base64 module से encoding और decoding handle करता है
    • Base64.encode64("Ruby on Rails")
    • Base64.decode64(encoded)
  • C# string को byte array में बदलकर Convert.ToBase64String से encode करता है, और System.Convert.FromBase64String से decode करता है
  • PHP top-level functions base64_encode और base64_decode देता है
  • JavaScript btoa() से encode और atob() से decode करता है
  • terminal में भी base64 command से encoding और decoding की जा सकती है
    • echo "akshay" | base64 YWtzaGF5Cg== output करता है
    • echo "YWtzaGF5Cg==" | base64 -d akshay output करता है

1 टिप्पणियां

 
GN⁺ 2023-10-24
Hacker News की राय
  • यह बात ज़ोर देकर बताने के लिए धन्यवाद कि यहाँ टेक्स्ट को encrypt नहीं किया जा रहा है। बहुत से junior developers encryption (जिसे reverse करने के लिए कोई secret value चाहिए), hashing (जिसे reverse नहीं किया जा सकता), और encoding (जिसे हमेशा आसानी से reverse किया जा सकता है) के बीच का फर्क बहुत देर से सीखते हैं और नुकसान उठा बैठते हैं
    यह भी जानने लायक है कि output भले ही random जैसा दिखे, entropy input जितनी ही रहती है। यानी password को ज़्यादा मजबूत बनाने के लिए उसे Base64 में encode नहीं करना चाहिए

    • यह थोड़ी nitpicking है और मुख्य मुद्दे से ज़्यादा संबंध नहीं रखती, लेकिन password को Base64 में encode करने से वह मजबूत हो भी सकता है। password strength सिर्फ entropy का मामला नहीं है; high entropy बस सबसे असरदार तरीका है
      अगर password पूरी तरह random तरीके से generate किया गया है, तो Base64 encoding का कोई असर नहीं होगा। लेकिन अगर password किसी low-entropy system से बना है, जैसे dictionary words या याद रखने में आसान नियम, तो attacker को अपने smart password cracker में Base64 encoding rule को भी consider करने के लिए configure करना पड़ेगा, जिससे हर attempt में लगभग एक अतिरिक्त operation जुड़ जाएगा
      बेशक, ऐसा password system इस्तेमाल नहीं करना चाहिए। “correct horse battery staple” जैसे password पर्याप्त माने जा सकते हैं
    • अगर कोई computer science major है, तो मुझे लगता है कि वह ये फर्क जानता ही होगा। coding में रुचि रखने वाला व्यक्ति भी ये concepts एक दोपहर में सीख सकता है
    • इसी से जुड़ी एक बात जिस पर हमेशा ज़ोर देना चाहिए: hash जरूरी नहीं कि cryptographically secure हो
      hashing के security के अलावा भी कई उद्देश्य होते हैं, इसलिए hash libraries भी कई तरह की होती हैं। अगर security या crypto-related use के लिए hash इस्तेमाल करना है, तो उसी उद्देश्य के लिए designed hash इस्तेमाल करना चाहिए। CRC hash तेज़ होते हैं, लेकिन user passwords के लिए अच्छे नहीं हैं
  • Base64 की एक दिलचस्प बात यह है कि अगर आप किसी string से शुरू करके encoding बार-बार दोहराएँ, तो result का शुरुआती हिस्सा धीरे-धीरे एक fixed point की ओर converge करता है। इसे Bash में भी देखा जा सकता है
    10 साल से भी ज़्यादा पहले मैंने इसे संयोग से खोजा और cipher की तरह tweet किया था [1], फिर किसी ने उस विषय पर blog post लिखी और यहाँ भी post किया, लेकिन चर्चा ज़्यादा नहीं हुई [2]। किसी और ने इसे Reddit /r/compsci पर post किया, तो वहाँ blog post को correct करने वाली productive चर्चा हुई [3]। अब blog down है, लेकिन Internet Archive में उसकी copy बची हुई है [4]
    [1] https://twitter.com/p4bl0/status/298900842076045312
    [2] https://news.ycombinator.com/item?id=5181256
    [3] https://www.reddit.com/r/compsci/comments/18234a/the_base64_...
    [4] https://web.archive.org/web/20130315082932/http://fmota.eu/b...

  • Bash में encode करते समय -n option इस्तेमाल करना चाहिए: $ echo -n "abcde" |base64
    -n न हो तो echo string के अंत में एक newline character जोड़ देता है, और वह character भी encode हो जाता है

    • अगर predictable output चाहिए, तो echo इस्तेमाल न करके printf इस्तेमाल करना बेहतर है। https://linux.die.net/man/1/printf
  • base64URL भी होता है, जो URL-safe दूसरे ASCII characters का इस्तेमाल करके encode करता है। कुछ developers BASE64URL को बस base64 भी कह देते हैं, जिससे जिन लोगों को यह पता नहीं होता, उन्हें समस्या हो सकती है
    https://datatracker.ietf.org/doc/html/rfc4648#section-5

    • base64url की समस्या यह है कि ~ और . letters नहीं हैं, इसलिए encoded value पर double-click करने पर पूरी value select नहीं होती। copy-paste करने के कई मामलों में यह unnecessary friction बन जाता है
      Base62 encoding (0-9A-Za-z) base64url जितनी ही लगभग efficient है और URL safety भी बनाए रखती है, जबकि copy-paste करना आसान बनाती है। अगर इंसानों के पढ़ते समय ambiguity कम करनी हो, तो Base58 तक नीचे जा सकते हैं, लेकिन आमतौर पर जब BaseXX encoding की जा रही होती है, तो length लंबी होती है और copy-paste ही सामान्य होता है, इसलिए यह बड़ी समस्या नहीं होती
      https://en.wikipedia.org/wiki/Base62
    • Base64url में आमतौर पर padding भी छोड़ दी जाती है
      padding वाली Base64 string की length हमेशा 4 का multiple होती है, इसलिए अगर 4 का multiple न होने वाली string मिले, तो पता चल सकता है कि original padding कितनी होनी चाहिए थी और last 3 bytes को कैसे decode करना है
      इसलिए यह थोड़ा confusing है कि Base64 में शुरू से ही == padding की जरूरत क्यों है
  • base conversion की बात आते ही मैं अपना arbitrary base converter बेधड़क promote करता हूँ: https://convert.zamicol.com
    “useful alphabets” के नीचे base64, radix से repeated division करने वाला “natural” base है, और RFC की “bucket” conversion method extras के नीचे है

  • अगर आपने कुछ encode किया है और उसे इंसान को खुद type करना है, तो https://en.wikipedia.org/wiki/Base32 recommend करता हूँ
    खराब fonts की वजह से l है या 1, o है या O या 0, यह confuse होने जितना परेशान करने वाला कुछ नहीं

  • थोड़ा strict होकर कहें, तो Base64 के लिए यह कहना ज़्यादा सही है कि वह binary data को पूरे ASCII character set में नहीं, बल्कि ASCII subset में encode करता है
    ASCII में 128 code points होते हैं, जिनमें 95 printable characters और 33 control characters हैं; Base64 उनमें से सिर्फ 64 characters इस्तेमाल करता है, और padding शामिल करें तो 65

  • लेख में = / == padding का उद्देश्य विस्तार से नहीं बताया गया, और 6-bit groups में ठीक-ठीक न बंटने वाले data को कैसे handle किया जाता है, यह भी example से नहीं दिखाया गया
    मोटे तौर पर समझ तो आ गया लगता है, लेकिन पक्का जानना चाहता/चाहती हूँ। = कब इस्तेमाल होता है और == कब, क्या इसे हमेशा add करते हैं या कभी नहीं भी लगाते, "5byte" जैसी string के बचे हुए bits को ठीक-ठीक कैसे handle किया जाता है, decoding करते समय किन बातों का ध्यान रखना होता है—अगर इसका छोटा और पूरा जवाब मिल सके तो अच्छा होगा

    • दोनों सवाल आपस में जुड़े हुए हैं
      Base64 का एक character 6 bits को represent करता है, इसलिए data का एक 3-byte block Base64-encoded characters के 4-character block से match करता है। इसी वजह से Base64 data को 4 characters के groups में process करना सुविधाजनक होता है
      = padding है, जिसे encoded string की length को 4 के multiple में लाने के लिए जरूरत के हिसाब से 0, 1 या 2 बार लगाया जाता है। उदाहरण के लिए "543210""543210==", "6543210""6543210=", और "76543210" में padding की जरूरत नहीं होती। padding में = तीन बार चाहिए ऐसा कभी नहीं होता, क्योंकि 1 byte data के लिए भी कम से कम 2 Base64 characters चाहिए होते हैं
      बचे हुए bits को 0 से भर सकते हैं, और decoder यह देखकर उन्हें discard कर सकता है कि पूरा 1 byte बनाने के लिए पर्याप्त bits नहीं हैं। आजकल ज्यादातर cases में padding सख्त जरूरत से ज्यादा एक convention जैसा है। Wikipedia article काफी detailed है: https://en.wikipedia.org/wiki/Base64
    • padding सिर्फ encoded data को जोड़ते समय या streaming करते समय जरूरी होती है, यानी जब encoded stream के बीच में padding characters आते हैं
      stream·file·string के अंत में मौजूद padding characters को पहले से process की गई length से infer किया जा सकता है, इसलिए कड़ाई से देखें तो वे अनिवार्य नहीं हैं
      हालांकि padding handle करने का तरीका काफी subtle है, और उन्हीं फर्कों की वजह से interesting implementation variants बने हैं: https://eprint.iacr.org/2022/361.pdf
    • लेख के अनुसार Base64 का एक digit data के 6 bits को represent करता है। byte 8 bits का होता है, और 8 और 6 का सबसे नजदीकी common multiple 24 है, इसलिए 24 bits, यानी 3 bytes को 6-bit Base64 digits के 4 characters में व्यक्त किया जा सकता है
      आखिरकार यह 24-bit units में encoding करने जैसा है। data खत्म होने पर बचे हुए 24-bit हिस्से को A से नहीं बल्कि = से भरा जाता है, क्योंकि A data के रूप में 000000 का मतलब रखता है। मैंने भी समझने के लिए पूरा text दो बार पढ़ा
  • मेरा Base64 encoder shader यहाँ है: https://github.com/Rezmason/excel_97_egg/blob/main/glsl/base...
    इसे GLSL में लगभग 13 lines तक घटाया है: https://github.com/Rezmason/excel_97_egg/blob/main/glsl/base...
    इसे एक side project के Cursed Mode में इस्तेमाल करता/करती हूँ, जहाँ WebGL framebuffer को Base64-encoded 640x480 pixel indexed color BMP के रूप में लगभग 15 बार प्रति सेकंड render किया जाता है: https://rezmason.github.io/excel_97_egg/?cursed=1

  • गहराई में जाने लगें तो कुछ और दिलचस्प details हैं, और उन details के variants भी हैरान करने लायक बहुत हैं
    अगर input data की length ठीक 3 bytes की multiple नहीं है, तो आखिरी 1 byte या 2 bytes को encode करने के लिए 2 या 3 Base64 characters इस्तेमाल होते हैं। चूँकि एक Base64 character 6 bits का होता है, 8 bits या 16 bits को represent करने के लिए 12 bits या 18 bits इस्तेमाल होते हैं, और नतीजे में extra 4 bits या 2 bits बचते हैं जो कुछ भी encode नहीं करते
    RFC encoder से अपेक्षा करता है कि वह उन bits को 0 set करे, लेकिन decoder के बारे में केवल इतना कहा गया है कि वह ऐसे input को reject कर सकता है जिनमें वे bits 0 नहीं हैं। असल में default रूप से reject करने वाली implementations बहुत कम हैं, और मेरी जानकारी में Ruby, Rust और Go ही ऐसी input पर fail होने के लिए configure किए जा सकते हैं। Python में validate option है, लेकिन वह उन bits को validate नहीं करता
    एक और बड़ा फर्क whitespace और non-Base64 characters को handle करने में है। Python समेत surprisingly कई implementations input के arbitrary characters को चुपचाप ignore कर देती हैं। alphabet गलत चुनने पर समस्या हो सकती है; उदाहरण के लिए Python में base64.standard_b64decode(base64.urlsafe_b64encode(b'\xFF\xFE\xFD\xFC')) error नहीं देता और चुपचाप गलत output देता है
    Ruby के Base64 encoder का हर 60 characters पर newline डालना भी दिलचस्प है। PEM के अलावा कोई standard encoding इतनी छोटी lines की मांग नहीं करती, और PEM ठीक 64-character lines मांगता है, इसलिए यह काफी unusual choice है
    मैंने programming languages और कुछ JavaScript libraries के बीच फर्कों को summarize करने वाला लेख लिखा है [1], और JS में बेहतर Base64 जोड़ने पर भी काम कर रहा/रही हूँ [2]
    [1] https://gist.github.com/bakkot/16cae276209da91b652c2cb3f612a...
    [2] https://github.com/tc39/proposal-arraybuffer-base64