Add base64 code (unpadded standard alphabet)

This commit is contained in:
Adam Ierymenko 2019-08-07 22:35:17 -05:00
parent 1a2ff884b3
commit 91a37f8868
No known key found for this signature in database
GPG key ID: 1657198823E52A61
3 changed files with 129 additions and 6 deletions

View file

@ -247,4 +247,83 @@ int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)
return -1;
}
unsigned int Utils::b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen)
{
static const char base64en[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };
unsigned int i = 0,j = 0;
uint8_t l = 0;
int s = 0;
for (;i<inlen;++i) {
uint8_t c = in[i];
switch (s) {
case 0:
s = 1;
if (j >= outlen) return 0;
out[j++] = base64en[(c >> 2) & 0x3f];
break;
case 1:
s = 2;
if (j >= outlen) return 0;
out[j++] = base64en[((l & 0x3) << 4) | ((c >> 4) & 0xf)];
break;
case 2:
s = 0;
if (j >= outlen) return 0;
out[j++] = base64en[((l & 0xf) << 2) | ((c >> 6) & 0x3)];
if (j >= outlen) return 0;
out[j++] = base64en[c & 0x3f];
break;
}
l = c;
}
switch (s) {
case 1:
if (j >= outlen) return 0;
out[j++] = base64en[(l & 0x3) << 4];
//out[j++] = '=';
//out[j++] = '=';
break;
case 2:
if (j >= outlen) return 0;
out[j++] = base64en[(l & 0xf) << 2];
//out[j++] = '=';
break;
}
if (j >= outlen) return 0;
out[j] = 0;
return j;
}
unsigned int Utils::b64d(const char *in,unsigned char *out,unsigned int outlen)
{
static const uint8_t base64de[256] = { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255,255,255,255,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255,255,255,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,255,255,255,255,255 };
unsigned int i = 0;
unsigned int j = 0;
while ((in[i] != '=')&&(in[i] != 0)) {
if (j >= outlen)
break;
uint8_t c = base64de[(unsigned char)in[i]];
if (c != 255) {
switch (i & 0x3) {
case 0:
out[j] = (c << 2) & 0xff;
break;
case 1:
out[j++] |= (c >> 4) & 0x3;
out[j] = (c & 0xf) << 4;
break;
case 2:
out[j++] |= (c >> 2) & 0xf;
out[j] = (c & 0x3) << 6;
break;
case 3:
out[j++] |= c;
break;
}
}
++i;
}
return j;
}
} // namespace ZeroTier

View file

@ -245,6 +245,10 @@ public:
static int b32d(const char *encoded, uint8_t *result, int bufSize);
static int b32e(const uint8_t *data,int length,char *result,int bufSize);
static inline unsigned int b64MaxEncodedSize(const unsigned int s) { return ((((s + 2) / 3) * 4) + 1); }
static unsigned int b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen);
static unsigned int b64d(const char *in,uint8_t *out,unsigned int outlen);
/**
* Tokenize a string (alias for strtok_r or strtok_s depending on platform)
*

View file

@ -712,6 +712,46 @@ static int testOther()
return -1;
}
std::cout << "[other] Testing base32... "; std::cout.flush();
for(unsigned int i=1;i<1024;++i) {
Utils::getSecureRandom(buf,(unsigned int)sizeof(buf));
int l = Utils::b32e((const uint8_t *)buf,i,buf2,sizeof(buf2));
if (l <= 0) {
std::cout << "FAIL (encode returned 0)" << std::endl;
return -1;
}
int l2 = Utils::b32d(buf2,(uint8_t *)buf3,sizeof(buf3));
if (l2 != (int)i) {
std::cout << "FAIL (decode returned wrong count)" << std::endl;
return -1;
}
if (memcmp(buf,buf3,i) != 0) {
std::cout << "FAIL (decode result incorrect)" << std::endl;
return -1;
}
}
std::cout << "PASS" << std::endl;
std::cout << "[other] Testing base64... "; std::cout.flush();
for(unsigned int i=1;i<1024;++i) {
Utils::getSecureRandom(buf,(unsigned int)sizeof(buf));
unsigned int l = Utils::b64e((const uint8_t *)buf,i,buf2,sizeof(buf2));
if (l == 0) {
std::cout << "FAIL (encode returned 0)" << std::endl;
return -1;
}
unsigned int l2 = Utils::b64d(buf2,(uint8_t *)buf3,sizeof(buf3));
if (l2 != i) {
std::cout << "FAIL (decode returned wrong count)" << std::endl;
return -1;
}
if (memcmp(buf,buf3,i) != 0) {
std::cout << "FAIL (decode result incorrect)" << std::endl;
return -1;
}
}
std::cout << "PASS" << std::endl;
std::cout << "[other] Testing InetAddress encode/decode..."; std::cout.flush();
std::cout << " " << InetAddress("127.0.0.1/9993").toString(buf);
std::cout << " " << InetAddress("feed:dead:babe:dead:beef:f00d:1234:5678/12345").toString(buf);