Base64 encoding and decoding with c++
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
base64 encoding and decoding with c++
License: Other
Base64 encoding and decoding with c++
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
Give this a try (SHA256 fingerprint):
base64_decode("lUsNVLwTUOmB9VNuaD96gWg7NnkpnqIle4+baDXCVIE", false).
Results in out-of-bounds indexing at:
Line 204 in 1b7dc2f
https://github.com/ReneNyffenegger/cpp-base64/blob/master/base64.cpp#L63
This line will not be catched by catch (std::exception)
, only catch (...)
.
(Of course it will be catched by catch (const char *)
, but this is not what users write.
Probably it should be replaced with std::runtime_error
.
std::string base64_encode(
unsigned char const* bytes_to_encode, unsigned int in_len, bool url) {
if (url) {
base64_chars[62] = '-';
base64_chars[63] = '_';
} else {
base64_chars[62] = '+';
base64_chars[63] = '/';
}
//...
}
If two threads call base64_encode
concurrently (one with url=true
and the other with url=false
, the values of base64_chars[62]
and base64_chars[63]
are undefined. For example, it's possible to get base64_chars[62]='-'
and base64_chars[63]='/'
, which is not a valid encoding.
The first test expects encoded = "UmVuw6kgTnlmZmVuZWdnZXIKaHR0cDovL3d3dy5yZW5lbnlmZmVuZWdnZXIuY2gKcGFzc2lvbiBmb3IgZGF0YQo=".
On my Windows this decodes to "René Nyffenegger\nhttp://www.renenyffenegger.ch\npassion for data\n"
Shouldn't the encoded value be
"UmVu6SBOeWZmZW5lZ2dlcgpodHRwOi8vd3d3LnJlbmVueWZmZW5lZ2dlci5jaApwYXNzaW9uIGZvciBkYXRhCg=="?
Codepage problem?
All other tests succeed.
Hi,
Could you create or push tags here, so releases will be visible?
it does not work with space truncation
Hello,
First of all, thanks for the implementation. I'd like to report a small bug. In some cases of URL-safe base64 strings, the decoding fails, because the exception If input is correct, this line should never be reached.
is thrown.
If you want to check the code directly, it's pretty straightforward. Inside base64_decode()
, in the main loop, there is a missing condition in the last if, which checks the last of character in the current quartet, namely the pos+3
-th.
while (pos < in_len) {
unsigned int pos_of_char_1 = pos_of_char(encoded_string[pos+1] );
ret.push_back( ( (pos_of_char(encoded_string[pos+0]) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4));
if (encoded_string[pos+2] != '=' && encoded_string[pos+2] != '.') { // accept URL-safe base 64 strings, too, so check for '.' also.
unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos+2] );
ret.push_back( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2));
if (encoded_string[pos+3] != '=') {
ret.push_back( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string[pos+3]) );
}
}
pos += 4;
}
I believe that the same check done for the pos+2
-th char should be done for the pos+3
-th char
Just create a bytestring with length= 3k-1, encode it as URL-safe and decode it.
void reproduce_error() {
//generate any sequence of bytes which needs exactly one char for padding.
unsigned char my_bytes[17];
int i;
for (i=0; i<17;i++) {
char random_char = 'a';
my_bytes[i] = *(reinterpret_cast <unsigned char const*> (&random_char));
}
std::string s =base64_encode(my_bytes,17,true);
base64_decode(s);
}
Thanks for quick accepting of adding header guard issue 👍
I have two more questions
This isn't so much a bug report but more of an alert or question about URL padding. The current implementation seems to use '.' for padding of URL content, rather than '='.
However, every online tool I found was either using '=' or not padding at all. So I looked up the RFC spec which says:
[3.2](https://www.rfc-editor.org/rfc/rfc4648#section-3.2). Padding of Encoded Data
In some circumstances, the use of padding ("=") in base-encoded data
is not required or used. In the general case, when assumptions about
the size of transported data cannot be made, padding is required to
yield correct decoded data.
And then
[5](https://www.rfc-editor.org/rfc/rfc4648#section-5). Base 64 Encoding with URL and Filename Safe Alphabet
The Base 64 encoding with an URL and filename safe alphabet has been
used in [[12](https://www.rfc-editor.org/rfc/rfc4648#ref-12)].
An alternative alphabet has been suggested that would use "~" as the
63rd character. Since the "~" character has special meaning in some
file system environments, the encoding described in this section is
recommended instead. The remaining unreserved URI character is ".",
but some file system environments do not permit multiple "." in a
filename, thus making the "." character unattractive as well.
The pad character "=" is typically percent-encoded when used in an
URI [[9](https://www.rfc-editor.org/rfc/rfc4648#ref-9)], but if the data length is known implicitly, this can be
avoided by skipping the padding; see [section 3.2](https://www.rfc-editor.org/rfc/rfc4648#section-3.2).
This encoding may be referred to as "base64url". This encoding
should not be regarded as the same as the "base64" encoding and
should not be referred to as only "base64". Unless clarified
otherwise, "base64" refers to the base 64 in the previous section.
This encoding is technically identical to the previous one, except
for the 62:nd and 63:rd alphabet character, as indicated in Table 2.
Table 2: The "URL and Filename safe" Base 64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 - (minus)
12 M 29 d 46 u 63 _
13 N 30 e 47 v (underline)
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y (pad) =
Can you help to encode the base64 encoding with japanese string
Hello,
I'm trying to use cpp-base64 to convert a png into base64. I'm trying to use the
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
constructor.
Whenever I try to compile my code I get the following error:
undefined reference to base64_encode[abi:cxx11](unsigned char const*, unsigned int, bool)
My compiler must be converting size_t type variables into unsigned int which triggers this undefined reference. Both attempts to use base64_encode below (one using vec.size() as the length argument and the other using an explicit size_t variable as the length argument) result in the same undefined reference. I'm not sure why my compiler is failing here, as vector.size() http://www.cplusplus.com/reference/vector/vector/size/ return a size_t variable and the explicitly defined size_t len should certainly be read as a size_t variable and not as an unsigned int. I think I must be missing a compiler flag but I don't know what exactly it is I'm missing. My code is below:
#include <cstddef> // one of many headers that defines size_t
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
string base64encoder(){
// https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp/
ifstream input("out.png", ios::in | ios::binary);
// https://stackoverflow.com/questions/42136152/cannot-get-vector-size-when-constructed-from-istreambuf-iterator
auto start = istreambuf_iterator<char>(input); // need to initialize start, stop like this so we can access vec.size(), see above link
auto stop = istreambuf_iterator<char>();
vector<unsigned char> vec(start, stop); // the unsigned char array that will hold binary string version of out.png.
auto base64_png = reinterpret_cast<const unsigned char*>(vec.data()); // convert vec to const unsigned char* to conform to base64_encode arg reqs.
size_t len = 50;
// vec.size() should return a size_t, which is what base64.h wants for this version of its constructor. HOWEVER vec.size() keeps returning unsigned int and causing build errors.
string result = base64_encode(base64_png, len); // feed vec to base64_encode and output the encoded string into result. results in compiler error
string result2 = base64_encode(base64_png, vec.size()); // results in compiler error
return result;
}
Thanks for any assistance you can give me!
Passing the decode method a strings of size so that
(size % 4) != 0
causes the algorithm to try to read memory not belonging to the input data
Hello, can you add an handling to special characters in the decode function ?
For example, with your actual implementation, "w6k=" will return "é" instead of "é".
Thank you :)
Can't remove '\n' directly at here ,because of the character not in standard base64-encoded data ,but i don't know better solution
issue at :base64.cpp:171
`
if (remove_linebreaks) {
std::string copy(encoded_string);
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
return base64_decode(copy, false);
}`
I looked at readme and the code, but I couldn’t find a way to encrypt or decrypt the file.
when i call base64_encode() , segment dmp, I get input use cv::imencode(".jpg", src, data_encode) (src is cv::Mat)
I compiled using :-
g++ test.cpp base64.cpp -o test-base64
But when I run ./test-bnase64
I cant see any thing at all. No error no output.
The license seems to be similar to the 3-clause BSD license in spirit, but not in exact wording.
Could you dual-license under your current license (for "backwards compatibility") and 3-clause BSD (or another established license you approve of)? This would help projects who want to be "on the safe side" licensing-wise.
Thanks @ReneNyffenegger for this useful c++ base64 library.
I noticed a similar old issue #24
Looks the problem is not fixed for invalid inputs.
As a simple example, base64_decode(std::string("a"))
will access encoded_string[1]
at line
https://github.com/ReneNyffenegger/cpp-base64/blob/master/base64.cpp#L207, which is beyond the encoded_string size.
Current code happen to work as there's a padding \0 after the string. But we cannot depend on that.
If we replace encoded_string[pos+1]
with encoded_string.at(pos+1)
, the test will throw.
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 1) >= this->size() (which is 1)
I noticed the function base64_ encode_ mime called encode_ mime, and this function uses pass value instead of pass reference. Will this result in unnecessary performance consumption?
make throws the below error
$ make
g++ -std=c++11 -Werror -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-declarations -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option -c base64.cpp -o base64-11.o
g++ -std=c++11 -Werror -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-declarations -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option -c test.cpp -o test-11.o
g++ base64-11.o test-11.o -o base64-test-11
g++ -std=c++17 -Werror -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-declarations -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option -c base64.cpp -o base64-17.o
g++ -std=c++17 -Werror -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-declarations -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option -c test.cpp -o test-17.o
g++ base64-17.o test-17.o -o base64-test-17
base64-test-11
make: base64-test-11: Command not found
Makefile:30: recipe for target 'test' failed
make: *** [test] Error 127
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.