Base64 encoding for string input.

[ Merge of http://go/wvgerrit/119805 ]

This change adds 3 new functions for encoding binary data from a C++
string to a base64 encoded ASCII string.

The CDM and protobuf generated code use C++ strings to store binary
data.  These binary strings are commonly converted into a base64
encoded ASCII string for logging and for returning to the app.

This change also cleans up some of the internal components of the
string_conversions library to use several standard library C++11
method.

Bug: 181732604
Test: CE CDM unittests
Change-Id: I547568c6402e011344260f2df2a06e972122ab8a
This commit is contained in:
Alex Dale
2021-03-12 19:27:51 -08:00
parent 30ebbefb40
commit e51f869190
4 changed files with 312 additions and 213 deletions

View File

@@ -55,8 +55,14 @@ const std::pair<const std::string*, const std::string*> kBase64TestVectors[] = {
make_pair(&kTwoBytesOverData, &kTwoBytesOverB64Data),
make_pair(&kTestData, &kB64TestData)};
const std::string kBase64ErrorVectors[] = {"Foo$sa", "Foo\x99\x23\xfa\02",
"Foo==Foo", "FooBa"};
// Arbitrary invalid base64 test vectors
const std::string kBase64ErrorVectors[] = {"Foo$sa",
"Foo\x99\x23\xfa\02",
"Foo==Foo",
"FooBa",
"SGVsbG8sIFdvcmxkI===",
"SGVsbG8sIFdvcmxkI======",
"SGVsbG8sIFdvcmxkIQp=="};
std::string ConvertToBase64WebSafe(const std::string& std_base64_string) {
std::string str(std_base64_string);
@@ -77,28 +83,90 @@ class Base64EncodeDecodeTest
TEST_P(Base64EncodeDecodeTest, EncodeDecodeTest) {
std::pair<const std::string*, const std::string*> values = GetParam();
std::vector<uint8_t> decoded_vector = Base64Decode(values.second->data());
std::string decoded_string(decoded_vector.begin(), decoded_vector.end());
EXPECT_STREQ(values.first->data(), decoded_string.data());
std::string b64_string = Base64Encode(decoded_vector);
EXPECT_STREQ(values.second->data(), b64_string.data());
const std::string& plain_text_string = *(values.first);
const std::string& expected_encoded = *(values.second);
// Encode from string.
const std::string b64_string_encoded = Base64Encode(plain_text_string);
EXPECT_EQ(b64_string_encoded, expected_encoded);
// Encode from vector.
const std::vector<uint8_t> plain_text_vector(plain_text_string.begin(),
plain_text_string.end());
const std::string b64_vector_encoded = Base64Encode(plain_text_vector);
EXPECT_EQ(b64_vector_encoded, expected_encoded);
// Decode from string.
const std::vector<uint8_t> decoded_vector = Base64Decode(expected_encoded);
EXPECT_EQ(decoded_vector, plain_text_vector);
}
TEST_P(Base64EncodeDecodeTest, WebSafeEncodeDecodeTest) {
std::pair<const std::string*, const std::string*> values = GetParam();
std::string encoded_string = ConvertToBase64WebSafe(*(values.second));
std::vector<uint8_t> decoded_vector = Base64SafeDecode(encoded_string);
std::string decoded_string(decoded_vector.begin(), decoded_vector.end());
EXPECT_STREQ(values.first->data(), decoded_string.data());
std::string b64_string = Base64SafeEncode(decoded_vector);
EXPECT_STREQ(encoded_string.data(), b64_string.data());
const std::string& plain_text_string = *(values.first);
const std::string& expected_encoded =
ConvertToBase64WebSafe(*(values.second));
// Encode from string.
const std::string b64_string_encoded = Base64SafeEncode(plain_text_string);
EXPECT_EQ(b64_string_encoded, expected_encoded);
// Encode from vector.
const std::vector<uint8_t> plain_text_vector(plain_text_string.begin(),
plain_text_string.end());
const std::string b64_vector_encoded = Base64SafeEncode(plain_text_vector);
EXPECT_EQ(b64_vector_encoded, expected_encoded);
// Decode from string.
const std::vector<uint8_t> decoded_vector =
Base64SafeDecode(expected_encoded);
EXPECT_EQ(decoded_vector, plain_text_vector);
}
TEST_P(Base64EncodeDecodeTest, WebSafeEncodeNoPad) {
std::pair<const std::string*, const std::string*> values = GetParam();
const std::string& plain_text_string = *(values.first);
const std::string& padded_encoded = ConvertToBase64WebSafe(*(values.second));
// Encode from string.
const std::string b64_string_encoded =
Base64SafeEncodeNoPad(plain_text_string);
// If input is empty, output will be empty.
if (plain_text_string.empty()) {
EXPECT_TRUE(b64_string_encoded.empty());
return;
}
if (padded_encoded.back() == '=') {
// If padding is present in the regular encoding, then it should be
// striped from the result.
EXPECT_NE(b64_string_encoded.back(), '=');
const std::string expected_encoded =
padded_encoded.substr(0, b64_string_encoded.size());
EXPECT_EQ(b64_string_encoded, expected_encoded);
} else {
// If no padding is present, then results should be equal.
EXPECT_EQ(b64_string_encoded, padded_encoded);
}
// Encode from vector.
const std::vector<uint8_t> plain_text_vector(plain_text_string.begin(),
plain_text_string.end());
const std::string b64_vector_encoded =
Base64SafeEncodeNoPad(plain_text_vector);
// Assuming the above has passed, the results should be the same as
// a result encoded from a string.
EXPECT_EQ(b64_vector_encoded, b64_string_encoded);
}
class Base64ErrorDecodeTest : public ::testing::TestWithParam<std::string> {};
TEST_P(Base64ErrorDecodeTest, EncoderErrors) {
std::vector<uint8_t> result = Base64Decode(GetParam());
EXPECT_EQ(0u, result.size());
const std::vector<uint8_t> standard_result = Base64Decode(GetParam());
EXPECT_TRUE(standard_result.empty());
const std::vector<uint8_t> safe_result = Base64SafeDecode(GetParam());
EXPECT_TRUE(safe_result.empty());
}
INSTANTIATE_TEST_CASE_P(ExecutesBase64Test, Base64EncodeDecodeTest,