Base.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "Base.h"
  4. namespace i2p
  5. {
  6. namespace data
  7. {
  8. static const char T32[32] = {
  9. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  10. 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
  11. 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
  12. 'y', 'z', '2', '3', '4', '5', '6', '7',
  13. };
  14. const char * GetBase32SubstitutionTable ()
  15. {
  16. return T32;
  17. }
  18. static void iT64Build(void);
  19. /*
  20. *
  21. * BASE64 Substitution Table
  22. * -------------------------
  23. *
  24. * Direct Substitution Table
  25. */
  26. static const char T64[64] = {
  27. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  28. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  29. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  30. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  31. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  32. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  33. 'w', 'x', 'y', 'z', '0', '1', '2', '3',
  34. '4', '5', '6', '7', '8', '9', '-', '~'
  35. };
  36. const char * GetBase64SubstitutionTable ()
  37. {
  38. return T64;
  39. }
  40. /*
  41. * Reverse Substitution Table (built in run time)
  42. */
  43. static char iT64[256];
  44. static int isFirstTime = 1;
  45. /*
  46. * Padding
  47. */
  48. static char P64 = '=';
  49. /*
  50. *
  51. * ByteStreamToBase64
  52. * ------------------
  53. *
  54. * Converts binary encoded data to BASE64 format.
  55. *
  56. */
  57. size_t /* Number of bytes in the encoded buffer */
  58. ByteStreamToBase64 (
  59. const uint8_t * InBuffer, /* Input buffer, binary data */
  60. size_t InCount, /* Number of bytes in the input buffer */
  61. char * OutBuffer, /* output buffer */
  62. size_t len /* length of output buffer */
  63. )
  64. {
  65. unsigned char * ps;
  66. unsigned char * pd;
  67. unsigned char acc_1;
  68. unsigned char acc_2;
  69. int i;
  70. int n;
  71. int m;
  72. size_t outCount;
  73. ps = (unsigned char *)InBuffer;
  74. n = InCount/3;
  75. m = InCount%3;
  76. if (!m)
  77. outCount = 4*n;
  78. else
  79. outCount = 4*(n+1);
  80. if (outCount > len) return 0;
  81. pd = (unsigned char *)OutBuffer;
  82. for ( i = 0; i<n; i++ ){
  83. acc_1 = *ps++;
  84. acc_2 = (acc_1<<4)&0x30;
  85. acc_1 >>= 2; /* base64 digit #1 */
  86. *pd++ = T64[acc_1];
  87. acc_1 = *ps++;
  88. acc_2 |= acc_1 >> 4; /* base64 digit #2 */
  89. *pd++ = T64[acc_2];
  90. acc_1 &= 0x0f;
  91. acc_1 <<=2;
  92. acc_2 = *ps++;
  93. acc_1 |= acc_2>>6; /* base64 digit #3 */
  94. *pd++ = T64[acc_1];
  95. acc_2 &= 0x3f; /* base64 digit #4 */
  96. *pd++ = T64[acc_2];
  97. }
  98. if ( m == 1 ){
  99. acc_1 = *ps++;
  100. acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */
  101. acc_1 >>= 2; /* base64 digit #1 */
  102. *pd++ = T64[acc_1];
  103. *pd++ = T64[acc_2];
  104. *pd++ = P64;
  105. *pd++ = P64;
  106. }
  107. else if ( m == 2 ){
  108. acc_1 = *ps++;
  109. acc_2 = (acc_1<<4)&0x3f;
  110. acc_1 >>= 2; /* base64 digit #1 */
  111. *pd++ = T64[acc_1];
  112. acc_1 = *ps++;
  113. acc_2 |= acc_1 >> 4; /* base64 digit #2 */
  114. *pd++ = T64[acc_2];
  115. acc_1 &= 0x0f;
  116. acc_1 <<=2; /* base64 digit #3 */
  117. *pd++ = T64[acc_1];
  118. *pd++ = P64;
  119. }
  120. return outCount;
  121. }
  122. /*
  123. *
  124. * Base64ToByteStream
  125. * ------------------
  126. *
  127. * Converts BASE64 encoded data to binary format. If input buffer is
  128. * not properly padded, buffer of negative length is returned
  129. *
  130. */
  131. size_t /* Number of output bytes */
  132. Base64ToByteStream (
  133. const char * InBuffer, /* BASE64 encoded buffer */
  134. size_t InCount, /* Number of input bytes */
  135. uint8_t * OutBuffer, /* output buffer length */
  136. size_t len /* length of output buffer */
  137. )
  138. {
  139. unsigned char * ps;
  140. unsigned char * pd;
  141. unsigned char acc_1;
  142. unsigned char acc_2;
  143. int i;
  144. int n;
  145. int m;
  146. size_t outCount;
  147. if (isFirstTime) iT64Build();
  148. n = InCount/4;
  149. m = InCount%4;
  150. if (InCount && !m)
  151. outCount = 3*n;
  152. else {
  153. outCount = 0;
  154. return 0;
  155. }
  156. ps = (unsigned char *)(InBuffer + InCount - 1);
  157. while ( *ps-- == P64 ) outCount--;
  158. ps = (unsigned char *)InBuffer;
  159. if (outCount > len) return -1;
  160. pd = OutBuffer;
  161. auto endOfOutBuffer = OutBuffer + outCount;
  162. for ( i = 0; i < n; i++ ){
  163. acc_1 = iT64[*ps++];
  164. acc_2 = iT64[*ps++];
  165. acc_1 <<= 2;
  166. acc_1 |= acc_2>>4;
  167. *pd++ = acc_1;
  168. if (pd >= endOfOutBuffer) break;
  169. acc_2 <<= 4;
  170. acc_1 = iT64[*ps++];
  171. acc_2 |= acc_1 >> 2;
  172. *pd++ = acc_2;
  173. if (pd >= endOfOutBuffer) break;
  174. acc_2 = iT64[*ps++];
  175. acc_2 |= acc_1 << 6;
  176. *pd++ = acc_2;
  177. }
  178. return outCount;
  179. }
  180. size_t Base64EncodingBufferSize (const size_t input_size)
  181. {
  182. auto d = div (input_size, 3);
  183. if (d.rem) d.quot++;
  184. return 4*d.quot;
  185. }
  186. std::string ToBase64Standard (const std::string& in)
  187. {
  188. auto len = Base64EncodingBufferSize (in.length ());
  189. char * str = new char[len+1];
  190. auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
  191. str[l] = 0;
  192. // replace '-' by '+' and '~' by '/'
  193. for (size_t i = 0; i < l; i++)
  194. if (str[i] == '-') str[i] = '+';
  195. else if (str[i] == '~') str[i] = '/';
  196. std::string s(str);
  197. delete[] str;
  198. return s;
  199. }
  200. /*
  201. *
  202. * iT64
  203. * ----
  204. * Reverse table builder. P64 character is replaced with 0
  205. *
  206. *
  207. */
  208. static void iT64Build()
  209. {
  210. int i;
  211. isFirstTime = 0;
  212. for ( i=0; i<256; i++ ) iT64[i] = -1;
  213. for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
  214. iT64[(int)P64] = 0;
  215. }
  216. size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen)
  217. {
  218. int tmp = 0, bits = 0;
  219. size_t ret = 0;
  220. for (size_t i = 0; i < len; i++)
  221. {
  222. char ch = inBuf[i];
  223. if (ch >= '2' && ch <= '7') // digit
  224. ch = (ch - '2') + 26; // 26 means a-z
  225. else if (ch >= 'a' && ch <= 'z')
  226. ch = ch - 'a'; // a = 0
  227. else
  228. return 0; // unexpected character
  229. tmp |= ch;
  230. bits += 5;
  231. if (bits >= 8)
  232. {
  233. if (ret >= outLen) return ret;
  234. outBuf[ret] = tmp >> (bits - 8);
  235. bits -= 8;
  236. ret++;
  237. }
  238. tmp <<= 5;
  239. }
  240. return ret;
  241. }
  242. size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
  243. {
  244. size_t ret = 0, pos = 1;
  245. int bits = 8, tmp = inBuf[0];
  246. while (ret < outLen && (bits > 0 || pos < len))
  247. {
  248. if (bits < 5)
  249. {
  250. if (pos < len)
  251. {
  252. tmp <<= 8;
  253. tmp |= inBuf[pos] & 0xFF;
  254. pos++;
  255. bits += 8;
  256. }
  257. else // last byte
  258. {
  259. tmp <<= (5 - bits);
  260. bits = 5;
  261. }
  262. }
  263. bits -= 5;
  264. int ind = (tmp >> bits) & 0x1F;
  265. outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2');
  266. ret++;
  267. }
  268. return ret;
  269. }
  270. }
  271. }