-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4615906
commit 74d9579
Showing
9 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2015 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "butil/base64.h" | ||
#include "butil/base64url.h" | ||
|
||
#include "third_party/modp_b64/modp_b64_data.h" | ||
|
||
namespace butil { | ||
|
||
// Base64url maps {+, /} to {-, _} in order for the encoded content to be safe | ||
// to use in a URL. These characters will be translated by this implementation. | ||
#define BASE64_CHARS "+/" | ||
#define BASE64_URL_SAFE_CHARS "-_" | ||
#define URL_SAFE_CHAR62 '-' | ||
#define URL_SAFE_CHAR63 '_' | ||
|
||
void Base64UrlEncode(const StringPiece& input, | ||
Base64UrlEncodePolicy policy, | ||
std::string* output) { | ||
Base64Encode(input, output); | ||
|
||
std::replace(output->begin(), output->end(), CHAR62, URL_SAFE_CHAR62); | ||
std::replace(output->begin(), output->end(), CHAR63, URL_SAFE_CHAR63); | ||
|
||
switch (policy) { | ||
case Base64UrlEncodePolicy::INCLUDE_PADDING: | ||
// The padding included in |*output| will not be amended. | ||
break; | ||
case Base64UrlEncodePolicy::OMIT_PADDING: | ||
// The padding included in |*output| will be removed. | ||
const size_t last_non_padding_pos = | ||
output->find_last_not_of(CHARPAD); | ||
if (last_non_padding_pos != std::string::npos) { | ||
output->resize(last_non_padding_pos + 1); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
bool Base64UrlDecode(const StringPiece& input, | ||
Base64UrlDecodePolicy policy, | ||
std::string* output) { | ||
// Characters outside of the base64url alphabet are disallowed, which includes | ||
// the {+, /} characters found in the conventional base64 alphabet. | ||
if (input.find_first_of(BASE64_CHARS) != std::string::npos) | ||
return false; | ||
|
||
const size_t required_padding_characters = input.size() % 4; | ||
const bool needs_replacement = | ||
input.find_first_of(BASE64_URL_SAFE_CHARS) != std::string::npos; | ||
|
||
switch (policy) { | ||
case Base64UrlDecodePolicy::REQUIRE_PADDING: | ||
// Fail if the required padding is not included in |input|. | ||
if (required_padding_characters > 0) | ||
return false; | ||
break; | ||
case Base64UrlDecodePolicy::IGNORE_PADDING: | ||
// Missing padding will be silently appended. | ||
break; | ||
case Base64UrlDecodePolicy::DISALLOW_PADDING: | ||
// Fail if padding characters are included in |input|. | ||
if (input.find_first_of(CHARPAD) != std::string::npos) | ||
return false; | ||
break; | ||
} | ||
|
||
// If the string either needs replacement of URL-safe characters to normal | ||
// base64 ones, or additional padding, a copy of |input| needs to be made in | ||
// order to make these adjustments without side effects. | ||
if (required_padding_characters > 0 || needs_replacement) { | ||
std::string base64_input; | ||
|
||
size_t base64_input_size = input.size(); | ||
if (required_padding_characters > 0) | ||
base64_input_size += 4 - required_padding_characters; | ||
|
||
base64_input.reserve(base64_input_size); | ||
input.AppendToString(&base64_input); | ||
|
||
// Substitute the base64url URL-safe characters to their base64 equivalents. | ||
std::replace(base64_input.begin(), base64_input.end(), URL_SAFE_CHAR62, CHAR62); | ||
std::replace(base64_input.begin(), base64_input.end(), URL_SAFE_CHAR63, CHAR63); | ||
|
||
// Append the necessary padding characters. | ||
base64_input.resize(base64_input_size, '='); | ||
|
||
return Base64Decode(base64_input, output); | ||
} | ||
|
||
return Base64Decode(input, output); | ||
} | ||
|
||
} // namespace butil |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2015 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef BASE_BASE64URL_H_ | ||
#define BASE_BASE64URL_H_ | ||
|
||
#include <string> | ||
|
||
#include "butil/base_export.h" | ||
#include "butil/strings/string_piece.h" | ||
|
||
namespace butil { | ||
|
||
enum class Base64UrlEncodePolicy { | ||
// Include the trailing padding in the output, when necessary. | ||
INCLUDE_PADDING, | ||
|
||
// Remove the trailing padding from the output. | ||
OMIT_PADDING | ||
}; | ||
|
||
// Encodes the |input| string in base64url, defined in RFC 4648: | ||
// https://tools.ietf.org/html/rfc4648#section-5 | ||
// | ||
// The |policy| defines whether padding should be included or omitted from the | ||
// encoded |*output|. |input| and |*output| may reference the same storage. | ||
BUTIL_EXPORT void Base64UrlEncode(const StringPiece& input, | ||
Base64UrlEncodePolicy policy, | ||
std::string* output); | ||
|
||
enum class Base64UrlDecodePolicy { | ||
// Require inputs to contain trailing padding if non-aligned. | ||
REQUIRE_PADDING, | ||
|
||
// Accept inputs regardless of whether they have the correct padding. | ||
IGNORE_PADDING, | ||
|
||
// Reject inputs if they contain any trailing padding. | ||
DISALLOW_PADDING | ||
}; | ||
|
||
// Decodes the |input| string in base64url, defined in RFC 4648: | ||
// https://tools.ietf.org/html/rfc4648#section-5 | ||
// | ||
// The |policy| defines whether padding will be required, ignored or disallowed | ||
// altogether. |input| and |*output| may reference the same storage. | ||
BUTIL_EXPORT bool Base64UrlDecode(const StringPiece& input, | ||
Base64UrlDecodePolicy policy, | ||
std::string* output) WARN_UNUSED_RESULT; | ||
|
||
} // namespace butil | ||
|
||
#endif // BASE_BASE64URL_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// Copyright 2015 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "butil/base64url.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace butil { | ||
|
||
TEST(Base64UrlTest, EncodeIncludePaddingPolicy) { | ||
std::string output; | ||
Base64UrlEncode("hello?world", Base64UrlEncodePolicy::INCLUDE_PADDING, | ||
&output); | ||
|
||
// Base64 version: aGVsbG8/d29ybGQ= | ||
EXPECT_EQ("aGVsbG8_d29ybGQ=", output); | ||
|
||
// Test for behavior for very short and empty strings. | ||
Base64UrlEncode("??", Base64UrlEncodePolicy::INCLUDE_PADDING, &output); | ||
EXPECT_EQ("Pz8=", output); | ||
|
||
Base64UrlEncode("", Base64UrlEncodePolicy::INCLUDE_PADDING, &output); | ||
EXPECT_EQ("", output); | ||
} | ||
|
||
TEST(Base64UrlTest, EncodeOmitPaddingPolicy) { | ||
std::string output; | ||
Base64UrlEncode("hello?world", Base64UrlEncodePolicy::OMIT_PADDING, &output); | ||
|
||
// base64 version: aGVsbG8/d29ybGQ= | ||
EXPECT_EQ("aGVsbG8_d29ybGQ", output); | ||
|
||
// Test for behavior for very short and empty strings. | ||
Base64UrlEncode("??", Base64UrlEncodePolicy::OMIT_PADDING, &output); | ||
EXPECT_EQ("Pz8", output); | ||
|
||
Base64UrlEncode("", Base64UrlEncodePolicy::OMIT_PADDING, &output); | ||
EXPECT_EQ("", output); | ||
} | ||
|
||
TEST(Base64UrlTest, DecodeRequirePaddingPolicy) { | ||
std::string output; | ||
ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ=", | ||
Base64UrlDecodePolicy::REQUIRE_PADDING, &output)); | ||
|
||
EXPECT_EQ("hello?world", output); | ||
|
||
ASSERT_FALSE(Base64UrlDecode( | ||
"aGVsbG8_d29ybGQ", Base64UrlDecodePolicy::REQUIRE_PADDING, &output)); | ||
|
||
// Test for behavior for very short and empty strings. | ||
ASSERT_TRUE( | ||
Base64UrlDecode("Pz8=", Base64UrlDecodePolicy::REQUIRE_PADDING, &output)); | ||
EXPECT_EQ("??", output); | ||
|
||
ASSERT_TRUE( | ||
Base64UrlDecode("", Base64UrlDecodePolicy::REQUIRE_PADDING, &output)); | ||
EXPECT_EQ("", output); | ||
} | ||
|
||
TEST(Base64UrlTest, DecodeIgnorePaddingPolicy) { | ||
std::string output; | ||
ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ", | ||
Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
|
||
EXPECT_EQ("hello?world", output); | ||
|
||
// Including the padding is accepted as well. | ||
ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ=", | ||
Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
|
||
EXPECT_EQ("hello?world", output); | ||
} | ||
|
||
TEST(Base64UrlTest, DecodeDisallowPaddingPolicy) { | ||
std::string output; | ||
ASSERT_FALSE(Base64UrlDecode( | ||
"aGVsbG8_d29ybGQ=", Base64UrlDecodePolicy::DISALLOW_PADDING, &output)); | ||
|
||
// The policy will allow the input when padding has been omitted. | ||
ASSERT_TRUE(Base64UrlDecode( | ||
"aGVsbG8_d29ybGQ", Base64UrlDecodePolicy::DISALLOW_PADDING, &output)); | ||
|
||
EXPECT_EQ("hello?world", output); | ||
} | ||
|
||
TEST(Base64UrlTest, DecodeDisallowsBase64Alphabet) { | ||
std::string output; | ||
|
||
// The "/" character is part of the conventional base64 alphabet, but has been | ||
// substituted with "_" in the base64url alphabet. | ||
ASSERT_FALSE(Base64UrlDecode( | ||
"aGVsbG8/d29ybGQ=", Base64UrlDecodePolicy::REQUIRE_PADDING, &output)); | ||
} | ||
|
||
TEST(Base64UrlTest, DecodeDisallowsPaddingOnly) { | ||
std::string output; | ||
|
||
ASSERT_FALSE(Base64UrlDecode( | ||
"=", Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
ASSERT_FALSE(Base64UrlDecode( | ||
"==", Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
ASSERT_FALSE(Base64UrlDecode( | ||
"===", Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
ASSERT_FALSE(Base64UrlDecode( | ||
"====", Base64UrlDecodePolicy::IGNORE_PADDING, &output)); | ||
} | ||
|
||
} // namespace butil |