File: Base64.cpp

package info (click to toggle)
librepfunc 1.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 424 kB
  • sloc: cpp: 1,601; makefile: 270
file content (148 lines) | stat: -rw-r--r-- 7,081 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*******************************************************************************
 * librepfunc - a collection of common functions, classes and tools.
 * See the README file for copyright information and how to reach the author.
 ******************************************************************************/
#include <string>    // std::string
#include <iostream>  // std::cout
#include <repfunc.h> // include this library

int main() {
  std::cout << "/*************************************************************\n"
            << " * Please read this article:\n"
            << " *   https://en.wikipedia.org/wiki/Base64\n"
            << " ************************************************************/\n"
            << "\n\n\n";

  std::cout << "== Examples ==\n\n";

  std::cout << "The example below uses ASCII text for simplicity, but this is"
            << " not a typical use\ncase, as Base64 encoded text can be safely "
            << "transferred across all systems that \ncan handle Base64.\nThe "
            << "more typical use is to encode binary data (such as an image);\n"
            << "the resulting Base64 data will only contain 64 different ASCII"
            << " characters, all\nof which can reliably be transferred across "
            << "systems that may corrupt the raw\nsource bytes.\n\n";

  std::cout << "Here is a well-known idiom from distributed computing:\n";

  std::string s("Many hands make light work.");
  std::cout << "'" << s << "'\n\n";

  std::cout << "When the quote is encoded into Base64, it is represented as a "
            << "byte sequence of \n8-bit-padded ASCII characters encoded in "
            << "MIME\'s Base64 scheme as follows\n(newlines and white spaces "
            << "may be present anywhere but are to be ignored on\ndecoding):"
            << "\n\n";

  std::vector<uint8_t> bytes(s.data(),s.data()+s.size());
  std::cout << "'" << ToBase64(bytes) << "'\n\n\n";


  bytes.erase(bytes.begin()+3,bytes.end());
  std::cout << "In the above quote, the encoded value of 'Man' is '"
            << ToBase64(bytes) << "'.\nEncoded in ASCII,the characters "
            << "'M', 'a', and 'n' are stored as the byte "
            << "values\n "
            << IntToHex('M',2) + ", " + IntToHex('a',2) + ", and " + IntToHex('n',2)
            << ", which are the 8-bit binary values\n"
            << IntToBits('M',8) + ", " + IntToBits('a',8) + ", and " + IntToBits('n',8)
            << ".\nThese three values are joined together into a 24-bit string,\n"
            << "producing '" + IntToBits('M'<<16 | 'a'<<8 | 'n',24) + "'.\n\n"
            << "Groups of 6 bits (6 bits have a maximum of 64 different "
            << "binary values) are\nconverted into individual numbers from "
            << "start to end (in this case, there are\nfour numbers in a "
            << "24-bit string), which are then converted into their\n"
            << "corresponding Base64 character values.\n\n";

  std::cout << "== Output padding ==\n\n";

  std::cout << "Because Base64 is a six-bit encoding, and because the decoded"
            << " values are divided\ninto 8-bit octets on a modern computer,"
            << " every four characters of Base64-encoded\ntext (4 sextets = "
            << "4 × 6 = 24 bits) represents three octets of unencoded text or\n"
            << "data (3 octets = 3 × 8 = 24 bits). This means that when the "
            << "length of the\nunencoded input is not a multiple of three, the "
            << "encoded output must have padding\nadded so that its length is a"
            << " multiple of four. The padding character is '=',\nwhich "
            << "indicates that no further bits are needed to fully encode the "
            << "input.\n(This is different from A, which means that the remain"
            << "ing bits are all zeros.)\nThe example below illustrates how tru"
            << "ncating the input of the above quote\nchanges the output "
            << "padding:\n\n";


  s = "light work.";
  bytes = std::vector<uint8_t>(s.data(),s.data()+s.size());
  for(int i=0; i<5; i++) {
     HexDump("Input", bytes);
     auto enc = ToBase64(bytes);
     int padding = (bytes.size()%3) == 0 ? 0 : 3 - (bytes.size()%3);
     std::cout << "   Output = '" << enc << "'"
               << ", length = " << IntToStr(enc.size())
               << ", padding = " << IntToStr(padding) << "bytes"
               << "\n\n\n\n";
     bytes.pop_back();
     }



  std::cout << "== Decoding Base64 with padding ==\n\n";

  std::cout << "When decoding Base64 text, four characters are typically "
            << "converted back to\nthree bytes. The only exceptions are when "
            << "padding characters exist.\nA single '=' indicates that the "
            << "four characters will decode to only two\nbytes, while '==' in"
            << "dicates that the four characters will decode to only a\nsingle"
            << " byte.\n\n"
            << "For example:\n\n";

  std::vector<std::string> samples;
  samples.push_back("bGlnaHQgdw==");
  samples.push_back("bGlnaHQgd28=");
  samples.push_back("bGlnaHQgd29y");

  for(auto s:samples) {
     bytes = std::vector<uint8_t>(s.data(),s.data()+s.size());
     size_t padding = s.find('=') == std::string::npos ? 0: s.size() - s.find('=');
     auto dec = FromBase64(s);
     dec.push_back(0); // zero termination for use as const char*.
     std::cout << "Encoded = '" + s + "'  padding bytes = "
               << IntToStr(padding) << ", Length of last encoded triple = "
               << IntToStr(3-padding) << ", Decoded = '"
               << (const char*) dec.data() << "'" << std::endl;
     }
  std::cout << "\n\n";



  std::cout << "== Decoding Base64 without padding ==\n\n";

  std::cout << "Without padding, after normal decoding of four characters to "
            << "three bytes over\nand over again, fewer than four encoded char"
            << "acters may remain. In this\nsituation, only two or three chara"
            << "cters can remain. A single remaining enco-\nded character is not"
            << " possible, because a single Base64 character only contains\n 6"
            << " bits, and 8 bits are  required to create a byte, so a minimum "
            << "of two Base64\ncharacters are required: The first character con"
            << "tributes 6 bits, and the second\ncharacter contributes its first"
            << " 2 bits.\n\n"
            << "For example:\n\n";

  samples[0] = "bGlnaHQgdw";
  samples[1] = "bGlnaHQgd28";
  samples[2] = "bGlnaHQgd29y";

  for(auto s:samples) {
     bytes = std::vector<uint8_t>(s.data(),s.data()+s.size());
     size_t padding = (s.size() % 3) == 0 ? 0 : 3 - (s.size() % 3);
     auto dec = FromBase64(s);
     dec.push_back(0); // zero termination for use as const char*.
     std::cout << "Encoded = " + BackFill("'" + s + "'",14)
               << "  Length of last encoded triple = "
               << IntToStr(3-padding) << ", Decoded = '"
               << (const char*) dec.data() << "'" << std::endl;
     }
  std::cout << "\n\n";

  return 0;
}