diff options
author | tomsmeding <tom.smeding@gmail.com> | 2016-10-06 20:21:16 +0200 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2016-10-06 20:21:16 +0200 |
commit | aa5365666bb17299035a3d857bcce962004bda1e (patch) | |
tree | 5381d1aa601812662eed0611c223785945502542 /base64.cpp | |
parent | 053d2e76ad5848c8d95d7d56bfe7f8a6a324c229 (diff) |
Base64 and import/export keys
Diffstat (limited to 'base64.cpp')
-rw-r--r-- | base64.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/base64.cpp b/base64.cpp new file mode 100644 index 0000000..80640f2 --- /dev/null +++ b/base64.cpp @@ -0,0 +1,91 @@ +#include "base64.h" + +using namespace std; + +namespace Base64{ + + char alphabet[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + uint8_t revbet[128]={ +#define XX (127) + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX, //0-15 + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX, //16-31 + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,62,XX,XX,XX,63, //32-47 + 52,53,54,55,56,57,58,59,60,61,XX,XX,XX,XX,XX,XX, //48-63 + XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, //64-79 + 15,16,17,18,19,20,21,22,23,24,25,XX,XX,XX,XX,XX, //80-95 + XX,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, //96-111 + 41,42,43,44,45,46,47,48,49,50,51,XX,XX,XX,XX,XX, //112-127 +#undef XX + }; + + string encode(const string &data){ + int sz=data.size(); + if(sz==0)return {}; + int blocks=sz/3; + string res(4*blocks+4*(sz%3!=0),'\0'); + int x; + for(int i=0;i<blocks;i++){ + x=((unsigned char)data[3*i]<<16)|((unsigned char)data[3*i+1]<<8)|(unsigned char)data[3*i+2]; + res[4*i+3]=alphabet[x&0x3f]; x>>=6; + res[4*i+2]=alphabet[x&0x3f]; x>>=6; + res[4*i+1]=alphabet[x&0x3f]; x>>=6; + res[4*i+0]=alphabet[x]; + } + switch(sz%3){ + case 1: + res[4*blocks+0]=alphabet[(unsigned char)data[3*blocks]>>2]; + res[4*blocks+1]=alphabet[((unsigned char)data[3*blocks]&0x3)<<4]; + res[4*blocks+2]='='; + res[4*blocks+3]='='; + break; + + case 2: + res[4*blocks+0]=alphabet[(unsigned char)data[3*blocks]>>2]; + res[4*blocks+1]=alphabet[(((unsigned char)data[3*blocks]&0x3)<<4)|((unsigned char)data[3*blocks+1]>>4)]; + res[4*blocks+2]=alphabet[(((unsigned char)data[3*blocks+1]&0xf)<<2)]; + res[4*blocks+3]='='; + break; + } + return res; + } + + string decode(const string &dataS){ + int szS=dataS.size(); + if(szS==0)return {}; + uint8_t data[szS]; + int sz=0; + for(char c : dataS){ + if(revbet[c&0x7f]!=127)data[sz++]=revbet[c&0x7f]; + } + + int blocks=sz/4; + int endlen; + if(sz%4==0){ + if(data[sz-1]=='='){ + blocks--; + if(data[sz-2]=='=')endlen=1; + else endlen=2; + } else endlen=0; + } else endlen=sz%4-1; + string res(3*blocks+endlen,'\0'); + int x; + for(int i=0;i<blocks;i++){ + x=(data[4*i]<<18)|(data[4*i+1]<<12)|(data[4*i+2]<<6)|data[4*i+3]; + res[3*i+2]=x&0xff; x>>=8; + res[3*i+1]=x&0xff; x>>=8; + res[3*i+0]=x; + } + switch(endlen){ + case 1: + res[3*blocks+0]=(data[4*blocks]<<2)|(data[4*blocks+1]>>4); + break; + + case 2: + res[3*blocks+0]=(data[4*blocks]<<2)|(data[4*blocks+1]>>4); + res[3*blocks+1]=(data[4*blocks+1]<<4)|(data[4*blocks+2]>>2); + break; + } + return res; + } + +} |