├── README.md ├── LICENSE ├── hex.h ├── base64.h ├── php ├── hex.php ├── test.php └── base64.php ├── hex.cpp ├── main.cpp └── base64.cpp /README.md: -------------------------------------------------------------------------------- 1 | Constant Time Encoding 2 | ====================== 3 | 4 | Constant time hex and base64, encode and decode. 5 | 6 | Base64 encoding with these character sets: 7 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" base64Encode() and base64Decode() 8 | * "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" base64EncodeDotSlash() and base64DecodeDotSlash() 9 | * "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" base64EncodeDotSlashOrdered() and base64DecodeDotSlashOrdered() 10 | 11 | Semi-tested 12 | =========== 13 | It looks correct there are some tests but there might be bugs. 14 | 15 | PHP 16 | === 17 | I'm pretty sure there are problems with PHP and multi-byte character strings. I think it's something screwy with strlen() and maybe ord() and chr(). So you should probably not use this yet. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Steve Thomas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /hex.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #ifndef CONST_TIME_HEX_H 24 | #define CONST_TIME_HEX_H 25 | 26 | int hexDecode (void *dest, const char *src, size_t srcLen); 27 | int hexDecodeLower(void *dest, const char *src, size_t srcLen); 28 | int hexDecodeUpper(void *dest, const char *src, size_t srcLen); 29 | void hexEncode (char *dest, const void *src, size_t srcLen); 30 | void hexEncodeUpper(char *dest, const void *src, size_t srcLen); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #ifndef CONST_TIME_BASE64_H 24 | #define CONST_TIME_BASE64_H 25 | 26 | void base64Encode (char *dest, const void *src, size_t srcLen); 27 | int base64Decode (void *dest, const char *src, size_t srcLen); 28 | void base64EncodeDotSlash (char *dest, const void *src, size_t srcLen); 29 | int base64DecodeDotSlash (void *dest, const char *src, size_t srcLen); 30 | void base64EncodeDotSlashOrdered(char *dest, const void *src, size_t srcLen); 31 | int base64DecodeDotSlashOrdered(void *dest, const char *src, size_t srcLen); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /php/hex.php: -------------------------------------------------------------------------------- 1 | 0x2f && $src < 0x3a) $ret += $src - 0x30 + 1; // -47 36 | $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); 37 | 38 | $src |= 0x20; 39 | 40 | // if ($src > 0x60 && $src < 0x67) $ret += $src - 0x61 + 10 + 1; // -86 41 | $ret += (((0x60 - $src) & ($src - 0x67)) >> 8) & ($src - 86); 42 | 43 | return $ret; 44 | } 45 | 46 | function hexDecodeNibbleLower($src) 47 | { 48 | // 0-9 0x30-0x39 49 | // a-f 0x61-0x66 50 | $ret = -1; 51 | 52 | // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 1; // -47 53 | $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); 54 | 55 | // if ($src > 0x60 && $src < 0x67) $ret += $src - 0x61 + 10 + 1; // -86 56 | $ret += (((0x60 - $src) & ($src - 0x67)) >> 8) & ($src - 86); 57 | 58 | return $ret; 59 | } 60 | 61 | function hexDecodeNibbleUpper($src) 62 | { 63 | // 0-9 0x30-0x39 64 | // A-F 0x41-0x46 65 | $ret = -1; 66 | 67 | // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 1; // -47 68 | $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); 69 | 70 | // if ($src > 0x40 && $src < 0x47) $ret += $src - 0x41 + 10 + 1; // -54 71 | $ret += (((0x40 - $src) & ($src - 0x47)) >> 8) & ($src - 54); 72 | 73 | return $ret; 74 | } 75 | 76 | function hexEncodeNibbleLower($src) 77 | { 78 | // 0-9 0x30-0x39 79 | // a-f 0x61-0x66 80 | $src += 0x30; 81 | 82 | // if (in > 0x39) in += 0x61 - 0x3a; 83 | $src += ((0x39 - $src) >> 8) & (0x61 - 0x3a); 84 | 85 | return chr($src); 86 | } 87 | 88 | function hexEncodeNibbleUpper($src) 89 | { 90 | // 0-9 0x30-0x39 91 | // A-F 0x41-0x46 92 | $src += 0x30; 93 | 94 | // if (in > 0x39) in += 0x41 - 0x3a; 95 | $src += ((0x39 - $src) >> 8) & (0x41 - 0x3a); 96 | 97 | return chr($src); 98 | } 99 | 100 | 101 | 102 | // ********************** 103 | // *** Main Functions *** 104 | // ********************** 105 | 106 | function hexDecode($src) 107 | { 108 | $err = 0; 109 | $srcLen = strlen($src); 110 | if ($srcLen % 2 != 0) 111 | { 112 | return 1; 113 | } 114 | $dest = ''; 115 | for ($i = 0; $i < $srcLen; $i += 2) 116 | { 117 | $tmp = (hexDecodeNibble(ord($src[$i + 0])) << 4) | hexDecodeNibble(ord($src[$i + 1])); 118 | $err |= $tmp >> 8; 119 | $dest .= chr($tmp & 0xff); 120 | } 121 | if ($err != 0) 122 | { 123 | return false; 124 | } 125 | return $dest; 126 | } 127 | 128 | function hexDecodeLower($src) 129 | { 130 | $err = 0; 131 | $srcLen = strlen($src); 132 | if ($srcLen % 2 != 0) 133 | { 134 | return 1; 135 | } 136 | $dest = ''; 137 | for ($i = 0; $i < $srcLen; $i += 2) 138 | { 139 | $tmp = (hexDecodeNibbleLower(ord($src[$i + 0])) << 4) | hexDecodeNibbleLower(ord($src[$i + 1])); 140 | $err |= $tmp >> 8; 141 | $dest .= chr($tmp & 0xff); 142 | } 143 | if ($err != 0) 144 | { 145 | return false; 146 | } 147 | return $dest; 148 | } 149 | 150 | function hexDecodeUpper($src) 151 | { 152 | $err = 0; 153 | $srcLen = strlen($src); 154 | if ($srcLen % 2 != 0) 155 | { 156 | return 1; 157 | } 158 | $dest = ''; 159 | for ($i = 0; $i < $srcLen; $i += 2) 160 | { 161 | $tmp = (hexDecodeNibbleUpper(ord($src[$i + 0])) << 4) | hexDecodeNibbleUpper(ord($src[$i + 1])); 162 | $err |= $tmp >> 8; 163 | $dest .= chr($tmp & 0xff); 164 | } 165 | if ($err != 0) 166 | { 167 | return false; 168 | } 169 | return $dest; 170 | } 171 | 172 | function hexEncode($src) 173 | { 174 | $dest = ''; 175 | $srcLen = strlen($src); 176 | for ($i = 0; $i < $srcLen; $i++) 177 | { 178 | $ch = ord($src[$i]); 179 | $dest .= hexEncodeNibbleLower($ch >> 4) . hexEncodeNibbleLower($ch & 0x0f); 180 | } 181 | return $dest; 182 | } 183 | 184 | function hexEncodeUpper($src) 185 | { 186 | $dest = ''; 187 | $srcLen = strlen($src); 188 | for ($i = 0; $i < $srcLen; $i++) 189 | { 190 | $ch = ord($src[$i]); 191 | $dest .= hexEncodeNibbleUpper($ch >> 4) . hexEncodeNibbleUpper($ch & 0x0f); 192 | } 193 | return $dest; 194 | } 195 | -------------------------------------------------------------------------------- /hex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #include "hex.h" 24 | #include 25 | 26 | // ************************ 27 | // *** Helper Functions *** 28 | // ************************ 29 | 30 | inline int hexDecodeNibble(char src) 31 | { 32 | // 0-9 0x30-0x39 33 | // A-F 0x41-0x46 or a-f 0x61-0x66 34 | int ch = (unsigned char) src; 35 | int ret = -1; 36 | 37 | // if (ch > 0x2f && ch < 0x3a) ret += ch - 0x30 + 1; // -47 38 | ret += (((0x2f - ch) & (ch - 0x3a)) >> 8) & (ch - 47); 39 | 40 | ch |= 0x20; 41 | 42 | // if (ch > 0x60 && ch < 0x67) ret += ch - 0x61 + 10 + 1; // -86 43 | ret += (((0x60 - ch) & (ch - 0x67)) >> 8) & (ch - 86); 44 | 45 | return ret; 46 | } 47 | 48 | inline int hexDecodeNibbleLower(char src) 49 | { 50 | // 0-9 0x30-0x39 51 | // a-f 0x61-0x66 52 | int ch = (unsigned char) src; 53 | int ret = -1; 54 | 55 | // if (ch > 0x2f && ch < 0x3a) ret += ch - 0x30 + 1; // -47 56 | ret += (((0x2f - ch) & (ch - 0x3a)) >> 8) & (ch - 47); 57 | 58 | // if (ch > 0x60 && ch < 0x67) ret += ch - 0x61 + 10 + 1; // -86 59 | ret += (((0x60 - ch) & (ch - 0x67)) >> 8) & (ch - 86); 60 | 61 | return ret; 62 | } 63 | 64 | inline int hexDecodeNibbleUpper(char src) 65 | { 66 | // 0-9 0x30-0x39 67 | // A-F 0x41-0x46 68 | int ch = (unsigned char) src; 69 | int ret = -1; 70 | 71 | // if (ch > 0x2f && ch < 0x3a) ret += ch - 0x30 + 1; // -47 72 | ret += (((0x2f - ch) & (ch - 0x3a)) >> 8) & (ch - 47); 73 | 74 | // if (ch > 0x40 && ch < 0x47) ret += ch - 0x41 + 10 + 1; // -54 75 | ret += (((0x40 - ch) & (ch - 0x47)) >> 8) & (ch - 54); 76 | 77 | return ret; 78 | } 79 | 80 | inline int hexDecodeByte(const char src[2]) 81 | { 82 | return (hexDecodeNibble(src[0]) << 4) | hexDecodeNibble(src[1]); 83 | } 84 | 85 | inline int hexDecodeByteLower(const char src[2]) 86 | { 87 | return (hexDecodeNibbleLower(src[0]) << 4) | hexDecodeNibbleLower(src[1]); 88 | } 89 | 90 | inline int hexDecodeByteUpper(const char src[2]) 91 | { 92 | return (hexDecodeNibbleUpper(src[0]) << 4) | hexDecodeNibbleUpper(src[1]); 93 | } 94 | 95 | inline char hexEncodeNibbleLower(unsigned int src) 96 | { 97 | // 0-9 0x30-0x39 98 | // a-f 0x61-0x66 99 | src += 0x30; 100 | 101 | // if (in > 0x39) in += 0x61 - 0x3a; 102 | src += ((0x39 - src) >> 8) & (0x61 - 0x3a); 103 | 104 | return (char) src; 105 | } 106 | 107 | inline char hexEncodeNibbleUpper(unsigned int src) 108 | { 109 | // 0-9 0x30-0x39 110 | // A-F 0x41-0x46 111 | src += 0x30; 112 | 113 | // if (in > 0x39) in += 0x41 - 0x3a; 114 | src += ((0x39 - src) >> 8) & (0x41 - 0x3a); 115 | 116 | return (char) src; 117 | } 118 | 119 | inline void hexEncodeByteLower(char dest[2], uint8_t src) 120 | { 121 | dest[0] = hexEncodeNibbleLower(src >> 4); 122 | dest[1] = hexEncodeNibbleLower(src & 0x0f); 123 | } 124 | 125 | inline void hexEncodeByteUpper(char dest[2], uint8_t src) 126 | { 127 | dest[0] = hexEncodeNibbleUpper(src >> 4); 128 | dest[1] = hexEncodeNibbleUpper(src & 0x0f); 129 | } 130 | 131 | 132 | // ********************** 133 | // *** Main Functions *** 134 | // ********************** 135 | 136 | int hexDecode(void *dest, const char *src, size_t srcLen) 137 | { 138 | int err = 0; 139 | 140 | if (srcLen % 2 != 0) 141 | { 142 | return 1; 143 | } 144 | srcLen /= 2; 145 | for (size_t i = 0; i < srcLen; i++) 146 | { 147 | int tmp = hexDecodeByte(src + 2 * i); 148 | 149 | err |= tmp >> 8; 150 | ((uint8_t*) dest)[i] = (uint8_t) tmp; 151 | } 152 | return err != 0; 153 | } 154 | 155 | int hexDecodeLower(void *dest, const char *src, size_t srcLen) 156 | { 157 | int err = 0; 158 | 159 | if (srcLen % 2 != 0) 160 | { 161 | return 1; 162 | } 163 | srcLen /= 2; 164 | for (size_t i = 0; i < srcLen; i++) 165 | { 166 | int tmp = hexDecodeByteLower(src + 2 * i); 167 | 168 | err |= tmp >> 8; 169 | ((uint8_t*) dest)[i] = (uint8_t) tmp; 170 | } 171 | return err != 0; 172 | } 173 | 174 | int hexDecodeUpper(void *dest, const char *src, size_t srcLen) 175 | { 176 | int err = 0; 177 | 178 | if (srcLen % 2 != 0) 179 | { 180 | return 1; 181 | } 182 | srcLen /= 2; 183 | for (size_t i = 0; i < srcLen; i++) 184 | { 185 | int tmp = hexDecodeByteUpper(src + 2 * i); 186 | 187 | err |= tmp >> 8; 188 | ((uint8_t*) dest)[i] = (uint8_t) tmp; 189 | } 190 | return err != 0; 191 | } 192 | 193 | void hexEncode(char *dest, const void *src, size_t srcLen) 194 | { 195 | for (size_t i = 0; i < srcLen; i++) 196 | { 197 | hexEncodeByteLower(dest + 2 * i, ((const uint8_t*) src)[i]); 198 | } 199 | dest[2 * srcLen] = 0; 200 | } 201 | 202 | void hexEncodeUpper(char *dest, const void *src, size_t srcLen) 203 | { 204 | for (size_t i = 0; i < srcLen; i++) 205 | { 206 | hexEncodeByteUpper(dest + 2 * i, ((const uint8_t*) src)[i]); 207 | } 208 | dest[2 * srcLen] = 0; 209 | } 210 | -------------------------------------------------------------------------------- /php/test.php: -------------------------------------------------------------------------------- 1 | > 4)) . 37 | chr((($i + 1) << 4) | (($i + 2) >> 2)) . 38 | chr((($i + 2) << 6) | ($i + 3) ); 39 | } 40 | 41 | for ($size = 1; $size <= 48; $size++) 42 | { 43 | $allDataBase64 = base64Encode(substr($allData, 0, $size)); 44 | printf("base64Encode(allData) = %s\n", $allDataBase64); 45 | 46 | $allDataBase64DotSlash = base64EncodeDotSlash(substr($allData, 0, $size)); 47 | printf("base64EncodeDotSlash(allData) = %s\n", $allDataBase64DotSlash); 48 | 49 | $allDataBase64DotSlashOrdered = base64EncodeDotSlashOrdered(substr($allData, 0, $size)); 50 | printf("base64EncodeDotSlashOrdered(allData) = %s\n\n", $allDataBase64DotSlashOrdered); 51 | 52 | $testAllData = base64Decode($allDataBase64); 53 | printf("base64Decode(allDataBase64) ret = %u: ", ($testAllData === false ? 1 : 0)); 54 | $good = true; 55 | for ($i = 0; $i < $size; $i++) 56 | { 57 | if ($testAllData[$i] != $allData[$i]) 58 | { 59 | $good = false; 60 | } 61 | } 62 | if ($testAllData === false || !$good) 63 | { 64 | $hasErrors = true; 65 | } 66 | printf("%s\n", ($good ? "good" : "bad")); 67 | 68 | $testAllData = base64DecodeDotSlash($allDataBase64DotSlash); 69 | printf("base64DecodeDotSlash(allDataBase64DotSlash) ret = %u: ", ($testAllData === false ? 1 : 0)); 70 | $good = true; 71 | for ($i = 0; $i < $size; $i++) 72 | { 73 | if ($testAllData[$i] != $allData[$i]) 74 | { 75 | $good = false; 76 | } 77 | } 78 | if ($testAllData === false || !$good) 79 | { 80 | $hasErrors = true; 81 | } 82 | printf("%s\n", ($good ? "good" : "bad")); 83 | 84 | $testAllData = base64DecodeDotSlashOrdered($allDataBase64DotSlashOrdered); 85 | printf("base64DecodeDotSlashOrdered(allDataBase64DotSlashOrdered) ret = %u: ", ($testAllData === false ? 1 : 0)); 86 | $good = true; 87 | for ($i = 0; $i < $size; $i++) 88 | { 89 | if ($testAllData[$i] != $allData[$i]) 90 | { 91 | $good = false; 92 | } 93 | } 94 | if ($testAllData === false || !$good) 95 | { 96 | $hasErrors = true; 97 | } 98 | printf("%s\n\n\n", ($good ? "good" : "bad")); 99 | } 100 | 101 | printf("Should error:\n"); 102 | $testAllData = base64Decode($allDataBase64DotSlash); 103 | printf("base64Decode(allDataBase64DotSlash) ret = %u: %s\n", ($testAllData === false ? 1 : 0), ($testAllData === false ? "good" : "bad")); 104 | if ($testAllData !== false) 105 | { 106 | $hasErrors = true; 107 | } 108 | $testAllData = base64DecodeDotSlash($allDataBase64); 109 | printf("base64DecodeDotSlash(allDataBase64) ret = %u: %s\n", ($testAllData === false ? 1 : 0), ($testAllData === false ? "good" : "bad")); 110 | if ($testAllData !== false) 111 | { 112 | $hasErrors = true; 113 | } 114 | $testAllData = base64DecodeDotSlashOrdered($allDataBase64); 115 | printf("base64DecodeDotSlashOrdered(allDataBase64) ret = %u: %s\n", ($testAllData === false ? 1 : 0), ($testAllData === false ? "good" : "bad")); 116 | if ($testAllData !== false) 117 | { 118 | $hasErrors = true; 119 | } 120 | 121 | if ($hasErrors) 122 | { 123 | printf("*** FAILED ***\n"); 124 | } 125 | else 126 | { 127 | printf("*** PASSED ***\n"); 128 | } 129 | return $hasErrors; 130 | } 131 | 132 | function testHex() 133 | { 134 | $hasErrors = false; 135 | $allBytes = ''; 136 | for ($i = 0; $i < 256; $i++) 137 | { 138 | $allBytes .= chr($i); 139 | } 140 | 141 | $allBytesHex = hexEncode($allBytes); 142 | printf("hexEncode(allBytes) = %s\n", $allBytesHex); 143 | 144 | $allBytesHexUpper = hexEncodeUpper($allBytes); 145 | printf("hexEncodeUpper(allBytes) = %s\n\n", $allBytesHexUpper); 146 | 147 | 148 | $allBytes = hexDecode($allBytesHex); 149 | printf("hexDecode(allBytesHexLower) ret = %u: ", ($allBytes === false ? 1 : 0)); 150 | $good = true; 151 | for ($i = 0; $i < 256; $i++) 152 | { 153 | if ($i != ord($allBytes[$i])) 154 | { 155 | $good = false; 156 | } 157 | } 158 | if ($allBytes === false || !$good) 159 | { 160 | $hasErrors = true; 161 | } 162 | printf("%s\n", ($good ? "good" : "bad")); 163 | 164 | 165 | $allBytes = hexDecode($allBytesHexUpper); 166 | printf("hexDecode(allBytesHexUpper) ret = %u: ", ($allBytes === false ? 1 : 0)); 167 | $good = true; 168 | for ($i = 0; $i < 256; $i++) 169 | { 170 | if ($i != ord($allBytes[$i])) 171 | { 172 | $good = false; 173 | } 174 | } 175 | if ($allBytes === false || !$good) 176 | { 177 | $hasErrors = true; 178 | } 179 | printf("%s\n", ($good ? "good" : "bad")); 180 | 181 | 182 | $allBytes = hexDecodeLower($allBytesHex); 183 | printf("hexDecodeLower(allBytesHexLower) ret = %u: ", ($allBytes === false ? 1 : 0)); 184 | $good = true; 185 | for ($i = 0; $i < 256; $i++) 186 | { 187 | if ($i != ord($allBytes[$i])) 188 | { 189 | $good = false; 190 | } 191 | } 192 | if ($allBytes === false || !$good) 193 | { 194 | $hasErrors = true; 195 | } 196 | printf("%s\n", ($good ? "good" : "bad")); 197 | 198 | 199 | $allBytes = hexDecodeUpper($allBytesHexUpper); 200 | printf("hexDecodeUpper(allBytesHexUpper) ret = %u: ", ($allBytes === false ? 1 : 0)); 201 | $good = true; 202 | for ($i = 0; $i < 256; $i++) 203 | { 204 | if ($i != ord($allBytes[$i])) 205 | { 206 | $good = false; 207 | } 208 | } 209 | if ($allBytes === false || !$good) 210 | { 211 | $hasErrors = true; 212 | } 213 | printf("%s\n", ($good ? "good" : "bad")); 214 | 215 | 216 | printf("\nShould error:\n"); 217 | $allBytes = hexDecodeLower($allBytesHexUpper); 218 | printf("hexDecodeLower(allBytesHexUpper) ret = %u\n", ($allBytes === false ? 1 : 0), ($allBytes === false ? "good" : "bad")); 219 | if ($allBytes !== false) 220 | { 221 | $hasErrors = true; 222 | } 223 | $allBytes = hexDecodeUpper($allBytesHex); 224 | printf("hexDecodeUpper(allBytesHexLower) ret = %u\n", ($allBytes === false ? 1 : 0), ($allBytes === false ? "good" : "bad")); 225 | if ($allBytes !== false) 226 | { 227 | $hasErrors = true; 228 | } 229 | 230 | if ($hasErrors) 231 | { 232 | printf("*** FAILED ***\n"); 233 | } 234 | else 235 | { 236 | printf("*** PASSED ***\n"); 237 | } 238 | return $hasErrors; 239 | } 240 | 241 | 242 | printf("*** Base64 ***\n"); 243 | $hasErrors = testBase64() != 0; 244 | 245 | printf("\n*** Hex ***\n"); 246 | $hasErrors = testHex() != 0 || $hasErrors; 247 | 248 | if ($hasErrors) 249 | { 250 | printf("\n***** FAILED *****\n"); 251 | } 252 | else 253 | { 254 | printf("\n***** ALL GOOD *****\n"); 255 | } 256 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #include "hex.h" 24 | #include "base64.h" 25 | #include 26 | #include 27 | #include 28 | 29 | int testBase64() 30 | { 31 | int ret; 32 | bool good; 33 | bool hasErrors = false; 34 | uint8_t allData[64*6/8] = {0}; 35 | uint8_t testAllData[64*6/8] = {0}; 36 | char allDataBase64[(sizeof(allData)+2)/3*4+1]; 37 | char allDataBase64DotSlash[(sizeof(allData)+2)/3*4+1]; 38 | char allDataBase64DotSlashOrdered[(sizeof(allData)+2)/3*4+1]; 39 | 40 | for (int i = 0, j = 0; i < 64; i += 4, j += 3) 41 | { 42 | allData[j ] = (uint8_t) (( i << 2) | ((i + 1) >> 4)); 43 | allData[j+1] = (uint8_t) (((i + 1) << 4) | ((i + 2) >> 2)); 44 | allData[j+2] = (uint8_t) (((i + 2) << 6) | (i + 3) ); 45 | } 46 | 47 | for (size_t size = 1; size <= sizeof(allData); size++) 48 | { 49 | base64Encode(allDataBase64, allData, size); 50 | printf("base64Encode(allData) = %s\n", allDataBase64); 51 | 52 | base64EncodeDotSlash(allDataBase64DotSlash, allData, size); 53 | printf("base64EncodeDotSlash(allData) = %s\n", allDataBase64DotSlash); 54 | 55 | base64EncodeDotSlashOrdered(allDataBase64DotSlashOrdered, allData, size); 56 | printf("base64EncodeDotSlash(allData) = %s\n\n", allDataBase64DotSlashOrdered); 57 | 58 | for (size_t i = 0; i < size; i++) 59 | { 60 | testAllData[i] = 0; 61 | } 62 | ret = base64Decode(testAllData, allDataBase64, strlen(allDataBase64)); 63 | printf("base64Decode(allDataBase64) ret = %u: ", ret); 64 | good = true; 65 | for (size_t i = 0; i < size; i++) 66 | { 67 | if (allData[i] != testAllData[i]) 68 | { 69 | good = false; 70 | } 71 | } 72 | if (ret != 0 || !good) 73 | { 74 | hasErrors = true; 75 | } 76 | printf("%s\n", (good ? "good" : "bad")); 77 | 78 | for (size_t i = 0; i < size; i++) 79 | { 80 | testAllData[i] = 0; 81 | } 82 | ret = base64DecodeDotSlash(testAllData, allDataBase64DotSlash, strlen(allDataBase64DotSlash)); 83 | printf("base64DecodeDotSlash(allDataBase64DotSlash) ret = %u: ", ret); 84 | good = true; 85 | for (size_t i = 0; i < size; i++) 86 | { 87 | if (allData[i] != testAllData[i]) 88 | { 89 | good = false; 90 | } 91 | } 92 | if (ret != 0 || !good) 93 | { 94 | hasErrors = true; 95 | } 96 | printf("%s\n", (good ? "good" : "bad")); 97 | 98 | for (size_t i = 0; i < size; i++) 99 | { 100 | testAllData[i] = 0; 101 | } 102 | ret = base64DecodeDotSlashOrdered(testAllData, allDataBase64DotSlashOrdered, strlen(allDataBase64DotSlashOrdered)); 103 | printf("base64DecodeDotSlashOrdered(allDataBase64DotSlashOrdered) ret = %u: ", ret); 104 | good = true; 105 | for (size_t i = 0; i < size; i++) 106 | { 107 | if (allData[i] != testAllData[i]) 108 | { 109 | good = false; 110 | } 111 | } 112 | if (ret != 0 || !good) 113 | { 114 | hasErrors = true; 115 | } 116 | printf("%s\n\n\n", (good ? "good" : "bad")); 117 | } 118 | 119 | printf("Should error:\n"); 120 | ret = base64Decode(testAllData, allDataBase64DotSlash, sizeof(allDataBase64DotSlash) - 1); 121 | printf("base64Decode(allDataBase64DotSlash) ret = %u: %s\n", ret, (ret != 0 ? "good" : "bad")); 122 | if (ret == 0) 123 | { 124 | hasErrors = true; 125 | } 126 | ret = base64DecodeDotSlash(testAllData, allDataBase64, sizeof(allDataBase64) - 1); 127 | printf("base64DecodeDotSlash(allDataBase64) ret = %u: %s\n", ret, (ret != 0 ? "good" : "bad")); 128 | if (ret == 0) 129 | { 130 | hasErrors = true; 131 | } 132 | ret = base64DecodeDotSlashOrdered(testAllData, allDataBase64, sizeof(allDataBase64) - 1); 133 | printf("base64DecodeDotSlashOrdered(allDataBase64) ret = %u: %s\n", ret, (ret != 0 ? "good" : "bad")); 134 | if (ret == 0) 135 | { 136 | hasErrors = true; 137 | } 138 | 139 | if (hasErrors) 140 | { 141 | printf("*** FAILED ***\n"); 142 | } 143 | else 144 | { 145 | printf("*** PASSED ***\n"); 146 | } 147 | return hasErrors; 148 | } 149 | 150 | int testHex() 151 | { 152 | int ret; 153 | bool good; 154 | bool hasErrors = false; 155 | uint8_t allBytes[256]; 156 | char allBytesHex[2 * sizeof(allBytes) + 1]; 157 | char allBytesHexUpper[2 * sizeof(allBytes) + 1]; 158 | 159 | for (int i = 0; i < sizeof(allBytes); i++) 160 | { 161 | allBytes[i] = (uint8_t) i; 162 | } 163 | 164 | hexEncode(allBytesHex, allBytes, sizeof(allBytes)); 165 | printf("hexEncode(allBytes) = %s\n", allBytesHex); 166 | 167 | hexEncodeUpper(allBytesHexUpper, allBytes, sizeof(allBytes)); 168 | printf("hexEncodeUpper(allBytes) = %s\n\n", allBytesHexUpper); 169 | 170 | for (int i = 0; i < sizeof(allBytes); i++) 171 | { 172 | allBytes[i] = 0; 173 | } 174 | ret = hexDecode(allBytes, allBytesHex, sizeof(allBytesHex) - 1); 175 | printf("hexDecode(allBytesHexLower) ret = %u: ", ret); 176 | good = true; 177 | for (int i = 0; i < sizeof(allBytes); i++) 178 | { 179 | if (i != allBytes[i]) 180 | { 181 | good = false; 182 | } 183 | } 184 | if (ret != 0 || !good) 185 | { 186 | hasErrors = true; 187 | } 188 | printf("%s\n", (good ? "good" : "bad")); 189 | 190 | for (int i = 0; i < sizeof(allBytes); i++) 191 | { 192 | allBytes[i] = 0; 193 | } 194 | ret = hexDecode(allBytes, allBytesHexUpper, sizeof(allBytesHexUpper) - 1); 195 | printf("hexDecode(allBytesHexUpper) ret = %u: ", ret); 196 | good = true; 197 | for (int i = 0; i < sizeof(allBytes); i++) 198 | { 199 | if (i != allBytes[i]) 200 | { 201 | good = false; 202 | } 203 | } 204 | if (ret != 0 || !good) 205 | { 206 | hasErrors = true; 207 | } 208 | printf("%s\n", (good ? "good" : "bad")); 209 | 210 | for (int i = 0; i < sizeof(allBytes); i++) 211 | { 212 | allBytes[i] = 0; 213 | } 214 | ret = hexDecodeLower(allBytes, allBytesHex, sizeof(allBytesHex) - 1); 215 | printf("hexDecodeLower(allBytesHexLower) ret = %u: ", ret); 216 | good = true; 217 | for (int i = 0; i < sizeof(allBytes); i++) 218 | { 219 | if (i != allBytes[i]) 220 | { 221 | good = false; 222 | } 223 | } 224 | if (ret != 0 || !good) 225 | { 226 | hasErrors = true; 227 | } 228 | printf("%s\n", (good ? "good" : "bad")); 229 | 230 | for (int i = 0; i < sizeof(allBytes); i++) 231 | { 232 | allBytes[i] = 0; 233 | } 234 | ret = hexDecodeUpper(allBytes, allBytesHexUpper, sizeof(allBytesHexUpper) - 1); 235 | printf("hexDecodeUpper(allBytesHexUpper) ret = %u: ", ret); 236 | good = true; 237 | for (int i = 0; i < sizeof(allBytes); i++) 238 | { 239 | if (i != allBytes[i]) 240 | { 241 | good = false; 242 | } 243 | } 244 | if (ret != 0 || !good) 245 | { 246 | hasErrors = true; 247 | } 248 | printf("%s\n", (good ? "good" : "bad")); 249 | 250 | printf("\nShould error:\n"); 251 | ret = hexDecodeLower(allBytes, allBytesHexUpper, sizeof(allBytesHexUpper) - 1); 252 | printf("hexDecodeLower(allBytesHexUpper) ret = %u\n", ret, (ret != 0 ? "good" : "bad")); 253 | if (ret == 0) 254 | { 255 | hasErrors = true; 256 | } 257 | ret = hexDecodeUpper(allBytes, allBytesHex, sizeof(allBytesHex) - 1); 258 | printf("hexDecodeUpper(allBytesHexLower) ret = %u\n", ret, (ret != 0 ? "good" : "bad")); 259 | if (ret == 0) 260 | { 261 | hasErrors = true; 262 | } 263 | 264 | if (hasErrors) 265 | { 266 | printf("*** FAILED ***\n"); 267 | } 268 | else 269 | { 270 | printf("*** PASSED ***\n"); 271 | } 272 | return hasErrors; 273 | } 274 | 275 | int main() 276 | { 277 | bool hasErrors; 278 | 279 | printf("*** Base64 ***\n"); 280 | hasErrors = testBase64() != 0; 281 | 282 | printf("\n*** Hex ***\n"); 283 | hasErrors = testHex() != 0 || hasErrors; 284 | 285 | if (hasErrors) 286 | { 287 | printf("\n***** FAILED *****\n"); 288 | } 289 | else 290 | { 291 | printf("\n***** ALL GOOD *****\n"); 292 | } 293 | return 0; 294 | } 295 | -------------------------------------------------------------------------------- /base64.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #include "base64.h" 24 | #include 25 | 26 | // ************************ 27 | // *** Helper Functions *** 28 | // ************************ 29 | 30 | // Base64 character set: 31 | // [A-Z] [a-z] [0-9] + / 32 | // 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f 33 | 34 | inline int base64Decode6Bits(char src) 35 | { 36 | int ch = (unsigned char) src; 37 | int ret = -1; 38 | 39 | // if (ch > 0x40 && ch < 0x5b) ret += ch - 0x41 + 1; // -64 40 | ret += (((0x40 - ch) & (ch - 0x5b)) >> 8) & (ch - 64); 41 | 42 | // if (ch > 0x60 && ch < 0x7b) ret += ch - 0x61 + 26 + 1; // -70 43 | ret += (((0x60 - ch) & (ch - 0x7b)) >> 8) & (ch - 70); 44 | 45 | // if (ch > 0x2f && ch < 0x3a) ret += ch - 0x30 + 52 + 1; // 5 46 | ret += (((0x2f - ch) & (ch - 0x3a)) >> 8) & (ch + 5); 47 | 48 | // if (ch == 0x2b) ret += 62 + 1; 49 | ret += (((0x2a - ch) & (ch - 0x2c)) >> 8) & 63; 50 | 51 | // if (ch == 0x2f) ret += 63 + 1; 52 | ret += (((0x2e - ch) & (ch - 0x30)) >> 8) & 64; 53 | 54 | return ret; 55 | } 56 | 57 | inline int base64Decode3Bytes(uint8_t dest[3], const char src[4]) 58 | { 59 | int c0 = base64Decode6Bits(src[0]); 60 | int c1 = base64Decode6Bits(src[1]); 61 | int c2 = base64Decode6Bits(src[2]); 62 | int c3 = base64Decode6Bits(src[3]); 63 | 64 | dest[0] = (uint8_t) ((c0 << 2) | (c1 >> 4)); 65 | dest[1] = (uint8_t) ((c1 << 4) | (c2 >> 2)); 66 | dest[2] = (uint8_t) ((c2 << 6) | c3 ); 67 | return ((c0 | c1 | c2 | c3) >> 8) & 1; 68 | } 69 | 70 | inline char base64Encode6Bits(unsigned int src) 71 | { 72 | int diff = 0x41; 73 | 74 | // if (in > 25) diff += 0x61 - 0x41 - 26; // 6 75 | diff += ((25 - src) >> 8) & 6; 76 | 77 | // if (in > 51) diff += 0x30 - 0x61 - 26; // -75 78 | diff -= ((51 - src) >> 8) & 75; 79 | 80 | // if (in > 61) diff += 0x2b - 0x30 - 10; // -15 81 | diff -= ((61 - src) >> 8) & 15; 82 | 83 | // if (in > 62) diff += 0x2f - 0x2b - 1; // 3 84 | diff += ((62 - src) >> 8) & 3; 85 | 86 | return (char) (src + diff); 87 | } 88 | 89 | inline void base64Encode3Bytes(char dest[4], const uint8_t src[3]) 90 | { 91 | unsigned int b0 = src[0]; 92 | unsigned int b1 = src[1]; 93 | unsigned int b2 = src[2]; 94 | 95 | dest[0] = base64Encode6Bits( b0 >> 2 ); 96 | dest[1] = base64Encode6Bits(((b0 << 4) | (b1 >> 4)) & 63); 97 | dest[2] = base64Encode6Bits(((b1 << 2) | (b2 >> 6)) & 63); 98 | dest[3] = base64Encode6Bits( b2 & 63); 99 | } 100 | 101 | 102 | // Base64 character set: 103 | // ./ [A-Z] [a-z] [0-9] 104 | // 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39 105 | 106 | inline int base64Decode6BitsDotSlash(char src) 107 | { 108 | int ch = (unsigned char) src; 109 | int ret = -1; 110 | 111 | // if (ch > 0x2d && ch < 0x30) ret += ch - 0x2e + 1; // -45 112 | ret += (((0x2d - ch) & (ch - 0x30)) >> 8) & (ch - 45); 113 | 114 | // if (ch > 0x40 && ch < 0x5b) ret += ch - 0x41 + 2 + 1; // -62 115 | ret += (((0x40 - ch) & (ch - 0x5b)) >> 8) & (ch - 62); 116 | 117 | // if (ch > 0x60 && ch < 0x7b) ret += ch - 0x61 + 28 + 1; // -68 118 | ret += (((0x60 - ch) & (ch - 0x7b)) >> 8) & (ch - 68); 119 | 120 | // if (ch > 0x2f && ch < 0x3a) ret += ch - 0x30 + 54 + 1; // 7 121 | ret += (((0x2f - ch) & (ch - 0x3a)) >> 8) & (ch + 7); 122 | 123 | return ret; 124 | } 125 | 126 | inline int base64Decode3BytesDotSlash(uint8_t dest[3], const char src[4]) 127 | { 128 | int c0 = base64Decode6BitsDotSlash(src[0]); 129 | int c1 = base64Decode6BitsDotSlash(src[1]); 130 | int c2 = base64Decode6BitsDotSlash(src[2]); 131 | int c3 = base64Decode6BitsDotSlash(src[3]); 132 | 133 | dest[0] = (uint8_t) ((c0 << 2) | (c1 >> 4)); 134 | dest[1] = (uint8_t) ((c1 << 4) | (c2 >> 2)); 135 | dest[2] = (uint8_t) ((c2 << 6) | c3 ); 136 | return ((c0 | c1 | c2 | c3) >> 8) & 1; 137 | } 138 | 139 | inline char base64Encode6BitsDotSlash(unsigned int src) 140 | { 141 | src += 0x2e; 142 | 143 | // if (in > 0x2f) in += 0x41 - 0x30; // 17 144 | src += ((0x2f - src) >> 8) & 17; 145 | 146 | // if (in > 0x5a) in += 0x61 - 0x5b; // 6 147 | src += ((0x5a - src) >> 8) & 6; 148 | 149 | // if (in > 0x7a) in += 0x30 - 0x7b; // -75 150 | src -= ((0x7a - src) >> 8) & 75; 151 | 152 | return (char) src; 153 | } 154 | 155 | inline void base64Encode3BytesDotSlash(char dest[4], const uint8_t src[3]) 156 | { 157 | unsigned int b0 = src[0]; 158 | unsigned int b1 = src[1]; 159 | unsigned int b2 = src[2]; 160 | 161 | dest[0] = base64Encode6BitsDotSlash( b0 >> 2 ); 162 | dest[1] = base64Encode6BitsDotSlash(((b0 << 4) | (b1 >> 4)) & 63); 163 | dest[2] = base64Encode6BitsDotSlash(((b1 << 2) | (b2 >> 6)) & 63); 164 | dest[3] = base64Encode6BitsDotSlash( b2 & 63); 165 | } 166 | 167 | 168 | // Base64 character set: 169 | // [.-9] [A-Z] [a-z] 170 | // 0x2e-0x39, 0x41-0x5a, 0x61-0x7a 171 | 172 | inline int base64Decode6BitsDotSlashOrdered(char src) 173 | { 174 | int ch = (unsigned char) src; 175 | int ret = -1; 176 | 177 | // if (ch > 0x2d && ch < 0x3a) ret += ch - 0x2e + 1; // -45 178 | ret += (((0x2d - ch) & (ch - 0x3a)) >> 8) & (ch - 45); 179 | 180 | // if (ch > 0x40 && ch < 0x5b) ret += ch - 0x41 + 12 + 1; // -52 181 | ret += (((0x40 - ch) & (ch - 0x5b)) >> 8) & (ch - 52); 182 | 183 | // if (ch > 0x60 && ch < 0x7b) ret += ch - 0x61 + 38 + 1; // -58 184 | ret += (((0x60 - ch) & (ch - 0x7b)) >> 8) & (ch - 58); 185 | 186 | return ret; 187 | } 188 | 189 | inline int base64Decode3BytesDotSlashOrdered(uint8_t dest[3], const char src[4]) 190 | { 191 | int c0 = base64Decode6BitsDotSlashOrdered(src[0]); 192 | int c1 = base64Decode6BitsDotSlashOrdered(src[1]); 193 | int c2 = base64Decode6BitsDotSlashOrdered(src[2]); 194 | int c3 = base64Decode6BitsDotSlashOrdered(src[3]); 195 | 196 | dest[0] = (uint8_t) ((c0 << 2) | (c1 >> 4)); 197 | dest[1] = (uint8_t) ((c1 << 4) | (c2 >> 2)); 198 | dest[2] = (uint8_t) ((c2 << 6) | c3 ); 199 | return ((c0 | c1 | c2 | c3) >> 8) & 1; 200 | } 201 | 202 | inline char base64Encode6BitsDotSlashOrdered(unsigned int src) 203 | { 204 | src += 0x2e; 205 | 206 | // if (in > 0x39) in += 0x41 - 0x3a; // 7 207 | src += ((0x39 - src) >> 8) & 7; 208 | 209 | // if (in > 0x5a) in += 0x61 - 0x5b; // 6 210 | src += ((0x5a - src) >> 8) & 6; 211 | 212 | return (char) src; 213 | } 214 | 215 | inline void base64Encode3BytesDotSlashOrdered(char dest[4], const uint8_t src[3]) 216 | { 217 | unsigned int b0 = src[0]; 218 | unsigned int b1 = src[1]; 219 | unsigned int b2 = src[2]; 220 | 221 | dest[0] = base64Encode6BitsDotSlashOrdered( b0 >> 2 ); 222 | dest[1] = base64Encode6BitsDotSlashOrdered(((b0 << 4) | (b1 >> 4)) & 63); 223 | dest[2] = base64Encode6BitsDotSlashOrdered(((b1 << 2) | (b2 >> 6)) & 63); 224 | dest[3] = base64Encode6BitsDotSlashOrdered( b2 & 63); 225 | } 226 | 227 | 228 | // ********************** 229 | // *** Main Functions *** 230 | // ********************** 231 | 232 | // Base64 character set "[A-Z][a-z][0-9]+/" 233 | void base64Encode(char *dest, const void *src, size_t srcLen) 234 | { 235 | for (; srcLen >= 3; srcLen -= 3) 236 | { 237 | base64Encode3Bytes(dest, (const uint8_t*) src); 238 | dest += 4; 239 | src = (const uint8_t*) src + 3; 240 | } 241 | if (srcLen > 0) 242 | { 243 | uint8_t tmp[3] = {0, 0, 0}; 244 | 245 | for (size_t i = 0; i < srcLen; i++) 246 | { 247 | tmp[i] = ((const uint8_t*) src)[i]; 248 | } 249 | base64Encode3Bytes(dest, tmp); 250 | dest[3] = '='; 251 | if (srcLen == 1) 252 | { 253 | dest[2] = '='; 254 | } 255 | dest += 4; 256 | } 257 | *dest = 0; 258 | } 259 | 260 | int base64Decode(void *dest, const char *src, size_t srcLen) 261 | { 262 | int err = 0; 263 | 264 | for (; srcLen > 4; srcLen -= 4) 265 | { 266 | err |= base64Decode3Bytes((uint8_t*) dest, src); 267 | dest = (uint8_t*) dest + 3; 268 | src += 4; 269 | } 270 | if (srcLen > 0) 271 | { 272 | size_t i; 273 | uint8_t tmpOut[3]; 274 | char tmpIn[4] = {'A', 'A', 'A', 'A'}; 275 | 276 | for (i = 0; i < srcLen && src[i] != '='; i++) 277 | { 278 | tmpIn[i] = src[i]; 279 | } 280 | if (i < 2) 281 | { 282 | err = 1; 283 | } 284 | srcLen = i - 1; 285 | err |= base64Decode3Bytes(tmpOut, tmpIn); 286 | for (i = 0; i < srcLen; i++) 287 | { 288 | ((uint8_t*) dest)[i] = tmpOut[i]; 289 | } 290 | } 291 | return err; 292 | } 293 | 294 | // Base64 character set "./[A-Z][a-z][0-9]" 295 | void base64EncodeDotSlash(char *dest, const void *src, size_t srcLen) 296 | { 297 | for (; srcLen >= 3; srcLen -= 3) 298 | { 299 | base64Encode3BytesDotSlash(dest, (const uint8_t*) src); 300 | dest += 4; 301 | src = (const uint8_t*) src + 3; 302 | } 303 | if (srcLen > 0) 304 | { 305 | uint8_t tmp[3] = {0, 0, 0}; 306 | 307 | for (size_t i = 0; i < srcLen; i++) 308 | { 309 | tmp[i] = ((const uint8_t*) src)[i]; 310 | } 311 | base64Encode3BytesDotSlash(dest, tmp); 312 | dest[3] = '='; 313 | if (srcLen == 1) 314 | { 315 | dest[2] = '='; 316 | } 317 | dest += 4; 318 | } 319 | *dest = 0; 320 | } 321 | 322 | int base64DecodeDotSlash(void *dest, const char *src, size_t srcLen) 323 | { 324 | int err = 0; 325 | 326 | for (; srcLen > 4; srcLen -= 4) 327 | { 328 | err |= base64Decode3BytesDotSlash((uint8_t*) dest, src); 329 | dest = (uint8_t*) dest + 3; 330 | src += 4; 331 | } 332 | if (srcLen > 0) 333 | { 334 | size_t i; 335 | uint8_t tmpOut[3]; 336 | char tmpIn[4] = {'A', 'A', 'A', 'A'}; 337 | 338 | for (i = 0; i < srcLen && src[i] != '='; i++) 339 | { 340 | tmpIn[i] = src[i]; 341 | } 342 | if (i < 2) 343 | { 344 | err = 1; 345 | } 346 | srcLen = i - 1; 347 | err |= base64Decode3BytesDotSlash(tmpOut, tmpIn); 348 | for (i = 0; i < srcLen; i++) 349 | { 350 | ((uint8_t*) dest)[i] = tmpOut[i]; 351 | } 352 | } 353 | return err; 354 | } 355 | 356 | // Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]" 357 | void base64EncodeDotSlashOrdered(char *dest, const void *src, size_t srcLen) 358 | { 359 | for (; srcLen >= 3; srcLen -= 3) 360 | { 361 | base64Encode3BytesDotSlashOrdered(dest, (const uint8_t*) src); 362 | dest += 4; 363 | src = (const uint8_t*) src + 3; 364 | } 365 | if (srcLen > 0) 366 | { 367 | uint8_t tmp[3] = {0, 0, 0}; 368 | 369 | for (size_t i = 0; i < srcLen; i++) 370 | { 371 | tmp[i] = ((const uint8_t*) src)[i]; 372 | } 373 | base64Encode3BytesDotSlashOrdered(dest, tmp); 374 | dest[3] = '='; 375 | if (srcLen == 1) 376 | { 377 | dest[2] = '='; 378 | } 379 | dest += 4; 380 | } 381 | *dest = 0; 382 | } 383 | 384 | int base64DecodeDotSlashOrdered(void *dest, const char *src, size_t srcLen) 385 | { 386 | int err = 0; 387 | 388 | for (; srcLen > 4; srcLen -= 4) 389 | { 390 | err |= base64Decode3BytesDotSlashOrdered((uint8_t*) dest, src); 391 | dest = (uint8_t*) dest + 3; 392 | src += 4; 393 | } 394 | if (srcLen > 0) 395 | { 396 | size_t i; 397 | uint8_t tmpOut[3]; 398 | char tmpIn[4] = {'A', 'A', 'A', 'A'}; 399 | 400 | for (i = 0; i < srcLen && src[i] != '='; i++) 401 | { 402 | tmpIn[i] = src[i]; 403 | } 404 | if (i < 2) 405 | { 406 | err = 1; 407 | } 408 | srcLen = i - 1; 409 | err |= base64Decode3BytesDotSlashOrdered(tmpOut, tmpIn); 410 | for (i = 0; i < srcLen; i++) 411 | { 412 | ((uint8_t*) dest)[i] = tmpOut[i]; 413 | } 414 | } 415 | return err; 416 | } 417 | -------------------------------------------------------------------------------- /php/base64.php: -------------------------------------------------------------------------------- 1 | 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 38 | $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); 39 | 40 | // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 41 | $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); 42 | 43 | // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 44 | $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); 45 | 46 | // if ($src == 0x2b) $ret += 62 + 1; 47 | $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; 48 | 49 | // if ($src == 0x2f) ret += 63 + 1; 50 | $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; 51 | 52 | return $ret; 53 | } 54 | 55 | function base64Encode6Bits($src) 56 | { 57 | $diff = 0x41; 58 | 59 | // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 60 | $diff += ((25 - $src) >> 8) & 6; 61 | 62 | // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 63 | $diff -= ((51 - $src) >> 8) & 75; 64 | 65 | // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 66 | $diff -= ((61 - $src) >> 8) & 15; 67 | 68 | // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 69 | $diff += ((62 - $src) >> 8) & 3; 70 | 71 | return chr($src + $diff); 72 | } 73 | 74 | 75 | // Base64 character set: 76 | // ./ [A-Z] [a-z] [0-9] 77 | // 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39 78 | 79 | function base64Decode6BitsDotSlash($src) 80 | { 81 | $ret = -1; 82 | 83 | // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45 84 | $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45); 85 | 86 | // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62 87 | $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62); 88 | 89 | // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68 90 | $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68); 91 | 92 | // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7 93 | $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7); 94 | 95 | return $ret; 96 | } 97 | 98 | function base64Encode6BitsDotSlash($src) 99 | { 100 | $src += 0x2e; 101 | 102 | // if ($src > 0x2f) $src += 0x41 - 0x30; // 17 103 | $src += ((0x2f - $src) >> 8) & 17; 104 | 105 | // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 106 | $src += ((0x5a - $src) >> 8) & 6; 107 | 108 | // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75 109 | $src -= ((0x7a - $src) >> 8) & 75; 110 | 111 | return chr($src); 112 | } 113 | 114 | 115 | // Base64 character set: 116 | // [.-9] [A-Z] [a-z] 117 | // 0x2e-0x39, 0x41-0x5a, 0x61-0x7a 118 | 119 | function base64Decode6BitsDotSlashOrdered($src) 120 | { 121 | $ret = -1; 122 | 123 | // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45 124 | $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45); 125 | 126 | // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52 127 | $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52); 128 | 129 | // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58 130 | $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58); 131 | 132 | return $ret; 133 | } 134 | 135 | function base64Encode6BitsDotSlashOrdered($src) 136 | { 137 | $src += 0x2e; 138 | 139 | // if ($src > 0x39) $src += 0x41 - 0x3a; // 7 140 | $src += ((0x39 - $src) >> 8) & 7; 141 | 142 | // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 143 | $src += ((0x5a - $src) >> 8) & 6; 144 | 145 | return chr($src); 146 | } 147 | 148 | 149 | // ********************** 150 | // *** Main Functions *** 151 | // ********************** 152 | 153 | // Base64 character set "[A-Z][a-z][0-9]+/" 154 | function base64Encode($src) 155 | { 156 | $dest = ''; 157 | $srcLen = strlen($src); 158 | for ($i = 0; $i + 3 <= $srcLen; $i += 3) 159 | { 160 | $b0 = ord($src[$i]); 161 | $b1 = ord($src[$i + 1]); 162 | $b2 = ord($src[$i + 2]); 163 | 164 | $dest .= 165 | base64Encode6Bits( $b0 >> 2 ) . 166 | base64Encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . 167 | base64Encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . 168 | base64Encode6Bits( $b2 & 63); 169 | } 170 | if ($i < $srcLen) 171 | { 172 | $b0 = ord($src[$i]); 173 | if ($i + 1 < $srcLen) 174 | { 175 | $b1 = ord($src[$i + 1]); 176 | $dest .= 177 | base64Encode6Bits( $b0 >> 2 ) . 178 | base64Encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . 179 | base64Encode6Bits( ($b1 << 2) & 63) . '='; 180 | } 181 | else 182 | { 183 | $dest .= 184 | base64Encode6Bits( $b0 >> 2) . 185 | base64Encode6Bits(($b0 << 4) & 63) . '=='; 186 | } 187 | } 188 | return $dest; 189 | } 190 | 191 | function base64Decode($src) 192 | { 193 | // Remove padding 194 | $srcLen = strlen($src); 195 | if ($srcLen == 0) 196 | { 197 | return ''; 198 | } 199 | if (($srcLen & 3) == 0) 200 | { 201 | if ($src[$srcLen - 1] == '=') 202 | { 203 | $srcLen--; 204 | if ($src[$srcLen - 1] == '=') 205 | { 206 | $srcLen--; 207 | } 208 | } 209 | } 210 | if (($srcLen & 3) == 1) 211 | { 212 | return false; 213 | } 214 | 215 | $err = 0; 216 | $dest = ''; 217 | for ($i = 0; $i + 4 <= $srcLen; $i += 4) 218 | { 219 | $c0 = base64Decode6Bits(ord($src[$i])); 220 | $c1 = base64Decode6Bits(ord($src[$i + 1])); 221 | $c2 = base64Decode6Bits(ord($src[$i + 2])); 222 | $c3 = base64Decode6Bits(ord($src[$i + 3])); 223 | 224 | $dest .= 225 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 226 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 227 | chr((($c2 << 6) | $c3 ) & 0xff); 228 | $err |= ($c0 | $c1 | $c2 | $c3) >> 8; 229 | } 230 | if ($i < $srcLen) 231 | { 232 | $c0 = base64Decode6Bits(ord($src[$i])); 233 | $c1 = base64Decode6Bits(ord($src[$i + 1])); 234 | if ($i + 2 < $srcLen) 235 | { 236 | $c2 = base64Decode6Bits(ord($src[$i + 2])); 237 | $dest .= 238 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 239 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 240 | chr( ($c2 << 6) & 0xff); 241 | $err |= ($c0 | $c1 | $c2) >> 8; 242 | } 243 | else 244 | { 245 | $dest .= 246 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 247 | chr( ($c1 << 4) & 0xff); 248 | $err |= ($c0 | $c1) >> 8; 249 | } 250 | } 251 | if ($err != 0) 252 | { 253 | return false; 254 | } 255 | return $dest; 256 | } 257 | 258 | // Base64 character set "./[A-Z][a-z][0-9]" 259 | function base64EncodeDotSlash($src) 260 | { 261 | $dest = ''; 262 | $srcLen = strlen($src); 263 | for ($i = 0; $i + 3 <= $srcLen; $i += 3) 264 | { 265 | $b0 = ord($src[$i]); 266 | $b1 = ord($src[$i + 1]); 267 | $b2 = ord($src[$i + 2]); 268 | 269 | $dest .= 270 | base64Encode6BitsDotSlash( $b0 >> 2 ) . 271 | base64Encode6BitsDotSlash((($b0 << 4) | ($b1 >> 4)) & 63) . 272 | base64Encode6BitsDotSlash((($b1 << 2) | ($b2 >> 6)) & 63) . 273 | base64Encode6BitsDotSlash( $b2 & 63); 274 | } 275 | if ($i < $srcLen) 276 | { 277 | $b0 = ord($src[$i]); 278 | if ($i + 1 < $srcLen) 279 | { 280 | $b1 = ord($src[$i + 1]); 281 | $dest .= 282 | base64Encode6BitsDotSlash( $b0 >> 2 ) . 283 | base64Encode6BitsDotSlash((($b0 << 4) | ($b1 >> 4)) & 63) . 284 | base64Encode6BitsDotSlash( ($b1 << 2) & 63) . '='; 285 | } 286 | else 287 | { 288 | $dest .= 289 | base64Encode6BitsDotSlash( $b0 >> 2) . 290 | base64Encode6BitsDotSlash(($b0 << 4) & 63) . '=='; 291 | } 292 | } 293 | return $dest; 294 | } 295 | 296 | function base64DecodeDotSlash($src) 297 | { 298 | // Remove padding 299 | $srcLen = strlen($src); 300 | if ($srcLen == 0) 301 | { 302 | return ''; 303 | } 304 | if (($srcLen & 3) == 0) 305 | { 306 | if ($src[$srcLen - 1] == '=') 307 | { 308 | $srcLen--; 309 | if ($src[$srcLen - 1] == '=') 310 | { 311 | $srcLen--; 312 | } 313 | } 314 | } 315 | if (($srcLen & 3) == 1) 316 | { 317 | return false; 318 | } 319 | 320 | $err = 0; 321 | $dest = ''; 322 | for ($i = 0; $i + 4 <= $srcLen; $i += 4) 323 | { 324 | $c0 = base64Decode6BitsDotSlash(ord($src[$i])); 325 | $c1 = base64Decode6BitsDotSlash(ord($src[$i + 1])); 326 | $c2 = base64Decode6BitsDotSlash(ord($src[$i + 2])); 327 | $c3 = base64Decode6BitsDotSlash(ord($src[$i + 3])); 328 | 329 | $dest .= 330 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 331 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 332 | chr((($c2 << 6) | $c3 ) & 0xff); 333 | $err |= ($c0 | $c1 | $c2 | $c3) >> 8; 334 | } 335 | if ($i < $srcLen) 336 | { 337 | $c0 = base64Decode6BitsDotSlash(ord($src[$i])); 338 | $c1 = base64Decode6BitsDotSlash(ord($src[$i + 1])); 339 | if ($i + 2 < $srcLen) 340 | { 341 | $c2 = base64Decode6BitsDotSlash(ord($src[$i + 2])); 342 | $dest .= 343 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 344 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 345 | chr( ($c2 << 6) & 0xff); 346 | $err |= ($c0 | $c1 | $c2) >> 8; 347 | } 348 | else 349 | { 350 | $dest .= 351 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 352 | chr( ($c1 << 4) & 0xff); 353 | $err |= ($c0 | $c1) >> 8; 354 | } 355 | } 356 | if ($err != 0) 357 | { 358 | return false; 359 | } 360 | return $dest; 361 | } 362 | 363 | // Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]" 364 | function base64EncodeDotSlashOrdered($src) 365 | { 366 | $dest = ''; 367 | $srcLen = strlen($src); 368 | for ($i = 0; $i + 3 <= $srcLen; $i += 3) 369 | { 370 | $b0 = ord($src[$i]); 371 | $b1 = ord($src[$i + 1]); 372 | $b2 = ord($src[$i + 2]); 373 | 374 | $dest .= 375 | base64Encode6BitsDotSlashOrdered( $b0 >> 2 ) . 376 | base64Encode6BitsDotSlashOrdered((($b0 << 4) | ($b1 >> 4)) & 63) . 377 | base64Encode6BitsDotSlashOrdered((($b1 << 2) | ($b2 >> 6)) & 63) . 378 | base64Encode6BitsDotSlashOrdered( $b2 & 63); 379 | } 380 | if ($i < $srcLen) 381 | { 382 | $b0 = ord($src[$i]); 383 | if ($i + 1 < $srcLen) 384 | { 385 | $b1 = ord($src[$i + 1]); 386 | $dest .= 387 | base64Encode6BitsDotSlashOrdered( $b0 >> 2 ) . 388 | base64Encode6BitsDotSlashOrdered((($b0 << 4) | ($b1 >> 4)) & 63) . 389 | base64Encode6BitsDotSlashOrdered( ($b1 << 2) & 63) . '='; 390 | } 391 | else 392 | { 393 | $dest .= 394 | base64Encode6BitsDotSlashOrdered( $b0 >> 2) . 395 | base64Encode6BitsDotSlashOrdered(($b0 << 4) & 63) . '=='; 396 | } 397 | } 398 | return $dest; 399 | } 400 | 401 | function base64DecodeDotSlashOrdered($src) 402 | { 403 | // Remove padding 404 | $srcLen = strlen($src); 405 | if ($srcLen == 0) 406 | { 407 | return ''; 408 | } 409 | if (($srcLen & 3) == 0) 410 | { 411 | if ($src[$srcLen - 1] == '=') 412 | { 413 | $srcLen--; 414 | if ($src[$srcLen - 1] == '=') 415 | { 416 | $srcLen--; 417 | } 418 | } 419 | } 420 | if (($srcLen & 3) == 1) 421 | { 422 | return false; 423 | } 424 | 425 | $err = 0; 426 | $dest = ''; 427 | for ($i = 0; $i + 4 <= $srcLen; $i += 4) 428 | { 429 | $c0 = base64Decode6BitsDotSlashOrdered(ord($src[$i])); 430 | $c1 = base64Decode6BitsDotSlashOrdered(ord($src[$i + 1])); 431 | $c2 = base64Decode6BitsDotSlashOrdered(ord($src[$i + 2])); 432 | $c3 = base64Decode6BitsDotSlashOrdered(ord($src[$i + 3])); 433 | 434 | $dest .= 435 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 436 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 437 | chr((($c2 << 6) | $c3 ) & 0xff); 438 | $err |= ($c0 | $c1 | $c2 | $c3) >> 8; 439 | } 440 | if ($i < $srcLen) 441 | { 442 | $c0 = base64Decode6BitsDotSlashOrdered(ord($src[$i])); 443 | $c1 = base64Decode6BitsDotSlashOrdered(ord($src[$i + 1])); 444 | if ($i + 2 < $srcLen) 445 | { 446 | $c2 = base64Decode6BitsDotSlashOrdered(ord($src[$i + 2])); 447 | $dest .= 448 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 449 | chr((($c1 << 4) | ($c2 >> 2)) & 0xff) . 450 | chr( ($c2 << 6) & 0xff); 451 | $err |= ($c0 | $c1 | $c2) >> 8; 452 | } 453 | else 454 | { 455 | $dest .= 456 | chr((($c0 << 2) | ($c1 >> 4)) & 0xff) . 457 | chr( ($c1 << 4) & 0xff); 458 | $err |= ($c0 | $c1) >> 8; 459 | } 460 | } 461 | if ($err != 0) 462 | { 463 | return false; 464 | } 465 | return $dest; 466 | } 467 | --------------------------------------------------------------------------------