LCOV - code coverage report
Current view: top level - libs/capy/src/bcrypt - base64.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 92.8 % 69 64
Test Date: 2025-12-30 20:31:35 Functions: 100.0 % 2 2

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3              : //
       4              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // Official repository: https://github.com/cppalliance/capy
       8              : //
       9              : 
      10              : #include "base64.hpp"
      11              : 
      12              : namespace boost {
      13              : namespace capy {
      14              : namespace bcrypt {
      15              : namespace detail {
      16              : 
      17              : namespace {
      18              : 
      19              : // bcrypt's non-standard base64 alphabet
      20              : constexpr char encode_table[] =
      21              :     "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      22              : 
      23              : // Decode table: maps ASCII char to 6-bit value, or 0xFF for invalid
      24              : constexpr std::uint8_t decode_table[256] = {
      25              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 0-7
      26              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 8-15
      27              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 16-23
      28              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 24-31
      29              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 32-39
      30              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,  // 40-47  (. /)
      31              :     0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,  // 48-55  (0-7)
      32              :     0x3E, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 56-63  (8-9)
      33              :     0xFF, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,  // 64-71  (A-G)
      34              :     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,  // 72-79  (H-O)
      35              :     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,  // 80-87  (P-W)
      36              :     0x19, 0x1A, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 88-95  (X-Z)
      37              :     0xFF, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,  // 96-103 (a-g)
      38              :     0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,  // 104-111 (h-o)
      39              :     0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,  // 112-119 (p-w)
      40              :     0x33, 0x34, 0x35, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 120-127 (x-z)
      41              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      42              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      43              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      44              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      45              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      46              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      47              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      48              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      49              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      50              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      51              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      52              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      53              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      54              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      55              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      56              :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      57              : };
      58              : 
      59              : } // namespace
      60              : 
      61              : std::size_t
      62           31 : base64_encode(
      63              :     char* dest,
      64              :     std::uint8_t const* src,
      65              :     std::size_t n)
      66              : {
      67           31 :     char* out = dest;
      68              : 
      69          210 :     while (n >= 3)
      70              :     {
      71          179 :         std::uint32_t v =
      72          179 :             (static_cast<std::uint32_t>(src[0]) << 16) |
      73          179 :             (static_cast<std::uint32_t>(src[1]) << 8) |
      74          179 :             static_cast<std::uint32_t>(src[2]);
      75              : 
      76          179 :         *out++ = encode_table[(v >> 18) & 0x3F];
      77          179 :         *out++ = encode_table[(v >> 12) & 0x3F];
      78          179 :         *out++ = encode_table[(v >> 6) & 0x3F];
      79          179 :         *out++ = encode_table[v & 0x3F];
      80              : 
      81          179 :         src += 3;
      82          179 :         n -= 3;
      83              :     }
      84              : 
      85           31 :     if (n == 2)
      86              :     {
      87           12 :         std::uint32_t v =
      88           12 :             (static_cast<std::uint32_t>(src[0]) << 16) |
      89           12 :             (static_cast<std::uint32_t>(src[1]) << 8);
      90              : 
      91           12 :         *out++ = encode_table[(v >> 18) & 0x3F];
      92           12 :         *out++ = encode_table[(v >> 12) & 0x3F];
      93           12 :         *out++ = encode_table[(v >> 6) & 0x3F];
      94              :     }
      95           19 :     else if (n == 1)
      96              :     {
      97           19 :         std::uint32_t v =
      98           19 :             static_cast<std::uint32_t>(src[0]) << 16;
      99              : 
     100           19 :         *out++ = encode_table[(v >> 18) & 0x3F];
     101           19 :         *out++ = encode_table[(v >> 12) & 0x3F];
     102              :     }
     103              : 
     104           31 :     return static_cast<std::size_t>(out - dest);
     105              : }
     106              : 
     107              : int
     108           17 : base64_decode(
     109              :     std::uint8_t* dest,
     110              :     char const* src,
     111              :     std::size_t n)
     112              : {
     113           17 :     std::uint8_t* out = dest;
     114           17 :     std::size_t i = 0;
     115              : 
     116          114 :     while (i + 4 <= n)
     117              :     {
     118           97 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     119           97 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     120           97 :         std::uint8_t c = decode_table[static_cast<unsigned char>(src[i + 2])];
     121           97 :         std::uint8_t d = decode_table[static_cast<unsigned char>(src[i + 3])];
     122              : 
     123           97 :         if ((a | b | c | d) & 0x80)
     124            0 :             return -1;
     125              : 
     126           97 :         std::uint32_t v =
     127           97 :             (static_cast<std::uint32_t>(a) << 18) |
     128           97 :             (static_cast<std::uint32_t>(b) << 12) |
     129           97 :             (static_cast<std::uint32_t>(c) << 6) |
     130           97 :             static_cast<std::uint32_t>(d);
     131              : 
     132           97 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     133           97 :         *out++ = static_cast<std::uint8_t>(v >> 8);
     134           97 :         *out++ = static_cast<std::uint8_t>(v);
     135              : 
     136           97 :         i += 4;
     137              :     }
     138              : 
     139              :     // Handle remaining 2 or 3 characters
     140           17 :     if (i + 3 == n)
     141              :     {
     142            6 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     143            6 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     144            6 :         std::uint8_t c = decode_table[static_cast<unsigned char>(src[i + 2])];
     145              : 
     146            6 :         if ((a | b | c) & 0x80)
     147            0 :             return -1;
     148              : 
     149            6 :         std::uint32_t v =
     150            6 :             (static_cast<std::uint32_t>(a) << 18) |
     151            6 :             (static_cast<std::uint32_t>(b) << 12) |
     152            6 :             (static_cast<std::uint32_t>(c) << 6);
     153              : 
     154            6 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     155            6 :         *out++ = static_cast<std::uint8_t>(v >> 8);
     156              :     }
     157           11 :     else if (i + 2 == n)
     158              :     {
     159           11 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     160           11 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     161              : 
     162           11 :         if ((a | b) & 0x80)
     163            0 :             return -1;
     164              : 
     165           11 :         std::uint32_t v =
     166           11 :             (static_cast<std::uint32_t>(a) << 18) |
     167           11 :             (static_cast<std::uint32_t>(b) << 12);
     168              : 
     169           11 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     170              :     }
     171            0 :     else if (i + 1 == n)
     172              :     {
     173              :         // Single trailing character is invalid
     174            0 :         return -1;
     175              :     }
     176              : 
     177           17 :     return static_cast<int>(out - dest);
     178              : }
     179              : 
     180              : } // detail
     181              : } // bcrypt
     182              : } // capy
     183              : } // boost
     184              : 
        

Generated by: LCOV version 2.1