1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <array> 17#include <algorithm> 18 19#include "base64_utils.h" 20 21namespace OHOS::NetManagerStandard::Base64 { 22static std::string BASE64_CHARS = /* NOLINT */ 23 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 24 "abcdefghijklmnopqrstuvwxyz" 25 "0123456789+/"; 26 27static constexpr const uint32_t CHAR_ARRAY_LENGTH_THREE = 3; 28static constexpr const uint32_t CHAR_ARRAY_LENGTH_FOUR = 4; 29 30enum BASE64_ENCODE_CONSTANT : uint8_t { 31 BASE64_ENCODE_MASK1 = 0xfc, 32 BASE64_ENCODE_MASK2 = 0x03, 33 BASE64_ENCODE_MASK3 = 0x0f, 34 BASE64_ENCODE_MASK4 = 0x3f, 35 BASE64_ENCODE_MASK5 = 0xf0, 36 BASE64_ENCODE_MASK6 = 0xc0, 37 BASE64_ENCODE_OFFSET2 = 2, 38 BASE64_ENCODE_OFFSET4 = 4, 39 BASE64_ENCODE_OFFSET6 = 6, 40 BASE64_ENCODE_INDEX0 = 0, 41 BASE64_ENCODE_INDEX1 = 1, 42 BASE64_ENCODE_INDEX2 = 2, 43}; 44 45enum BASE64_DECODE_CONSTANT : uint8_t { 46 BASE64_DECODE_MASK1 = 0x30, 47 BASE64_DECODE_MASK2 = 0xf, 48 BASE64_DECODE_MASK3 = 0x3c, 49 BASE64_DECODE_MASK4 = 0x3, 50 BASE64_DECODE_OFFSET2 = 2, 51 BASE64_DECODE_OFFSET4 = 4, 52 BASE64_DECODE_OFFSET6 = 6, 53 BASE64_DECODE_INDEX0 = 0, 54 BASE64_DECODE_INDEX1 = 1, 55 BASE64_DECODE_INDEX2 = 2, 56 BASE64_DECODE_INDEX3 = 3, 57}; 58 59static inline bool IsBase64Char(const char c) 60{ 61 return (isalnum(c) || (c == '+') || (c == '/')); 62} 63 64static inline void MakeCharFour(const std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree, 65 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour) 66{ 67 const uint8_t table[CHAR_ARRAY_LENGTH_FOUR] = { 68 static_cast<uint8_t>((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK1) >> BASE64_ENCODE_OFFSET2), 69 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK2) << BASE64_ENCODE_OFFSET4) + 70 ((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK5) >> BASE64_ENCODE_OFFSET4)), 71 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK3) << BASE64_ENCODE_OFFSET2) + 72 ((charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK6) >> BASE64_ENCODE_OFFSET6)), 73 static_cast<uint8_t>(charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK4), 74 }; 75 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) { 76 charArrayFour[index] = table[index]; 77 } 78} 79 80static inline void MakeCharTree(const std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour, 81 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree) 82{ 83 const uint8_t table[CHAR_ARRAY_LENGTH_THREE] = { 84 static_cast<uint8_t>((charArrayFour[BASE64_DECODE_INDEX0] << BASE64_DECODE_OFFSET2) + 85 ((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK1) >> BASE64_DECODE_OFFSET4)), 86 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK2) << BASE64_DECODE_OFFSET4) + 87 ((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK3) >> BASE64_DECODE_OFFSET2)), 88 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK4) << BASE64_DECODE_OFFSET6) + 89 charArrayFour[BASE64_DECODE_INDEX3]), 90 }; 91 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_THREE; ++index) { 92 charArrayThree[index] = table[index]; 93 } 94} 95 96std::string Encode(const std::string &source) 97{ 98 auto it = source.begin(); 99 std::string ret; 100 size_t index = 0; 101 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = {0}; 102 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = {0}; 103 104 while (it != source.end()) { 105 charArrayThree[index] = *it; 106 ++index; 107 ++it; 108 if (index != CHAR_ARRAY_LENGTH_THREE) { 109 continue; 110 } 111 MakeCharFour(charArrayThree, charArrayFour); 112 std::for_each(charArrayFour.begin(), charArrayFour.end(), [&ret](uint8_t idx) { 113 ret += BASE64_CHARS[idx]; 114 }); 115 index = 0; 116 } 117 if (index == 0) { 118 return ret; 119 } 120 121 for (auto i = index; i < CHAR_ARRAY_LENGTH_THREE; ++i) { 122 charArrayThree[i] = 0; 123 } 124 MakeCharFour(charArrayThree, charArrayFour); 125 126 for (size_t i = 0; i < index + 1; ++i) { 127 ret += BASE64_CHARS[charArrayFour[i]]; 128 } 129 130 while (index < CHAR_ARRAY_LENGTH_THREE) { 131 ret += '='; 132 ++index; 133 } 134 return ret; 135} 136 137std::string Decode(const std::string &encoded) 138{ 139 auto it = encoded.begin(); 140 size_t index = 0; 141 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = {0}; 142 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = {0}; 143 std::string ret; 144 145 while (it != encoded.end() && IsBase64Char(*it)) { 146 charArrayFour[index] = *it; 147 ++index; 148 ++it; 149 if (index != CHAR_ARRAY_LENGTH_FOUR) { 150 continue; 151 } 152 for (index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) { 153 charArrayFour[index] = BASE64_CHARS.find(static_cast<char>(charArrayFour[index])); 154 } 155 MakeCharTree(charArrayFour, charArrayThree); 156 std::for_each(charArrayThree.begin(), charArrayThree.end(), [&ret](uint8_t idx) { 157 ret += static_cast<char>(idx); 158 }); 159 index = 0; 160 } 161 if (index == 0) { 162 return ret; 163 } 164 165 for (auto i = index; i < CHAR_ARRAY_LENGTH_FOUR; ++i) { 166 charArrayFour[i] = 0; 167 } 168 for (unsigned char &i : charArrayFour) { 169 std::string::size_type idx = BASE64_CHARS.find(static_cast<char>(i)); 170 if (idx != std::string::npos) { 171 i = static_cast<unsigned char>(idx); 172 } 173 } 174 MakeCharTree(charArrayFour, charArrayThree); 175 176 for (size_t i = 0; i < index - 1; i++) { 177 ret += static_cast<char>(charArrayThree[i]); 178 } 179 return ret; 180} 181} // namespace OHOS::NetManagerStandard::Base64 182