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

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

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

पहली अच्छी ख़बर: encode_base64 2002 से Perl के कोर में रह रहा है, C में बना है, और आराम से तेज़ है। दिलचस्प बात यह है कि इस फ़ंक्शन की अपनी राय है। यह अपने आउटपुट को 76 चरों पर लपेटता है, आख़िर में एक न्यूलाइन जोड़ देता है, और वे Unicode चर जो आप पहले बाइट्स में बदल नहीं किए, उनको एन्कोड करने से इनकार कर देता है: Latin-1 सीमा से ऊपर वह डाय ही कर देता है, और उस सीमा से नीचे वह चुपचाप Latin-1 बाइट्स मान लेता है। यह गाइड उन सब रूपों से गुज़रती है जो एक Perl डेवलपर वाकई बनाता है: वन-लाइनर, MIME-लपटी ईमेल बॉडी, PEM-लपटी key, URL-safe टोकन, और वही स्ट्रीमिंग वर्ज़न जो तब काम आती है जब फ़ाइल मेमोरी में पूरी न समा सके।

एक फ़ंक्शन, एक छिपा न्यूलाइन

पूरा API, बिल्कुल वैसे ही जैसे आधुनिक दस्तावेज़ीकरण इसे पेश करता है:

encode_base64( $bytes )
encode_base64( $bytes, $eol )

एक और बार पढ़ें। दो आर्गुमेंट्स, उनमें से एक वैकल्पिक, एक return value, कोई फ्लैग नहीं। वैकल्पिक दूसरा आर्गुमेंट लाइन-एंडिंग का अनुक्रम है, और वह डिफ़ॉल्ट में सादा न्यूलाइन होता है, यानी Perl की सबसे बेगुनाह-सी लगने वाली कॉल भी लपेटा हुआ, न्यूलाइन-ख़त्म आउटपुट देती है:

use MIME::Base64 qw(encode_base64);
my $wrapped = encode_base64("Aladdin:open sesame");
print length($wrapped), "\n";  # 29: 28 चर और एक न्यूलाइन
my $single = encode_base64("Aladdin:open sesame", "");
print length($single), "\n";   # 28: बिना लपेटन के, खाली स्ट्रिंग पास करें

आउटपुट का आकार एक निश्चित पैटर्न का पालन करता है जिसे आप कॉल करने से पहले ही पकड़ सकते हैं:

इनपुट बाइट्स आउटपुट चर पैडिंग
0 0 कोई नहीं
1 4 दो =
2 4 एक =
3 4 कोई नहीं
100,000 133,336 कोई नहीं, एक ही लाइन में
3,000,000 4,000,000 कोई नहीं

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

use MIME::Base64 ();
my $with_wrap   = MIME::Base64::encoded_base64_length($bytes);        # 76-चर लाइनें, डिफ़ॉल्ट लाइन-एंडिंग
my $single_line = MIME::Base64::encoded_base64_length($bytes, "");    # बिना लपेटन के
my $mime_body   = MIME::Base64::encoded_base64_length($bytes, "\r\n");

याद रखने लायक एक और नियम है, क्योंकि यह एन्कोडर की चिल्लाने की एकमात्र तरकीब है: अगर आपकी स्ट्रिंग में 255 से ऊपर कॉड वाले चर हों, तो encode_base64 Wide character in subroutine entry के साथ डाय कर देता है। उस सीमा से नीचे असफलता चुपकी-चुपकी होती है: 255 तक के चर चुपचाप अपने Latin-1 बाइट्स में नीचे खिसक जाते हैं, इसलिए संकेत वाले चरों वाली स्ट्रिंग जो रूपांतरण से छूट गई, वह UTF-8 के बजाय Latin-1 में एन्कोड हो जाती है, और कोई आपको नहीं बताता। Base64 एन्कोडिंग सिर्फ़ एक-बाइट चरों के लिए परिभाषित है, और Perl 5.8 या बेहतर स्ट्रिंग्स में 255 से ऊपर चरों की मंज़ूरी देता है, इसलिए रूपांतरण वह फैसला है जो आप जानबूझकर करते हैं, Encode के साथ, बिल्कुल अगले भाग में।

टेक्स्ट या बाइट्स? वह कदम जो फ़ंक्शन नहीं उठा सकता

Perl स्ट्रिंग्स पर एक ख़ामोश फ्लैग चलता है जो बताता है कि वे चर रखती हैं या बाइट्स, और Base64 उसी रेखा के बाइट्स वाले पक्ष पर रहती है। अगर आपका टेक्स्ट एक चरों की स्ट्रिंग है - और JSON parse करने वाला, टेंपलेट, या UTF-8 स्रोत फ़ाइल में संकेत वाले अक्षरों वाली literal से आते वक़्त वह ठीक उसी रूप में होता है - तो एन्कोडर अंदाज़े से इनकार कर देता है: Latin-1 सीमा से ऊपर के चरों के लिए आपने कौन-सी बाइट्स की उम्मीद की, उसका अंदाज़ा लगाएगा ही नहीं, बल्कि आपको बता भी देता है; सीमा के नीचे वह चुपचाप Latin-1 का अंदाज़ा लगाता है। दोनों मामलों में दवा एक ही है, और वह Encode मॉड्यूल का एक कोर फ़ंक्शन है:

use MIME::Base64 qw(encode_base64);
use Encode qw(encode);
my $chars = "H\x{eb}llo W\x{f6}rld";  # चरों की स्ट्रिंग
my $utf8  = encode("UTF-8", $chars);  # अब: बाइट्स
my $b64   = encode_base64($utf8, "");
print $b64, "\n";  # SMOrbGxvIFfDtnJsZA==

वह encode कॉल ही पूरा नाच है: बाइट रूप चुनें, आधुनिक सब कुछ के लिए UTF-8, चरों को उन बाइट्स में बदलें, और तभी एन्कोडर को बाइट्स सौंपें। पुराने पश्चिमी टेक्स्ट के लिए जो Windows 1252 के रूप में आया है, रूपांतरण दूसरे नाम से वही फ़ंक्शन है, encode("Windows-1252", $legacy), जो आपको मूल एक-बाइट रूप लौटा देता है। Encode मॉड्यूल कोर है, इसलिए यह सब कुछ फ़्री है।

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

use Encode qw(encode decode);
my $right = encode("UTF-8", "H\x{eb}llo");
my $wrong = encode("UTF-8", $right);  # बाइट्स को चर मानकर दोबारा एन्कोड किया
print decode("UTF-8", $right), "\n";  # Hëllo
print decode("UTF-8", $wrong), "\n";  # Hëllo

इसे रोकने का अनुभव-नियम: बाइट्स बिल्कुल एक बार एन्कोड होते हैं, और utf8::is_utf8() दिखाता है कि स्ट्रिंग रेखा के कौन-से पक्ष पर है। फ्लैग set है तो आपके पास चर हैं और encode() कॉल सही कदम है; set नहीं है तो बाइट्स हैं और आप Base64 के लिए तैयार हैं।

लाइन लपेटन: तीन बोलियाँ, एक नियम

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

बिना लाइन-ब्रेक के। फ़ंक्शन का आउटपुट जिसमें लपेटन बंद है, बिल्कुल एक लाइन। URLs, JSON पेलोड्स, हेडर, डेटाबेस वैल्यूज़, और हर ऐसी चीज़ के लिए यही चाहिए जहाँ लाइन-ब्रेक बग होगा। और "बस Base64 दो" कहते वक़्त ज़्यादातर लोगों का मतलब भी यही होता है:

my $single = encode_base64($bytes, "");

MIME: 76 चर और CRLF। RFC 2045 की ईमेल कन्वेंशन: एन्कोडेड लाइनें 76 चरों से ऊपर नहीं जा सकतीं, और MIME की दुनिया CRLF बोलती है। यह मॉड्यूल की खुद की ज़िम्मेदारी है, दूसरे आर्गुमेंट से हो जाती है:

my $mime_body = encode_base64($bytes, "\r\n");

PEM: 64 चर और LF। की और सर्टिफिकेट उस पुरानी कन्वेंशन का पालन करते हैं जिसमें छोटी 64-चर लाइनें होती हैं, और मॉड्यूल वह चौड़ाई अपने आप नहीं बना सकता, इसलिए चार-लाइन का सहायक वह खाली जगह भर देता है:

sub wrap_lines {
  my ($text, $width) = @_;
  return join "\n", $text =~ /(.{1,$width})/g;
}
my $pem = "-----BEGIN CERTIFICATE-----\n"
        . wrap_lines(encode_base64($der, ""), 64) . "\n"
        . "-----END CERTIFICATE-----\n";

वही सहायक उन बाकी 64-चर बोलियों के लिए भी काम आता है - RFC 7468 की PKIX textual एन्कोडिंग और OpenPGP कवच, जिनकी डेटा लाइनें 64 चर चौड़ी होती हैं, और जिसकी आख़िरी CRC24 checksum लाइन GnuPG जोड़ता है, आप नहीं। एक फ़ँदा सब पर लागू है: encode_base64 नतीजे के बिल्कुल अंत में लाइन-एंडिंग जोड़ देता है, भले ही आख़िरी लाइन अपनी चौड़ाई तक पूरी भरी हुई हो। अगर स्ट्रीम के आगे का consumer उस ख़ाली लाइन पर टकराए, तो नतीजे पर rtrim कॉल उसे ठीक कर देती है।

URL-safe Base64: - और _ वाली वर्णमाला

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

use MIME::Base64 qw(encode_base64url);
my $seg = encode_base64url("sunset-42");
print $seg, "\n";  # c3Vuc2V0LTQy: बिना पैडिंग, बिना न्यूलाइन

वह एक कॉल तीनों बदलाव एक साथ कर देती है: वर्णमाला का बदलाव, कोई पैडिंग नहीं, कोई लाइन-ब्रेक नहीं। अगर आपके पास पहले से स्टैंडर्ड Base64 है और गंतव्य को URL-safe बोली चाहिए, तो दो स्ट्रिंग-संचालन उसे जगह पर ही बदल देती हैं:

sub to_urlsafe {
  my ($b64) = @_;
  $b64 =~ tr{+/}{-_};
  return $b64 =~ s/=+\z//r;
}
my $seg = to_urlsafe(encode_base64($bytes, ""));

कब इस्तेमाल करें: JSON Web Token के हिस्सों, OAuth के state और nonce पैरामीटर्स, API IDs जो आप URL पैथ्स में रखते हैं, और opaque keys जो एड्रेस बार या फ़ाइल-नाम में टिकनी चाहिए, जहाँ CPAN का Data::UUID::Base64URLSafe बिल्कुल इसके लिए मौजूद है। कब न इस्तेमाल करें: ईमेल बॉडीज़, PEM कवच, और हर जगह जहाँ तार के दूसरे सिरे पर स्टैंडर्ड वर्णमाला के consumer बैठे हों, क्योंकि - और _ उनके वचनभंडार में नहीं हैं। और दो वर्णमालाओं को चुपचाप मिलाएँ नहीं: URL-safe में एन्कोड किया गया मान URL-safe में ही डिकोड होना चाहिए, हर जगह, हमेशा। 3.11 से पुराने Perl पर, 2006 का स्टैंडअलोन MIME::Base64::URLSafe मॉड्यूल, जो Python के urlsafe कोडेक का पोर्ट है, urlsafe_b64encode देता है; किसी भी आधुनिक चीज़ पर बिल्ट-इन ही सही औज़ार है।

JWT बनाना: हर हिस्सा हाथ से

आधुनिक APIs में Base64 का प्रमुख consumer JSON Web Tokens हैं, और वे उपरोक्त खंड की URL-safe, बिना-पैडिंग वाली बोली इस्तेमाल करते हैं। RFC 7515 के मुताबिक, संक्षिप्त JWT तीन डॉट से अलग base64url हिस्से हैं: protected हेडर, पेलोड, और सिग्नेचर। एक को हाथ से बनाना हर हिस्सा को देखने का मज़ेदार तरीका है:

use MIME::Base64 qw(encode_base64url);
use JSON::PP qw(encode_json);
use Digest::SHA qw(hmac_sha256);
my $secret  = "correct-horse-battery-staple";
my $head    = encode_base64url(encode_json({ alg => "HS256", typ => "JWT" }));
my $claims  = encode_base64url(encode_json({ sub => "homer", role => "admin" }));
my $sig     = encode_base64url(hmac_sha256("$head.$claims", $secret));
my $jwt     = "$head.$claims.$sig";
print $jwt, "\n";  # compact HS256 टोकन; हर JSON part के अंदर की key का क्रम run-to-run बदलता है

तीन विवरण ध्यान देने लायक हैं। पहला, कोर JSON::PP मॉड्यूल का encode_json व्हाइटस्पेस-मुक्त संक्षिप्त UTF-8 बाइट्स निकालता है, जो बिल्कुल वही है जो JOSE स्पेसिफिकेशन टोकन के अंदर चाहता है। दूसरा, पेलोड किसी भी इंसान के लिए पढ़ा जा सकता है, और यह डिज़ाइन की बात है: JWT एक साइन किया हुआ टिकट है, सिक्रेट नहीं, इसलिए claims में कभी गोपनीय मान न रखें। तीसरा, सिग्नेचर कच्चे HMAC बाइट्स का base64url एन्कोडिंग है, इसीलिए hmac_sha256 बिना किसी hex फ़ॉर्मेटिंग के सीधा एन्कोडर में जाता है।

प्रोडक्शन के लिए आप साइनिंग को हाथ से नहीं करते। CPAN मॉड्यूल Crypt::JWT, जो CryptX पर खड़ा है, JWS और JWE दोनों को पूरे एल्गोरिद्म set के साथ सपोर्ट करता है:

use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(
  payload => { sub => "homer", role => "admin" },
  alg     => "HS256",
  key     => $secret,
);

और रिसीवर की तरफ, accepted_alg से एल्गोरिद्म पिन करें ताकि attacker टोकन को कमज़ोर वैरिएंट पर पलट न सके: decode_jwt(token => $jwt, key => $secret, accepted_alg => "HS256") सिग्नेचर सत्यापित करता है और फेलियर पर क्रोक कर देता है। समझने के लिए हाथ से बनाना ठीक है; पैसे के लिए लाइब्रेरी ठीक है।

HTTP: Auth हेडर, Data URI और WebSocket हैंडशेक

Authorization: Basic हेडर सबसे पुराना लाइव use case है: यूज़रनेम और पासवर्ड जो कॉलन से जुड़े हों, एक लाइन में एन्कोड, और सामने स्कीम का शब्द। यहाँ खाली स्ट्रिंग वाला दूसरा आर्गुमेंट बोझ उठाता है, क्योंकि हेडर फ़ील्ड के अंदर आख़िरी न्यूलाइन बग है:

use MIME::Base64 qw(encode_base64);
my $user = "alice";
my $pass = "s3cr3t";
my $header = "Basic " . encode_base64("$user:$pass", "");
print $header, "\n";  # Basic YWxpY2U6czNjcjN0

RFC 2397 के Data URI उसी फ़िकिर को तस्वीरों पर लागू करता है: पेलोड सीधे URL में बैठता है, इसलिए उसे फ़ेट करने की दूसरी रिक्वेस्ट की ज़रूरत नहीं। बाइनरी media ;base64 फ्लैग इस्तेमाल करते हैं, इसलिए पेलोड बिल्कुल वही है जो encode_base64 ने लपेटन बंद करके बनाया:

my $uri = "data:" . $mime_type . ";base64," . encode_base64($bytes, "");

फिर भी ट्रेड-ऑफ़ असली हैं। एन्कोडेड पेलोड फ़ाइल से करीब 33 प्रतिशत बड़ा है, जिससे HTML दस्तावेज़ खुद बड़ा हो जाता है। ब्राउज़र Data URI को फ़ाइल URL की तरह कैश नहीं करते - कैश करने के लिए कोई अलग फ़ेट तो नहीं, इसलिए हर पेज व्यू पर बाइट्स दस्तावेज़ का हिस्सा बनकर फिर चले जाते हैं, और RFC खुद कहता है कि Data URI सिर्फ़ छोटे मानों के लिए काम आते हैं। इन्हें avatars, आइकॉन्स, और छोटे inline ग्राफिक्स के लिए इस्तेमाल करें; बाकी सब के लिए असली फ़ाइलें। HTTP का एक तीसरा छोर भी है जो Base64 का चुपचाप इस्तेमाल करती है: RFC 6455 का WebSocket हैंडशेक, जहाँ क्लाइंट एक Sec-WebSocket-Key हेडर भेजता है जो 16 random बाइट्स का Base64 होता है। Mojolicious जैसे फ्रेमवर्क्स इसे आपके लिए कर देते हैं, पर अगर कभी वायर पर दिखे, तो अब आप जानते हैं कि वह क्या है:

use MIME::Base64 qw(encode_base64);
my $key = encode_base64(pack("C16", map { int(rand 256) } 1 .. 16), "");
print length($key), "\n";  # 24: 16 random बाइट्स, चार-चर समूह तक पैड

फ़ाइलें: slurp, 57-बाइट चंक और CLI

सबसे सीधा एन्कोडिंग काम: फ़ाइल टेक्स्ट बन जाती है। Perl स्ट्रिंग्स बाइट्स ही हैं, इसलिए ढूँढने को कोई बाइनरी मोड नहीं है - :raw लेयर ही सारा काम है। raw मोड में खोलें, पढ़ें, एन्कोड करें, लिखें:

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
local $/;
my $bytes = <$in>;
close $in;
open my $out, ">:raw", $ARGV[1] or die $!;
print {$out} encode_base64($bytes);
close $out;

:raw लेयर्स मायने रखती हैं। बिना उनसे, आते-जाते Perl बाइट्स को प्लेटफ़ॉर्म टेक्स्ट की तरह समझने की कोशिश करेगा, और डिफ़ॉल्ट एन्कोडिंग अलग रखने वाले सिस्टम्स पर यही वह ख़राबी है जो तब तक नहीं दिखती जब तक फ़ाइल कहीं और न खुले। और स्टोरेज की प्लानिंग करते वक़्त साइज़ का बिल याद रखें: 500 KB की तस्वीर 670 KB की टेक्स्ट फ़ाइल बन जाती है, और 1 GB की वीडियो 1.33 GB की।

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

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
while (read($in, my $buf, 57 * 10)) {
  print encode_base64($buf);
}
close $in;

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

perl -MMIME::Base64 -0777 -ne 'print encode_base64($_, "")' < file > file.b64

ईमेल: MIME बॉडी और अटैचमेंट्स

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

use MIME::Lite;
my $mime = MIME::Lite->new(
  From    => 'me@example.com',
  To      => 'you@example.com',
  Subject => 'A file',
  Type    => 'text/plain',
  Data    => 'The body text.',
);
$mime->attach(
  Type     => 'application/octet-stream',
  Data     => $bytes,
  Encoding => 'base64',
  Filename => 'hello.txt',
);

Encoding आर्गुमेंट ही ट्रिगर है: MIME::Lite अटैचमेंट को 76-चर लाइनों में Base64 एन्कोड करता है (मॉड्यूल के डिफ़ॉल्ट सादा न्यूलाइन के साथ; इन्हें CRLF में मेल ट्रांसपोर्ट बदलता है) और हिस्सा पर मेल खाता Content-Transfer-Encoding हेडर अंकित कर देता है। Email::MIME भी वही रुख़ रखता है और जो भी अटैचमेंट आप सौंपें उसे कच्चा डेटा स्ट्रिंग के तौर पर Base64 एन्कोड कर देता है (उसकी docs: "इस तरह बनाए गए हर हिस्सा को base64 में एन्कोड किया जाता है, बस सावधानी के तौर पर")। अगर आप कच्चा MIME संदेश हाथ से जोड़ रहे हैं, तो समतुल्य काम लपेटन खंड की दो लाइनों से होता है, encode_base64($bytes, "\r\n") और हेडर लाइन, और प्रोटोकॉल की पूरी कहानी यहीं ख़त्म है।

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

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

use MIME::Base64 qw(encode_base64);
# $dbh एक पहले से जुड़ा DBI handle है
my $stmt = $dbh->prepare(q{UPDATE photos SET data = ? WHERE id = ?});
$stmt->execute(encode_base64($bytes, ""), 42);

कॉन्फ़िग फ़ाइलें भी वही रूप हैं: JSON दस्तावेज़ जिसमें बाइनरी या सिक्रेट फ़ील्ड एक-लाइन Base64 स्ट्रिंग होती है, और यही वजह है कि दूसरा आर्गुमेंट मौजूद है:

use JSON::PP qw(encode_json);
my $config = {
  api_key  => encode_base64($key_bytes, ""),
  logo_png => encode_base64($png_bytes, ""),
};
open my $fh, ">:raw", "app.json" or die $!;
print {$fh} encode_json($config);
close $fh;

एनवायरन्मेंट वेरिएबल्स को एक चेतावनी का हक़ है। छोटे टोकन के लिए एनवायरन्मेंट में Base64 ठीक है, पर एन्कोडेड रूप मूल से 33 प्रतिशत बड़ा होता है, और ऑपरेटिंग सिस्टम हर आर्गुमेंट पर सीमा लगाता है। Linux पर सीमा है हर स्ट्रिंग के लिए 128 KB, जो execve लागू करता है, और एनवायरन्मेंट वेरिएबल में बड़ा ब्लाब डालने पर विफलता विनम्र नहीं होती: child प्रोसेस spawn होते ही रहस्यमयी एरर के साथ डाय हो जाता है। छोटे मान एनवायरन्मेंट में, बड़े मान फ़ाइल या डेटाबेस में।

परफ़ॉर्मेंस: काम C कर रहा है, Perl नहीं

कोर मॉड्यूल C में बना है, और वह C 1991 में metamail के लिए लिखे गए कोड से उतरा है, जो एक मनोरंजक तथ्य है, जब तक आप उसका असर न देख लें: एन्कोडर के पल्ले तीन दशकों का ट्यूनिंग है। आधुनिक मशीन पर यह gigabytes-per-second की रफ़्तार से डेटा प्रोसेस करता है, जिस डीस्क या नेटवर्क को वह आमतौर पर खिला रहा होता है, उससे तेज़ रहा होता है, इसलिए Base64 खुद लगभग कभी बॉटलनेक नहीं होता। बॉटलनेक I/O होता है।

C कंपाइलर के बिना किसी अजीब सिस्टम के लिए, CPAN का pure Perl जुड़वा MIME::Base64::Perl वही बेसिक इंटरफ़ेस देता है, कुछ गुना धीमा तो है, पर साधारण वर्कलोड्स के लिए आराम से काम का। और दो आदतें बड़े काम को पहले से तय रखती हैं: slurp करने के बजाय 57-बाइट चंक में स्ट्रीम करें, और अलॉक करने से पहले encoded_base64_length से बफ़र का साइज़ तय करें, जो आपको अंदाज़े और री-अलोकेशन दोनों से बचाता है।

फ़ँदे, एफ़्टरनून के ख़र्च के हिसाब से रैंक किए

फ़ँदे, क़रीब-क़रीब उसी क्रम में जिसमें वे काटते हैं:

फ़ँदा क्या होता है दवा
दूसरे आर्गुमेंट को भूल जाना आउटपुट 76 चरों पर लपेटा हुआ आता है, आख़िरी न्यूलाइन समेत, और आपकी URL, JSON फ़ील्ड, या हेडर वैल्यू के बीच में टूट जाता है एक-लाइन आउटपुट के लिए "" पास करें, और जहाँ ज़रूरत हो वहाँ लपेटन बरकरार रखें
ग़लत चौड़ाई पर लपेटन PEM सामने वाला 64-चर लाइनें चाहता है और 76 पाता है, या MIME बॉडी 76-चर की सीमा पार कर जाती है चौड़ाई को बोली से मिलाएँ: बिना लपेटन के लिए "", MIME के लिए "\r\n", PEM के लिए सहायक
wide-character का क्रोक 255 से ऊपर कॉड वाले चरों वाली स्ट्रिंग रिक्वेस्ट के बीच में Wide character in subroutine entry के साथ डाय हो जाती है चरों को पहले Encode से नाम लेकर जानबूझकर गुज़ारें, encode_base64 कॉल से पहले
डबल एन्कोडिंग पहले से UTF-8 बाइट्स को फिर encode("UTF-8", ...) से एन्कोड करना Hëllo को Hëllo बना देता है बाइट्स बिल्कुल एक बार एन्कोड होते हैं; शक हो तो utf8::is_utf8() की जाँच करें
वर्णमालाओं को चुपचाप मिला लेना - और _ से एन्कोड किया गया मान स्टैंडर्ड वर्णमाला के डिकोडर तक पहुँचता है और क़चरे के रूप में लौटता है हर मान के लिए एक बोली, सिरे से सिरे तक: सीमा पर base64url या स्टैंडर्ड चुनें
आख़िरी लाइन एंडिंग encode_base64 eol जोड़ देता है भले ही आख़िरी लाइन ठीक भरी हुई हो, और सख़्त सामने वाले को ख़ाली लाइन दिखती है सामने वाला सख़्त हो तो नतीजा पर chomp या rtrim करें
डेटाबेस में लपेटा हुआ मान न्यूलाइन TEXT कॉलम के अंदर उतर जाते हैं और अगली SELECT टूटा हुआ टोकन लौटाता है एक-लाइन रूप स्टोर करें; लपेटन सिर्फ़ गंतव्य पर करें
एनवायरन्मेंट वेरिएबल्स में बड़े ब्लाब 33 प्रतिशत की बढ़त और OS की प्रति-आर्गुमेंट सीमा मिलकर child प्रोसेस को spawn पर ही रहस्यमयी एरर के साथ मार देती हैं छोटे मान एनवायरन्मेंट में, बड़े मान फ़ाइल या डेटाबेस में
यह मान लेना कि Base64 ही सुरक्षा है फ़ॉर्मेट कुछ छुपाता ही नहीं, और सार्वजनिक रिकॉर्ड में असली घटनाएँ दर्ज हैं जहाँ एक यूज़र ने IMAP exchange में पेस्ट करके ग़लती से पासवर्ड सार्वजनिक कर दिया आउटपुट को बनते ही गोपनीय मानें, और उसे लॉग फ़ाइलों से दूर रखें
साइज़ के बिल को न देखकर नियोजन 500 KB की तस्वीर 670 KB टेक्स्ट बन जाती है, और वह स्टोरेज या पेलोड सीमा जो आपने नहीं चेक की, काटती है कमिट करने से पहले मूल साइज़ का 4/3 बजट बना लें

एन्कोडर द्वारा बताया गया इतिहास

Perl के Base64 एन्कोडर के पास एक मिनट खर्च करने लायक़ करियर है, और वह शुरू होता है पहले वेब टूलकिट से:

  • libwww perl में जन्म। एन्कोडर की शुरुआत LWP::Base64 के रूप में हुई, जिसे Martijn Koster और Joerg Reichelt ने लिखा था, और Gisle Aas ने उसे MIME::Base64 के तौर पर libwww perl में जड़ लिया; अप्रैल 1997 में वह अपने अलग CPAN वितरण के रूप में निकला, वर्ज़न 2.00, जिसका चेंजलॉग एंट्री सिर्फ़ इतना कहता है कि यह libwww perl 5.08 पर आधारित है।
  • रफ़्तार का दौर। 1998 की वर्ज़न 2.07 ने डिकोडर का तेज़ और समझदार C implementation ले कर आई, जो तब-आधुनिक Linux मशीनों पर करीब 25 प्रतिशत ज़्यादा तेज़ था, और ट्यूनिंग का दौर एक दशक तक चला।
  • Unicode का दौर। 2002 का Perl 5.8 ने 255 से ऊपर कॉड वाले चरों को साधारण स्ट्रिंग्स में उतारा, और मॉड्यूल ने क़दम-दर-क़दम जवाब दिया: 2001 की 2.12 ने एन्कोडिंग से पहले UTF-8 स्ट्रिंग्स को डाउनग्रेड किया, और आधुनिक Wide character in subroutine entry का क्रोक एन्कोडर का वही वादा निभाने का तरीका है। उसी साल की 2.13 कोर सिंक के साथ EBCDIC सपोर्ट भी आई, एक ऐसी याद कि Perl में Base64 आज भी मेनफ्रेम पर चलता है।
  • कमांड लाइन का दौर। 2003 की 2.14 से 2004 की 3.05 तक रिलीज़ों ने एक असली encode-base64 कमांड बंडल किया, उसके डिकोड और quoted-printable जुड़वा समेत; 2005 की 3.06 ने स्क्रिप्ट्स को अलग MIME Base64 Scripts वितरण में खिसका दिया।
  • URL-safe की एंट्री। 2006 में RFC 4648 ने URL-safe वर्णमाला को मानकीकृत किया, उसी साल स्टैंडअलोन MIME::Base64::URLSafe मॉड्यूल दिखा, और कोर मॉड्यूल 2010 की 3.11 में encode_base64url के एक कॉल के साथ पहूँच गया।
  • आधुनिक लाइन। 2020 की वर्ज़न 3.16 ने पैकेजिंग फिर से की और न्यूनतम वर्ज़न को Perl 5.6 तक उठाया; वर्तमान कोर Perl संस्करण 3.16 series के साथ आते हैं, और मॉड्यूल कोर वितरण के अंदर ही मेंटेन होता है, जो एक कोर मॉड्यूल के लिए उतना ही सुरक्षित घर है जितना हो सकता है।

मज़ेदार तथ्य, खास तौर पर Perl के

वे ट्रिविया जो इस कहानी को अच्छी बनाते हैं:

  • POD का उदाहरण एक जादुई वाक्य है। 1997 से मॉड्यूल की खुद की दस्तावेज़ीकरण Aladdin:open sesame एन्कोड करता आ रहा है, इसलिए स्ट्रिंग QWxhZGRpbjpvcGVuIHNlc2FtZQ== करीब तीस साल से मॉड्यूल का बिज़नेस कार्ड रही है।
  • डिफ़ॉल्ट लाइन एंडिंग वह है जो शायद आपने नहीं उम्मीद किया था। वह सादा \n है, MIME की बोलने वाली CRLF नहीं। RFC की खुद की कन्वेंशन के लिए दूसरा आर्गुमेंट चाहिए, और मॉड्यूल प्रोग्रामर के डिफ़ॉल्ट के साथ आता है, प्रोटोकॉल के डिफ़ॉल्ट के साथ नहीं।
  • खाली स्ट्रिंग का अपना नियम है। कुछ भी एन्कोड न करें तो कुछ भी वापस नहीं मिलता, कोई न्यूलाइन जोड़ा नहीं जाता: आख़िरी eol नियम का एकमात्र दस्तावेज़ित एक्ससेप्शन, और यही वजह है कि खाली फ़ाइल साफ़-सुथरा राउंड ट्रिप करती है।
  • IMAP का फौजदी कॉमा रखता है। RFC 3501 का mailbox-name वैरिएंट वर्णमाला में / की जगह कॉमा रख देता है, इसलिए IMAP सर्वर से आने वाली Base64 स्ट्रिंग में एक चर हो सकता है जिसे स्टैंडर्ड डिकोडर शोर की तरह ही मानता है।
  • 1991 की नस्ल असली है। C implementation की नस्ल metamail से आती है, Bellcore की 1991 की मेल प्रोग्राम से, Perl 5 के जन्म से तीन साल पहले, इसलिए हर encode_base64 कॉल क़िस्में 90 के दशक का कोड है।
  • pure Perl जुड़वे की अपनी कहानी है। जब 2004 की वर्ज़न 3.00 ने कोर मॉड्यूल से pure-Perl implementations हटा दीं, चेंजलॉग ने उन्हें bloat, जो XS implementations की असली समस्याएँ छुपाता है, और उन्हें फिर से MIME::Base64::Perl के तौर पर रिलीज़ किया गया, जहाँ वे आज भी रहते हैं।

तो अगली बार जब कच्चे बाइट्स को सिर्फ़ टेक्स्ट वाली दुनिया से गुज़रना हो, तो आप पूरी कहानी जानते हैं। एक फ़ंक्शन कॉल काम कर देती है, छिपा न्यूलाइन दूसरे आर्गुमेंट से आपका फैसला है, wide-चर वाला क्रोक एन्कोडर का तरीका है कि वह आपके Unicode को ईमानदार पकड़े रखे, URL-safe बोली 2010 से एक कॉल में है, फ़ाइलें 57-बाइट चंक में स्ट्रीम होती हैं, और 33 प्रतिशत का बिल प्रवेश शुल्क है। और अगर किसी दिन आपको उल्टी दिशा में सफ़र करना हो, अक्षरों की स्ट्रिंग लेकर मूल बाइट्स बाहर निकालने, तो नीचे लिंक वाली Perl में Base64 डिकोडिंग की संबंधित आर्टिकल उसी विस्तार से उस पूरे काम को ढकती है।

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

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