क्या आपको Base64 फ़ॉर्मेट के साथ काम करना होता है? तो यह साइट आपके लिए एकदम सही है! अपने डेटा को एन्कोड या डिकोड करने के लिए, हमारे बेहद आसान ऑनलाइन टूल का इस्तेमाल करें।

Perl में Base64 डिकोडिंग: एक सम्पूर्ण गाइड

आपके हाथ में अक्षरों और अंकों की एक स्ट्रिंग आ गई है, कभी-कभार + या / के साथ भी, और आपको अहसास है कि यह वैसा नहीं है जैसा दिखाई देता है। शायद यह Authorization हेडर में सफ़र कर रहा कोई टोकन है, शायद किसी सपोर्ट टिकट से निकाली गई .b64 फ़ाइल, शायद -----BEGIN कवच पहने सर्टिफिकेट, या कनफ़िग फ़ाइल में ख़ामोशी से बैठे हुए कोई ब्लाब। आप टर्मिनल खोलते हैं, perl टाइप करते हैं, और एक ही सवाल सब कुछ छा लेता है: असली डेटा वापस कैसे लाएँ?

उत्तर छोटा है और सुकून भरा। 2002 से Perl, खुद भाषा के साथ, Base64 मॉड्यूल शिप कर रहा है, और एक ही फ़ंक्शन कॉल, decode_base64, पूरा काम निपटा देता है: कुछ इंस्टॉल करने को नहीं, कुछ कनफ़िगर करने को नहीं। कॉफ़ी ब्रेव होती जा रही है, इस बीच एक त्वरित याद ताज़ा कर लें: Base64 डेटा के हर तीन बाइट्स को 64-चर वर्णमाला के चार चरों में फिर से लिख देता है, और आख़िरी हिस्से को एक या दो = चिह्नों से पैड कर देता है ताकि नतीजा हमेशा चार का गुणज बने - यही वजह है कि एन्कोडेड रूप आमतौर पर अपने मूल से करीब 33 प्रतिशत बड़ा होता है। इस साइट का होम पेज यह फ़ॉर्मेट पूरी तरह समझाता है, इसलिए यह गाइड अपना पूरा समय उस पक्ष पर लगाती है जहाँ Perl खड़ा है: डिकोडर के नियम, बोलीयाँ, और असली दुनिया के वो फ़ॉर्मेट जिनसे आप वाकई रूबरू होंगे।

टूलकिट: पाँच फ़ंक्शन, शून्य इंस्टॉलेशन

आपकी हर ज़रूरत का कॉल MIME::Base64 में रहता है, जो 5.8 से कोर Perl डिस्ट्रिब्यूशन का हिस्सा है, इसलिए यह हर ठीक-ठाक इंस्टॉलेशन पर मौजूद है, राउटर के फ़र्मवेयर में एम्बेडेड वाली से लेकर डेटाबेस सर्वर वाली तक। जाँच सिर्फ़ एक लाइन की है:

perl -MMIME::Base64 -e 'print $MIME::Base64::VERSION, "\n"'
# 3.16_01

यहाँ मॉड्यूल का पूरा डिकोडिंग पक्ष है, बिल्कुल सारा:

फ़ंक्शन यह क्या करता है नोट्स
decode_base64($str) इस आर्टिकल का सितारा: Base64 ब्लाब को कच्चे बाइट्स में बदल देता है वर्णमाला के बाहर का हर चर ख़ामोशी से नज़रअंदाज़ करता है, हमेशा के लिए
MIME::Base64::decode($str) वही डिकोडर, बिना import किए कॉल किया गया यह रूप आपको बहुत सारे पुराने स्क्रिप्ट्स में मिलेगा
decode_base64url($str) - और _ वाली URL-safe बोली डिकोड करता है, पैडिंग हो या न हो 2010 में 3.11 में जुड़ा; यही JWT पढ़ने वाला है
MIME::Base64::decoded_base64_length($str) बिना डिकोड किए बताता है कि डिकोडेड डेटा कितना बड़ा होगा डिफ़ॉल्ट में एक्सपोर्ट नहीं होता, बफ़र की आगे की प्लानिंग के लिए काम आता है
unpack("u", $data) uuencoded डेटा डिकोड करता है, Base64 से पहले का फ़ॉर्मेट Perl के अंदर ही बिल्ट-इन है, कोई मॉड्यूल नहीं चाहिए

उन्हीं फ़ंक्शन्स का वर्ज़न मैप, उन के लिए जो पुरानी मशीनों की एक फ़्लीट चला रहे हैं:

फ़ीचर कब से उपलब्ध
C की रफ़्तार वाला रास्ता सहित decode_base64() 2002 में Perl 5.8, जब मॉड्यूल कोर में जुड़ा
decoded_base64_length() 2010 में मॉड्यूल 3.10
decode_base64url() 2010 में मॉड्यूल 3.11
शांत डिकोडिंग, शक की इनपुट पर कोई वार्निंग नहीं 2010 में मॉड्यूल 3.11
वर्तमान 3.16 लाइन 2020, Perl 5.6 या नया चाहिए

अगर आपकी सिस्टम Perl में किसी वजह से यह मॉड्यूल नहीं है, हालाँकि ऐसा होने का कोई कारण नहीं, तो दवा सिर्फ़ दो लाइनों में से एक है: Debian और Ubuntu पर डिस्ट्रो पैकेज libmime-base64-perl, या cpanm MIME::Base64, जो CPAN से वर्तमान रिलीज़ ला लेता है, जहाँ मॉड्यूल अपने कोर दिनों से एक दो-ज़िन्दगी पैकेज के तौर पर रह रहा है। C कम्पाइलर के बिन किसी अजीब मशीन के लिए, CPAN का शुद्ध Perl जुड़वा MIME::Base64::Perl वही बेसिक इंटरफ़ेस देता है, कुछ गुना धीमा तो है, पर बड़े पैमाने के काम के सिवा हर काम के लिए पर्याप्त। यही पूरी निर्भरता की कहानी है: कुछ और नहीं।

एक ऐसा डिकोडर जो कभी नहीं मना करता

अनुबंध सिर्फ़ एक लाइन लंबा है। उसे स्ट्रिंग दें, वह डिकोडेड बाइट्स वापस एक साधारण Perl स्ट्रिंग के तौर पर देता है, जिसमें कच्चे बाइट्स रखे हों। न कोई ऑब्जेक्ट, न कोई एक्ससेप्शन, न कोई फ्लैग। दस्तावेज़ीकरण एक ही वाक्य में उन दो नियमों को बयान करता है जो इसकी शख़्सियत तय करते हैं: 65-चर Base64 उपसमूह का हिस्सा न होने वाला कोई भी चर ख़ामोशी से नज़रअंदाज़ कर दिया जाता है, और = पैडिंग चर के बाद आने वाला कोई भी चर कभी डिकोड नहीं होता। यही शालीनता इस आर्टिकल की सबसे बड़ी बात है, इसलिए इसे एक बार अपने काम पर लगा दें:

use MIME::Base64 qw(decode_base64);
print decode_base64("TWFu!"),   "\n";  # Man - विस्मय-चिह्न के पार से पार, बिन एक निशान
print decode_base64("TWFu=XX"), "\n";  # Man - = के बाद का सब कुछ छूट हो जाता है
print decode_base64("TQ"),      "\n";  # M - न वार्निंग, न कोई कमेंट
print decode_base64("T"),       "\n";  # खाली स्ट्रिंग, फिर भी कोई शिकायत नहीं

आख़िरी दो लाइनें सहनशीलता का उम़ड़न हैं। TQ में एक पूरा बाइट और चार बेकार बिट्स हैं, और डिकोडर बस बाइट रख लेता है और बाकी छोड़ देता है। T में एक पूरा बाइट भी नहीं, इसलिए नतीजा खाली है। मॉड्यूल में पुराने ढंग की तफ़सील-परस्ती वापस लाने का न कोई सख़्त मोड है और न कोई वैलिडेटर: 2010 की वर्ज़न 3.11 से, decode_base64 कटी हुई इनपुट पर भी वार्निंग नहीं करता, और पुरानी वर्ज़न Premature end of base64 data वार्निंग की -w के तहत चिढ़ाहट करती थीं। ब्लाब ग़लत हो तो भी वह डिकोड कर ही देता है, यानी गुणवत्ता चौकी बनकर आप खड़े हो जाते हैं।

यहाँ सहनशीलता की पूरी नीति एक जगह है, ताकि एक नज़र में पूरा नक्शा दिख जाए:

इनपुट नतीजा क्यों
"TWFu" Man साफ़ इनपुट, ख़ुशनसीब रास्ता
"TWFu!" Man विस्मय-चिह्न वर्णमाला में नहीं है, इसलिए वह छूट हो गया
"TWFu=XX" Man पैडिंग के बाद का कुछ भी कभी डिकोड नहीं होता
"TWFuIFdvcmxkIQ==" Man World! कहीं भी ख़ाली जगहें मुफ़्त हैं
"TQ" M एक पूरा बाइट आ जाता है, बेकार के बिट्स ख़ामोशी से गिर जाते हैं
"T" खाली स्ट्रिंग एक पूरा बाइट भी नहीं, और न कोई वार्निंग
"ab-cd_efgh" ख़ामोशी से ग़लत बाइट्स URL-safe अक्षर शोर के तौर पर गिर जाते हैं, क्लासिक फ़ँदा

वो आख़िरी पंक्ति ही याद रखने लायक है। स्टैंडर्ड डिकोडर को सौंपा गया base64url खंड फेल नहीं होता: वह ऐसा-वैसा लगने वाला क़चरा डिकोड कर देता है, क्योंकि - और _ चरों को अजनबी शोर मानकर हटा दिया जाता है, जबकि बचे अक्षर फिर भी वैध समूह बनाते हैं। डिकोडर गवाह है, द्वार-रक्षक नहीं, इसलिए इनपुट पर भरोसा नहीं है तो जाँच आप खुद करें। बस एक छोटा सा सख़्त चेक काफी है:

sub strict_base64 {
  my ($blob) = @_;
  $blob =~ s/[\r\n]//g;  # डिकोडर इन्हें नज़रअंदाज़ करता है, हम भी
  return 0 unless length($blob) % 4 == 0;
  return $blob =~ /\A[0-9A-Za-z+\/]+(?:={1,2})?\z/ ? 1 : 0;
}
print strict_base64("TWFu"),  "\n";  # 1
print strict_base64("TQ="),   "\n";  # 0 - ग़लत पैडिंग की गिनती
print strict_base64("ab-cd"), "\n";  # 0 - URL-safe वर्णमाला

उस रेगुलर एक्सप्रेशन के बारे में एक छोटी सी बात, मुश्किल से मिले अनुभव की तरफ़ से: अगर कोई सब-रूटीन बस return $x =~ /.../ पर ख़त्म हो जाए और असफल मिलान सीधा printf में चल जाए, तो Perl एक साफ़ शून्य के बजाय भटकाने वाली Missing argument in printf वार्निंग उठाता है। वापस लौटने से पहले ? 1 : 0 से मिलान को बाध्य करें, जैसे ऊपर वाला फ़ंक्शन करता है, और यह खिल्ली पूरी तरह गायब हो जाती है।

पहले बाइट्स, फिर चर

decode_base64 क्या वापस देता है, याद रखें: कच्चे बाइट्स, एक साधारण स्ट्रिंग जिस पर UTF-8 फ्लैग सेट नहीं है। उन बाइट्स का मतलब क्या है, यह फैसला सिर्फ़ आप कर सकते हैं, और यही वह कदम है जहाँ Unicode लोगों को उठाता है। Perl ट्रैक करता है कि स्ट्रिंग में चर हैं या बाइट्स, और length(), substr(), और अधिकांश रेगुलर एक्सप्रेशन्स जवाब के हिसाब से अलग-अलग व्यवहार करते हैं। दवा है अपने एन्कोडिंग को जानबूझकर नाम देना, Encode मॉड्यूल से जो हर Perl इंस्टॉल के साथ शिप होता है:

use MIME::Base64 qw(decode_base64);
use Encode qw(decode);
my $raw  = decode_base64("SMOrbGxvIFdvcmxkIQ==");
my $text = decode("UTF-8", $raw);
print $text, "\n";            # Hëllo World!
print length($text), " chars\n";  # 12
print length($raw),  " bytes\n";  # 13

वह जोड़ी ही पूरा पाठ है। ब्लाब 13 बाइट्स का है पर सिर्फ़ 12 चरों का, क्योंकि संकेत वाला अक्षर UTF-8 में दो बाइट्स लेता है। चरसेट का कदम छोड़ दें तो भी बाइट्स UTF-8 टर्मिनल पर ठीक-ठाक प्रिंट हो जाते हैं, और यही वजह है कि ग़लती छुपी रहती है, तब तक जब तक कोई स्ट्रिंग फ़ंक्शन उन्हें गिने, या बाइट्स ऐसे पाइपलाइन से न गुज़र जाएं जहाँ चर की उम्मीद हो। शक हो तो सख़्त चरसेट से डिकोड करें और एक्ससेप्शन को बाइट्स की सच बताने दें: Encode::FB_CROAK पास करें और decode() ग़लत चर-क्रम पर डाय हो जाता है, डिफ़ॉल्ट की ख़ामोशी वाली U+FFFD जगह-बदली के बजाय, और यह कोई कमज़ोरी नहीं, फ़ीचर है।

उन चरसेट्स की छोटी सूची जिनसे आप वाकई हाथ बढ़ाएँगे:

चरसेट कब इस्तेमाल करें किसकी निगाह रखें
UTF-8 डिफ़ॉल्ट मान: APIs, JSON, वेब सामग्री, आधुनिक टेक्स्ट अवैध चर-क्रम डिफ़ॉल्ट में U+FFFD बन जाते हैं; Encode::FB_CROAK के साथ वे साफ़-साफ़ डाय कर जाते हैं, जो बिल्कुल वही है जो आप चाहते हैं
Latin-1 पुराने पश्चिमी टेक्स्ट, एक बाइट प्रति चर, कभी फेल नहीं हो सकता यह खुशी-खुशी UTF-8 को दो-बार एन्कोडेड mojibake में बदल देगा
ASCII ऐसा डेटा जिसके सादा 7-bit टेक्स्ट होने में आपको पूरा यक़ीन हो 127 से ऊपर कोई भी बाइट डिफ़ॉल्ट में U+FFFD बन जाता है (Encode::FB_CROAK के तहत डाय कर जाता है)
UTF-16 Windows टेक्स्ट, जहाँ BOM बाइट-क्रम तय करता है BOM ही एकमात्र बाइट-क्रम संकेत है, इसलिए उसे बाइट्स में बचाए रखें

और यही वह फ़ँदा है जिससे चरसेट का कदम आपको बचाता है। अगर आपके डिकोड किए बाइट्स पहले से UTF-8 हैं और आप उन्हें निकलते वक्त encode("UTF-8", ...) से गुज़ारा देते हैं, तो आपको कॉपी नहीं मिलती: आपको डबल एन्कोडिंग मिलती है, जहाँ हर संकेत वाला चर अपने आप दो चरों में फूल जाता है। क्लासिक लक्षण है ऐसा टेक्स्ट जो पहले Hëllo पढ़ा जाता था और अब Hëllo पढ़ा जाता है, और तार के दूसरे सिरे पर बैठे प्राप्तकर्ता इसे ईमानदारी से डिकोड कर लेगा। बाइट्स आएं, बाइट्स जाएं, बीच में एक नामित रूपांतरण।

base64url: URL और टोकन की वर्णमाला

आधुनिक इंटरनेट पार होने वाली Base64 का आधा हिस्सा स्टैंडर्ड वर्णमाला ही नहीं है। + चर वही है जिसे ब्राउज़र क्वेरी स्ट्रिंग में खाली जगह एन्कोड करता है, और / पथ विभाजक है, इसलिए स्टैंडर्ड अक्षर URLs में बलातीं हैं। RFC 4648, सेक्शन 5, दवा परिभाषित करता है: दूसरी वर्णमाला, जो + और / की जगह - और _ रखती है, और मान्यता के तौर पर = पैडिंग और लाइन-ब्रेक भी गिरा देती है। RFC स्पष्ट कहता है कि यह एन्कोडिंग base64 एन्कोडिंग के बराबर नहीं मानी जानी चाहिए, और 2010 की वर्ज़न 3.11 से Perl के पास इसके लिए एक समर्पित जोड़ी है:

use MIME::Base64 qw(decode_base64url);
my $raw = decode_base64url("c3Vuc2V0LTQy");
print $raw, "\n";  # sunset-42

दो बातें जानने लायक हैं। पहली, decode_base64url बिना पैडिंग वाली इनपुट से खुश रहता है, और यही रूप वाकई दुनिया में मिलता है, इसलिए उस पहले-पैडिंग-वापस-लाने की रस्म जो अन्य भाषाएँ मज़बूर करती हैं, यहाँ लागू नहीं होती; पैड वाली इनपुट भी काम करती है। दूसरी, स्टैंडर्ड डिकोडर एक अलग जानवर है: उसे base64url खंड दें तो आपको ख़ामोशी से ग़लत बाइट्स मिलेंगे, क्योंकि - और _ चर शोर की तरह गिर जाते हैं और बाकी फिर भी डिकोड हो जाता है। सही डिकोडर इस्तेमाल करें, या जब पुराना कोड रास्ता में फँसे हों तो हाथ से नॉर्मलाइज़ करें:

my $seg = "ab-cd_efgh";
$seg =~ tr{-_}{+/};                    # URL-safe अक्षरों का वापस-घर अनुवाद
$seg .= "=" x (-length($seg) % 4);     # स्टैंडर्ड डिकोडर के लिए पैडिंग वापस लौटाई गई
my $raw = decode_base64($seg);
print unpack("H*", $raw), "\n";  # 69bf9c77f79f82 - सात बाइट्स, स्टैंडर्ड वर्णमाला में वापस

base64url से आपकी मुलाक़ात JWT में तुरंत होगी, जो हर आधुनिक API बाँटता है, और हर अपाक ID में जो URL में रहती है: ग्यारह-चर वीडियो IDs, URL-safe वर्णमाला में रखे UUIDs (इसीलिए CPAN पर Data::UUID::Base64URLSafe मौजूद है), और डेटाबेस कीज़ जो एड्रेस बार में टिकनी चाहिए। और अगर आप पुराने Perl पर हैं जो कोर फ़ंक्शन्स से पहले का है, तो 2006 का स्वतंत्र MIME::Base64::URLSafe मॉड्यूल, जो Python के urlsafe कोडेक का पोर्ट है, urlsafe_b64encode और urlsafe_b64decode देता है; 3.11 या उससे नया कुछ भी हो, बिल्ट-इन्स ही बेहतर चोइस है।

JWT: हेडर और पेलोड पढ़ना

JSON Web Token, संरचना में, दो टुकड़ों की JSON है जो मुखौटा पहने हैं, और साथ में एक क्रिप्टोग्राफिक रसीद। RFC 7515 की संक्षिप्त रूप तीन डॉट से जुड़े base64url खंडों में बनी है: संरक्षित हेडर, पेलोड, और साइनेचर। इसे खंडित करके पढ़ना सिर्फ़ तीन लाइन का काम है:

use MIME::Base64 qw(decode_base64url);
use JSON::PP;
my $jwt = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJob21lciJ9.uzM6l0c4...";
my ($head_b64, $claims_b64, $sig_b64) = split /\./, $jwt, 3;
my $head   = decode_json(decode_base64url($head_b64));
my $claims = decode_json(decode_base64url($claims_b64));
print $claims->{sub}, " (", $head->{alg}, ")\n";  # homer (HS256)

काम-बंटवारे पर नज़र रखें: decode_base64url हर खंड को बाइट्स में बदलता है, और कोर JSON::PP मॉड्यूल का decode_json, जो Perl 5.14 से मौजूद है, हेडर और पेलोड के बाइट्स को Perl डेटा रचनाएँ बनाने में बदल देता है। साइनेचर खंड भी base64url ही है, पर वह क्रिप्टोग्राफिक डिजेस्ट है, इसलिए आप हमेशा सिर्फ़ पहले दो खंड को डिकोड करते हैं और तीसरे को एक सही लाइब्रेरी पर छोड़ देते हैं।

फ़ँदा वही है जो हर कोई भूल जाता है: पढ़ा जा सके, इसका मतलब वैध नहीं। हेडर और पेलोड डिज़ाइन की वजह से पढ़े जा सकते हैं, यानी कोई भी उन्हें फिर से लिख सकता है; साइनेचर ही एकमात्र सबूत है। किसी असली काम के लिए सत्यापित करें, सिर्फ़ डिकोड नहीं। CPAN मॉड्यूल Crypt::JWT, जो CryptX पर खड़ा है, पूरा काम कर देता है:

use Crypt::JWT qw(decode_jwt);
my $claims = decode_jwt(
  token        => $jwt,
  key          => $secret,
  accepted_alg => "HS256",
);

ग़लत साइनेचर पर यह क्रोक करता है, और accepted_alg को पिन कर लेने से वह अल्गोरिथम-गड़बड़ की दरार बंद हो जाती है जहाँ आक्रमणकारी टोकन को कमज़ोर रूप पर पलट सकता है। सपोर्ट कॉल के दौरान टोकन देखने के लिए सिर्फ़ डिकोड करके प्रिंट करने की प्रक्रिया ठीक है; प्रमाणीकरण नहीं।

फ़ाइलें: .b64 से वापस मूल तक

फ़ाइलें वही जगह हैं जहाँ Perl की वन-लाइनर संस्कृति चमकती है, और पूरा काम एक ही कमांड में समा जाता है। -0777 फ्लैग गुप्त सामग्री है, क्योंकि यह पूरी फ़ाइल को एक ही स्ट्रिंग में एक साथ पकड़ लेता है, लाइन-दर-लाइन डिकोडर को खिलाने के बजाय:

perl -MMIME::Base64 -0777 -ne 'print decode_base64($_)' < in.b64 > out

लाइन-दर-लाइन रूप एक खास तरह की फ़ाइलों के लिए सुरक्षित है: जिनमें हर लाइन चार की गुणज Base64 चरों को पकड़े हुए हो, जो हर सही-तरह से MIME-लपटी बॉडी के लिए सच है, क्योंकि 76 चार का गुणज है। जैसे ही लपेटन बिंदु बेसूरी होने लगें - और हाथ से लपटी फ़ाइलों में अक्सर ऐसा ही होता है - लाइन-दर-लाइन डिकोडिंग डेटा के बीच में पैडिंग बनाना शुरू कर देती है। -0777 मोड में ऐसी कोई शर्त नहीं, यही वजह है कि यह डिफ़ॉल्ट चोइस है:

perl -MMIME::Base64 -ne 'print decode_base64($_)' < in.b64 > out

स्क्रिप्ट के अंदर, पैटर्न वही स्टैंडर्ड Perl फ़ाइल-नाच है, एक ख़ामोश पर महत्वपूर्ण विवरण के साथ: दोनों हैंडल पर :raw लेयर्स, ताकि Perl आते-जाते बाइट्स को प्लेटफ़ॉर्म टेक्स्ट की तरह समझने की कोशिश कभी न करे:

use MIME::Base64 qw(decode_base64);
use Digest::SHA qw(sha256_hex);
open my $in, "<:raw", $ARGV[0] or die $!;
local $/;
my $blob = <$in>;
close $in;
my $decoded = decode_base64($blob);
print sha256_hex($decoded), "\n";  # भेजने वाले के चेकसम से मिलान करें
open my $out, ">:raw", $ARGV[1] or die $!;
print {$out} $decoded;
close $out;

हैश वाली लाइन सिर्फ़ दिखावे के लिए नहीं है। क्योंकि डिकोडर लगभग कुछ भी स्वीकार कर लेता है, भेजने वाले द्वारा प्रकाशित किए गए चेकसम से मिलान ही एकमात्र सबूत है कि सफ़र बाइट-दर-बाइट सटीक था। सच में विशाल फ़ाइलों के लिए, लाइन-दर-लाइन लूप कम-मेमोरी विकल्प है, बशर्ते लपेटन चार-चर की सीमाओं पर बैठे हों, और MIME::Base64::decoded_base64_length आपको बता देता है कि आउटपुट कितना बड़ा होगा, बफ़र पर क़ब्ज़ा करने से पहले।

PEM कवच: कोट उतारें, DER बचाए रखें

हर सुरक्षा स्टैक में .pem फ़ाइलें वही Base64 हैं जो कवच पहने हैं: एक हेडर लाइन, एक फुटर लाइन, और पुरानी Privacy Enhanced Mail मान्यता के मुताबिक 64 चरों पर लपटी हुई बॉडी। रसदार हिस्सा सिर्फ़ लपेटी है, क्योंकि मॉड्यूल के डिकोडर को लाइनों की लंबाई की बिल्कुल परवाह नहीं:

use MIME::Base64 qw(decode_base64);
open my $fh, "<:raw", "cert.pem" or die $!;
local $/;
my $blob = <$fh>;
close $fh;
my @body = grep { !/^-----/ && /\S/ } split /\n/, $blob;
my $der = decode_base64(join "", @body);
print length($der), " bytes of DER\n";

BEGIN और END लाइनें निकाल दी जाती हैं, बाकी सब एक स्ट्रिंग में जुड़ जाता है, और रास्ते में हर न्यूलाइन नज़रअंदाज़ हो जाता है। रोज़मर्रा के सर्टिफिकेट काम के लिए OpenSSL टूलिंग पहले से यह कर देती है; ऊपर की आठ लाइनें वही पैटर्न हैं जो याद रखना है, जब कच्चे DER बाइट्स खुद चाहिए हों, एक हैश, फिंगरप्रिंट, या तुलना के लिए।

Data URI: वह तस्वीरें जो अपना पता खुद साथ लाती हैं

RFC 2397 का data: स्कीम पेलोड को सीधे URL के अंदर ही रख देता है: data:, एक वैकल्पिक मीडिया प्रकार, एक वैकल्पिक ;base64 फ्लैग, एक कॉमा, और डेटा। तस्वीरों जैसे बाइनरी मीडिया फ्लैग का इस्तेमाल करते हैं, इसलिए पेलोड पैडिंग समेत स्टैंडर्ड वर्णमाला की होती है, और एक छोटे से काट के बाद साधारण डिकोडर ही पकड़ लेता है:

use MIME::Base64 qw(decode_base64);
my $uri = "data:image/png;base64,iVBORw0KGgo...";
$uri =~ s/^data:[^,]+,// or die "not a data URI";
my $raw = decode_base64($uri);
print unpack("H8", $raw), "\n";  # 89504e47: PNG के मैजिक बाइट्स

मैजिक बाइट्स की जाँच ही असली चाल है। अगर वो पहली आठ हेक्साडेसिमल चर 89504e47 नहीं हैं, तो तस्वीर PNG नहीं है, मीडिया प्रकार चाहे जो कुछ दावा करे, और एक ऐसा डिकोडर जो कभी शिकायत नहीं करता, बिल्कुल ऐसी ही ख़ामोश झूठ को संभव बनाता है।

रिश्तेदार और जीवाश्म: uuencode और बाकी वर्णमालाएँ

Base64 जीतने से पहले, बाइनरी को ईमेल करने का क्लासिक UNIX तरीका uuencode था, और आप इसे पुराने मेलिंग लिस्ट और पुराने टूल्स में अभी भी मिलेंगे। ख़ुशख़बरी: इसके लिए Perl में बिल्ट-इन डिकोडर है, कोई मॉड्यूल नहीं चाहिए, pack और unpack के u टेम्पलेट की वजह से:

my $uu   = pack("u", "Hello, World!");
print $uu, "\n";  # -2&5L;&\L(%=O<FQD(0`` एक न्यूलाइन के साथ
my $back = unpack("u", $uu);
print $back, "\n";  # Hello, World!

दोनों कॉल एक-दूसरे के ठीक व्युत्क्रम हैं, और यही पूरी कहानी है जो आपको चाहिए, और UNIX टूलचेन का क्लासिक uuencode कमांड बस उन्हीं सादी लाइनों को begin हेडर और end फुटर में लपेट देता है, इसलिए जो पेलोड आप डिकोड कर रहे हैं वह उन दोनों के बीच का हिस्सा है।

Base64 के बोली-रिश्तेदार भी हैं, और यह जानना कि कौन-सा डिकोडर किस चीज़ को खा जाता है, आपको एक डीबगिंग सत्र बचा सकता है:

बोली लपेटन जहाँ मिलेगा decode_base64 क्या करता है
MIME (RFC 2045) 76 चर ईमेल बॉडीज़ वैसे ही डिकोड करता है: लाइन-ब्रेक और CRLF नज़रअंदाज़
PEM (RFC 1421) 64 चर सर्टिफिकेट्स और कीज़ वैसे ही डिकोड करता है
PKIX (RFC 7468) 64 चर X.509 टेक्स्ट रचनाएँ वैसे ही डिकोड करता है
OpenPGP कवच (RFC 9580) 76 चर और एक CRC24 लाइन PGP कीज़ और साइनेचर वैसे ही डिकोड करता है, चेकसम लाइन बस नज़रअंदाज़ रहती है
IMAP (RFC 3501) कोई नहीं मेलबॉक्स नाम यह वर्णमाला नहीं: स्लाश कॉमा बन जाता है, पहले अक्षरों का अनुवाद करें

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

कॉन्फ़िग, डेटाबेस और एनवायरन्मेंट वेरिएबल्स

कंटेनर प्लेटफ़ॉर्म, क्लाउड कंसोल, और एक चौंकाने वाली संख्या में कन्फ़िगरेशन फ़ाइलें क्रेडेंशियल और छोटे दस्तावेज़ अपाक Base64 स्ट्रिंग्स के तौर पर सुरक्षित करती हैं, क्योंकि अक्षरों और अंकों का ब्लाब उस पासवर्ड से कम ख़तरनाक लगता है जिसका वह है। डिकोड हमेशा वही दो कदम हैं: decode_base64 और एक चरसेट फैसला:

use MIME::Base64 qw(decode_base64);
use Encode qw(decode);
my $secret = decode("UTF-8", decode_base64($config->{api_key}));

इस जगह फ़ॉर्मेट इतना लोकप्रिय होने का कारण बिल्कुल वही है जो RFC 4648 चेताता है: इंसान भूल जाते हैं कि डेटा पढ़ा जा सकता है। इसलिए डिकोडेड आउटपुट को वापस आते ही गोपनीय मानें, और न ब्लाब को ही और न उसके नतीजे को लॉग फ़ाइलें, अलर्ट, और डीबग डम्प में जाने दें।

वही रूप डेटाबेस में भी दिखता है, जहाँ बाइनरी डेटा अक्सर TEXT कॉलम में Base64 के तौर पर सफ़र करती है, क्योंकि कॉलम का वादा नहीं कि वह किसी भी बाइट्स को छूए-बिछे न छोड़े:

use MIME::Base64 qw(decode_base64);
my $icon = decode_base64($row->{icon_data});
open my $fh, ">:raw", "icon.png" or die $!;
print {$fh} $icon;
close $fh;

ईमेल: MIME भाग और अटैचमेंट्स

ईमेल वही जगह है जहाँ Base64 को नाम मिला, और मॉड्यूल की सहनशीलता बिल्कुल इसी ट्रैफ़िक के लिए बनाई गई है। Content-Transfer-Encoding: base64 वाला MIME भाग 76-चर CRLF से ख़त्म लाइनों के तौर पर आता है, और डिकोडर पूरा एनवलप वैसे ही खा लेता है, लाइन-ब्रेक समेत:

use MIME::Base64 qw(decode_base64);
my $part_body = "SGVsbG8sIHF1ZXJ5IQpUaGlzIE1JTUUgcGFydCB0cmF2ZWxsZWQgYXMgYmFzZTY0LCB3cmFwcGVk";
$part_body .= "\r\nIGF0IDc2IGNoYXJhY3RlcnMsIENSTEYgYmV0d2VlbiBsaW5lcy4=";
my $text = decode_base64($part_body);
print $text;  # मूल दो-लाइन संदेश बॉडी

अगर आप फ़्रेमवर्क से मेल बनाते या विश्लेषण करते हैं, तो यह सब हाथ से नहीं करते: MIME::Lite आपके लिए अटैचमेंट को Base64 एन्कोड कर देता है जब आप attach में Encoding => "base64" पास करते हैं, और Email::MIME वही काम अपने आप कर देता है। ऊपर वाला हाथ-से-बनाया वर्ज़न उन मेल के लिए है जो लॉग, टिकट, या आगे भेजे गए संदेश में कच्चे टेक्स्ट के तौर पर आते हैं, और अक्सर ऐसा ही होता है।

फ़ँदे, इकट्ठे और रैंक किए

मॉड्यूल रट लेने के लिए इतना छोटा है, इसलिए यहाँ पूरा फ़ँदों की सूची एक जगह है, क़रीब-क़रीब इसी क्रम में कि कितनी बार जलाती है:

फ़ँदा क्या होता है दवा
स्टैंडर्ड डिकोडर को base64url खंड खिलाना - और _ शोर की तरह गिर जाते हैं, और बाकी ख़ामोशी से ग़लत बाइट्स में डिकोड हो जाता है decode_base64url इस्तेमाल करें, या पहले वर्णमाला का अनुवाद करके पैडिंग वापस लाएँ
ख़राब इनपुट पर ख़ामोशी का भरोसा अजनबी चर, कटाई, और ग़लत वर्णमाला - सब एक वार्निंग के बिन डिकोड हो जाते हैं पहले सख़्त चेक चलाएँ, और मूल हाथ में हो तो हैश से सत्यापित करें
ब्लाब के अंदर non-ASCII चर एक टूटा हुआ संकेत वाला अक्षर या Unicode की पेस्ट की गई खाली जगह ख़ामोशी से नज़रअंदाज़ हो जाता है, नतीजा बिन कोई कमेंट छोटा होता जाता है वही सख़्त चेक 7-bit वर्णमाला के बाहर के सब को रिजेक्ट कर देता है
नतीजे को टेक्स्ट की तरह 취급 करना बाइट्स पर UTF-8 फ्लैग नहीं, इसलिए length() बाइट्स गिनता है और स्ट्रिंग फ़ंक्शन्स ग़लत तस्वीर पाते हैं किसी टेक्स्ट प्रोसेसिंग से पहले decode("UTF-8", $raw) या चुना हुआ चरसेट चैन करें
निकलते वक्त डबल एन्कोडिंग पहले से UTF-8 बाइट्स को encode("UTF-8", ...) से गुज़ारना Hëllo को Hëllo बना देता है चर एन्कोड करें, कभी कच्चे बाइट्स नहीं, और शक हो तो utf8::is_utf8() से फ्लैग की जाँच करें
बेसूरी लपेटन के साथ फ़ाइल को लाइन-दर-लाइन डिकोड करना चार-चर की सीमाओं पर ख़त्म न होने वाली लाइनें आउटपुट के बीच में पैडिंग बना देती हैं -0777 से एक साथ पढ़ें, या चार-चर लपेटन बिंदु की गारंटी दें
असफल रेगुलर एक्सप्रेशन मिलान को संख्यकीय संदर्भ में वापस लाना return $x =~ /.../ पर ख़त्म होने वाला सब-रूटीन जो उसे printf में खिला दे, भटकाने वाली Missing argument in printf वार्निंग उठाता है मिलान को बाध्य करें: return $x =~ /.../ ? 1 : 0
पुराने वार्निंग की उम्मीद रखने वाला पुराना कोड 3.11 से पहले के स्क्रिप्ट्स जो Premature end of base64 data carp चेतावनी -w के तहत देखने पर निर्भर करते थे, अब कुछ नहीं देखते अपना सख़्त चेक जोड़ लें; वार्निंग हमेशा के लिए गायब है
यह मान लेना कि डिकोडिंग ही प्रमाणीकरण है डिकोडर लगभग कुछ भी स्वीकार कर लेता है और इस बारे में कुछ नहीं कहता मिलान वाला चेकसम या सत्यापित साइनेचर ही वह सबूत है जो मायने रखता है
जो डिकोड करते हैं उसे लॉग करना फ़ॉर्मेट कुछ छुपाता ही नहीं, और लॉग फ़ाइल बिल्कुल वही जगह है जहाँ अगला इंसान इसे ढूँढेगा डिकोडेड सीक्रेट्स को लॉग्स, अलर्ट, और डीबग डम्प से दूर रखें

अच्छी आदतें

वही आदतें जो Base64 को आपके स्क्रिप्ट्स पर हावी होने से हमेशा के लिए रोकती हैं:

  • हमेशा बाइट्स की उम्मीद रखें। ऐसे कोड लिखें जो जानता है कि decode_base64 कच्चे बाइट्स वापस देता है, और टर्मिनल के सही काम करने की उम्मीद के बजाय चरसेट का decode खुद चैन करें।
  • अपने चरसेट का नाम रखें। डिफ़ॉल्ट UTF-8 रखें और सिर्फ़ तब बदलें जब डेटा कुछ और कहें। decode("UTF-8", ..., Encode::FB_CROAK) की सख़्त फेलियर फ़ीचर है: यह बताता है कि बाइट्स आपकी सोच से कुछ और हैं।
  • वर्णमाला को स्रोत से मिलाएँ। URLs, टोकन्स, और IDs के लिए decode_base64url; बाकी सबके लिए decode_base64। दोनों वर्णमालाएँ आपस में नहीं बदल सकतीं, और ग़लत पकड़ने पर डिकोडर आपको नहीं बताएगा।
  • डिकोड से पहले जाँच करें। इस मॉड्यूल में सख़्त मोड फ्लैग नहीं है, इसलिए एक छोटा सा चेक बौंसर बनता है।
  • फ़ाइलें डिफ़ॉल्ट से एक साथ पढ़ें। -0777 या local $/ = undef लपेटन-बिंदु बग्स की पूरी एक श्रेणी हटा देता है, और जिन फ़ाइलों को आप वाकई डिकोड करते हैं, उनके लिए मेमोरी ख़र्च कोई बहस नहीं।
  • हर फ़ाइल हैंडल पर :raw रखें। बाइनरी आए, बाइनरी जाए। टेक्स्ट लेयर्स इंसानों के लिए हैं, बाइट्स के लिए नहीं।
  • हैश से सत्यापित करें। मूल हाथ में हो, तो मिलान वाला चेकसम ही बाइट-दर-बाइट सटीक डिकोड का एकमात्र सबूत है।
  • जो डिकोड करते हैं उसे कभी लॉग न करें। फ़ॉर्मेट कुछ छुपाता ही नहीं।

एक छोटा इतिहास, जो चेंजलॉग सुनाता है

फ़ॉर्मेट पुराना है, और Perl का उसके साथ रिश्ता जितना लगता है उससे भी पुराना है। कुछ पक्की तारीख़ें, इसी क्रम में:

  • C कोड Perl 5 से पहले का है। मॉड्यूल के अंदर का तेज़ डिकोडर metamail के कोड से उतरा है, Bellcore का मेल प्रोग्राम, 1991 में कॉपीराइट, पहली Perl 5 रिलीज़ से तीन साल पहले। आज जब आप decode_base64 कॉल करते हैं, तो नाइटीज़ का एक टुकड़ा काम कर रहा होता है।
  • जन्म वेब टूल्स में हुआ। मॉड्यूल ने 1990 के दशक के बीच में libwww-perl के अंदर LWP::Base64 के रूप में शुरुआत की, Martijn Koster और Joerg Reichelt के लिखे हुए, और April 1997 में यह अपनी CPAN डिस्ट्रिब्यूशन, MIME::Base64, में पदोन्नत हुआ, वर्ज़न 2.00, जिसकी चेंजलॉग प्रविष्टि based on libwww-perl-5.08 लिखी हुई है।
  • वार्निंग का ज़माना। 1997 की 2.03 से, कटी हुई इनपुट Premature end of base64 data वार्निंग -w के तहत पैदा करता था, क्रोक के बजाय, और 1999 की 2.11 ने उन बिल्ड्स को ठीक किया जो ठीक-ठाक डेटा पर भी वार्निंग कर रही थीं। डिकोडर्स के लिए यह दशक तनाव भरा था।
  • 2002 से कोर में। Perl 5.8 ने मॉड्यूल को कोर डिस्ट्रिब्यूशन में खींच लिया, और उसी दिसंबर की 2.13 कोर सिंक के साथ EBCDIC सपोर्ट भी आ गई, यही वजह है कि एन्कोडर और डिकोडर आज भी मेनफ्रेम पर काम करते हैं।
  • URL-safe बोली 2010 में Perl कोर में आई। वर्ज़न 3.11 ने decode_base64url और उसका जुड़वाँ जोड़े, चार साल बाद, जब स्वतंत्र MIME::Base64::URLSafe मॉड्यूल 2006 में CPAN पर उतरा था - वही साल, जब RFC 4648 ने बोली को लिखा-बद्ध किया।
  • शांत होना। उसी 3.11 रिलीज़ ने पुरानी कटाई वार्निंग भी हटा दी, इस ताक की उम्मीद में कि शक की इनपुत जानबूझकर हो सकती है - और उसके बाद हर रिलीज़, 2020 की वर्तमान 3.16 लाइन समेत, ने डिकोडर को शालीन और ख़ामोश रखा है।

मज़ेदार बातें, ख़ासकर Perl की

टूर को गोल करने के लिए, वही मनोरंजक तथ्य जो यह कहानी अच्छी बनाती है:

  • फ़ॉर्मेट का अपना नाम डिकोड करें। decode_base64("YmFzZTY0") वापस base64 देता है। 1997 से यह सच है और हमेशा सच रहेगा।
  • डिकोडर एक शालीन भूत है। अपने 3.x इतिहास में यह कभी ग़लत इनपुट पर एक्ससेप्शन नहीं उठाया। ख़राब, कटी हुई, ग़लत वर्णमाला: वह सब कुछ डिकोड करता है और किसी चीज़ की शिकायत नहीं करता, एक ऐसी व्यवहार जिसे चेंजलॉग ने 2010 में जानबूझकर पक्का कर दिया।
  • MIME लपेटन जानबूझकर चार का गुणज है। 76-चर की सीमा नौदो तीन-बाइट समूह है, कुल 57 बाइट्स, और हर समूह चार चर देता है, यही वजह है कि लाइन-दर-लाइन डिकोड किसी भी सही-तरह से लपटी MIME बॉडी पर सुरक्षित है और बाकी सब पर ख़तरनाक।
  • uuencode कभी लोअरकेस अक्षर प्रिंट नहीं करता। इसकी वर्णमाला अंडरस्कोर तक ही जाती है, यही वजह है कि पुरानी uuencoded फ़ाइलें ऐसी लगती हैं जैसे किसी बड़े-अक्षरों की मशीन ने टाइप की हों, और यही वजह है कि Perl इंटरनेट से पुराने फ़ॉर्मेट का बिल्ट-इन डिकोडर आज भी साथ रखता है।
  • Perl ने एक बार अपना decode-base64 कमांड भी शिप किया था। 2003 की 2.14 से 2004 की 3.05 तक की रिलीज़ में encode-base64, decode-base64, और उनके quoted-printable जुड़वाँ स्क्रिप्ट्स के तौर पर शामिल थे; 2005 की 3.06 ने उन्हें अलग MIME-Base64-Scripts डिस्ट्रिब्यूशन में चला दिया। अगर आपको पुरानी इंस्टॉल मिले जिसके PATH पर वह कमांड हो, तो अब आप जानते हैं कि वह कहाँ से आया।
  • YouTube वीडियो IDs base64url का मुखौटा पहने हैं। आपके एड्रेस बार में ग्यारह-चर ID URL-safe वर्णमाला की 64-bit संख्या है, पैडिंग गिराई हुई, इसलिए हर वीडियो जिसे आपने कभी देखा, उसकी URL में Base64 स्ट्रिंग छुपी है, और decode_base64url उसे पढ़ सकता है।
  • सहनशीलता स्टैंडर्ड है, बग नहीं। MIME का नियम - जो स्वीकार करते हैं उसमें उदार रहें - यही वजह है कि यह डिकोडर गंदे-बिगड़े डेटा के तीन दशक पार कर रहा है, और यही वजह है कि RFC 4648 चेताता है कि यही सहनशीलता अविश्वसनीय इनपुट पर भरोसा करने से गुप्त चैनल बन सकती है।

तो अगली बार जब अक्षरों, अंकों, प्लस, और स्लाश की स्ट्रिंग आपके टर्मिनल में उतरे, तो आप पूरी कहानी जानते हैं। एक फ़ंक्शन कॉल काम करती है, डिकोडर वह शालीन भूत है जो कभी नहीं मना करता, base64url का अपना डिकोडर है, चरसेट वह फैसला है जो आप जानबूझकर करते हैं, फ़ाइलें कच्ची आती हैं और कच्ची जाती हैं, और हैश ही वह सबूत है जो मायने रखता है। और अगर एक दिन आपको सफ़र की दूसरी दिशा में जाना पड़े, अपने कच्चे डेटा को टेक्स्ट एनवलप में लपेटकर दुनिया में भेजना, तो नीचे लिंक वाली Perl में Base64 एन्कोडिंग की संबंधित आर्टिकल उस रस्म को उसी गहराई में कवर करती है।

अंतिम अपडेट: 2026-09-08

संबंधित लेख: Perl में Base64 एन्कोडिंग: एक सम्पूर्ण गाइड