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 "base64.h" 17 18namespace panda::es2panda::util { 19std::string Base64Encode(const std::string &inputString) 20{ 21 size_t strLen = inputString.length(); 22 size_t encodedStrLen = strLen / TO_TRANSFORM_CHAR_NUM * TRANSFORMED_CHAR_NUM; 23 if (strLen % TO_TRANSFORM_CHAR_NUM != 0) { 24 encodedStrLen += TRANSFORMED_CHAR_NUM; 25 } 26 std::string encodedRes = std::string(encodedStrLen, '\0'); 27 const char* base64CharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 28 // 2: the index do not exceed the range of encodedRes and form a complete four-character block 29 for (size_t i = 0, j = 0; i < encodedRes.length() - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { 30 // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit 31 // former 00 + first 6 bits of the first char 32 encodedRes[i] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0xff) >> 2]; 33 // 00 + the last 2 bits of the first char + the first 4 bits of the second char 34 encodedRes[i + 1] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0x03) << 4 | 35 (static_cast<unsigned int>(inputString[j + 1]) & 0xf0) >> 4]; 36 // 00 + last 4 bits of the second char + the first 2 bits of the third char 37 encodedRes[i + 2] = base64CharSet[(static_cast<unsigned int>(inputString[j + 1]) & 0x0f) << 2 | 38 (static_cast<unsigned int>(inputString[j + 2]) & 0xc0) >> 6]; 39 // 00 + the last 6 bits of the third char 40 encodedRes[i + 3] = base64CharSet[static_cast<unsigned int>(inputString[j + 2]) & 0x3f]; 41 } 42 switch (strLen % TO_TRANSFORM_CHAR_NUM) { 43 // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes 44 case 1: 45 // 1,2: the original character is one, and two characters are missing after conversion 46 encodedRes[encodedRes.length() - 2] = '='; 47 encodedRes[encodedRes.length() - 1] = '='; 48 break; 49 case 2: 50 // 1: the original character is two, and a character are missing after conversion 51 encodedRes[encodedRes.length() - 1] = '='; 52 break; 53 default: 54 break; 55 } 56 return encodedRes; 57} 58 59std::string Base64Decode(const std::string &base64String) 60{ 61 const int decodeTable[] = { 62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65 -1, -1, -1, -1, -1, -1, -1, 66 62, // '+' 67 -1, -1, -1, 68 63, // '/' 69 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'~'9' 70 -1, -1, -1, -1, -1, -1, -1, 71 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 72 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'~'Z' 73 -1, -1, -1, -1, -1, -1, 74 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 75 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 'a'~'z' 76 }; 77 78 size_t strLen = base64String.length(); 79 size_t decodedStrLen = strLen / TRANSFORMED_CHAR_NUM * TO_TRANSFORM_CHAR_NUM; 80 if (base64String.find("==") != std::string::npos) { 81 decodedStrLen -= std::string("==").length(); 82 } else if (base64String.find("=") != std::string::npos) { 83 decodedStrLen -= std::string("=").length(); 84 } 85 std::string decodedRes = std::string(decodedStrLen, '\0'); 86 int firstChar = 0; 87 int secondChar = 0; 88 int thirdChar = 0; 89 int fourthChar = 0; 90 // 2: the index do not exceed the range of encodedRes and form a complete four-character block 91 for (size_t i = 0, j = 0; i < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { 92 // 1,2,3 is the nth character after the current position 93 firstChar = decodeTable[static_cast<unsigned char>(base64String[i])]; 94 secondChar = decodeTable[static_cast<unsigned char>(base64String[i + 1])]; 95 thirdChar = decodeTable[static_cast<unsigned char>(base64String[i + 2])]; 96 fourthChar = decodeTable[static_cast<unsigned char>(base64String[i + 3])]; 97 98 if (firstChar == -1 || secondChar == -1) { 99 return ""; 100 } 101 // the last 6 bit of the first char + the 2~3 bit of the second char(first 4 bit - 00) 102 decodedRes[j] = (static_cast<unsigned int>(firstChar) << 2) | (static_cast<unsigned int>(secondChar) >> 4); 103 if (j == decodedStrLen - 1) { 104 break; 105 } 106 if (thirdChar == -1) { 107 return ""; 108 } 109 // the last 4 bit of the second char + the 2~5 bit of the third char(first 6 bit - 00) 110 decodedRes[j + 1] = (static_cast<unsigned int>(secondChar) << 4) | (static_cast<unsigned int>(thirdChar) >> 2); 111 if (j + 1 == decodedStrLen - 1) { 112 break; 113 } 114 if (fourthChar == -1) { 115 return ""; 116 } 117 // the last 2 bit of the third char + the last 6 bit of the fourth char 118 decodedRes[j + 2] = (static_cast<unsigned int>(thirdChar) << 6) | static_cast<unsigned int>(fourthChar); 119 } 120 return decodedRes; 121} 122} // namespace panda::es2panda::util 123