00001
00024 #include <libzrtpcpp/Base32.h>
00025
00026 int divceil(int a, int b) {
00027 int c;
00028 if (a>0) {
00029 if (b>0) c=a+b-1;
00030 else c=a;
00031 } else {
00032 if (b>0) c=a;
00033 else c=a+b+1;
00034 }
00035 return c/b;
00036 }
00037
00038
00039
00040 static const char* const chars= "ybndrfg8ejkmcpqxot1uwisza345h769";
00041
00042
00043
00044
00045
00046 static const unsigned char revchars[]= {
00047 255, 255, 255, 255, 255, 255, 255, 255,
00048 255, 255, 255, 255, 255, 255, 255, 255,
00049 255, 255, 255, 255, 255, 255, 255, 255,
00050 255, 255, 255, 255, 255, 255, 255, 255,
00051 255, 255, 255, 255, 255, 255, 255, 255,
00052 255, 255, 255, 255, 255, 255, 255, 255,
00053 255, 18, 255, 25, 26, 27, 30, 29,
00054 7, 31, 255, 255, 255, 255, 255, 255,
00055 255, 255, 255, 255, 255, 255, 255, 255,
00056 255, 255, 255, 255, 255, 255, 255, 255,
00057 255, 255, 255, 255, 255, 255, 255, 255,
00058 255, 255, 255, 255, 255, 255, 255, 255,
00059 255, 24, 1, 12, 3, 8, 5, 6,
00060 28, 21, 9, 10, 255, 11, 2, 16,
00061 13, 14, 4, 22, 17, 19, 255, 20,
00062 15, 0, 23, 255, 255, 255, 255, 255,
00063 255, 255, 255, 255, 255, 255, 255, 255,
00064 255, 255, 255, 255, 255, 255, 255, 255,
00065 255, 255, 255, 255, 255, 255, 255, 255,
00066 255, 255, 255, 255, 255, 255, 255, 255,
00067 255, 255, 255, 255, 255, 255, 255, 255,
00068 255, 255, 255, 255, 255, 255, 255, 255,
00069 255, 255, 255, 255, 255, 255, 255, 255,
00070 255, 255, 255, 255, 255, 255, 255, 255,
00071 255, 255, 255, 255, 255, 255, 255, 255,
00072 255, 255, 255, 255, 255, 255, 255, 255,
00073 255, 255, 255, 255, 255, 255, 255, 255,
00074 255, 255, 255, 255, 255, 255, 255, 255,
00075 255, 255, 255, 255, 255, 255, 255, 255,
00076 255, 255, 255, 255, 255, 255, 255, 255,
00077 255, 255, 255, 255, 255, 255, 255, 255,
00078 255, 255, 255, 255, 255, 255, 255, 255
00079 };
00080
00081
00082 Base32::Base32(const string encoded):
00083 binaryResult(NULL), resultLength(0) {
00084
00085 a2b_l(encoded, encoded.size(), (encoded.size()*5/8)*8);
00086 }
00087
00088 Base32::Base32(const string encoded, int noOfBits):
00089 binaryResult(NULL), resultLength(0) {
00090
00091 a2b_l(encoded, divceil(noOfBits, 5), noOfBits);
00092 }
00093
00094 Base32::Base32(const unsigned char* data, int noOfBits):
00095 binaryResult(NULL), resultLength(0) {
00096
00097 b2a_l(data, (noOfBits+7)/8, noOfBits);
00098 }
00099
00100 Base32::~Base32() {
00101 if (binaryResult != NULL && binaryResult != smallBuffer) {
00102 delete [] binaryResult;
00103 }
00104 binaryResult = NULL;
00105 }
00106
00107 const unsigned char* Base32::getDecoded(int &length) {
00108 length = resultLength;
00109 return binaryResult;
00110 }
00111
00112 void Base32::b2a_l(const unsigned char* os, int len,
00113 const size_t lengthinbits) {
00114
00115
00116
00117
00118
00119 string result(divceil(len*8, 5), ' ');
00120
00121
00122
00123
00124 int resp = result.size();
00125
00126
00127
00128
00129 const unsigned char* osp = os + len;
00130
00131
00132
00133 unsigned long x = 0;
00134 switch ((osp - os) % 5) {
00135
00136 case 0:
00137 do {
00138 x = *--osp;
00139 result[--resp] = chars[x % 32];
00140 x /= 32;
00141 case 4:
00142 x |= ((unsigned long)(*--osp)) << 3;
00143 result[--resp] = chars[x % 32];
00144 x /= 32;
00145 result[--resp] = chars[x % 32];
00146 x /= 32;
00147 case 3:
00148 x |= ((unsigned long)(*--osp)) << 1;
00149
00150 result[--resp] = chars[x % 32];
00151 x /= 32;
00152 case 2:
00153 x |= ((unsigned long)(*--osp)) << 4;
00154
00155 result[--resp] = chars[x%32];
00156 x /= 32;
00157 result[--resp] = chars[x%32];
00158 x /= 32;
00159 case 1:
00160 x |= ((unsigned long)(*--osp)) << 2;
00161
00162 result[--resp] = chars[x%32];
00163 x /= 32;
00164 result[--resp] = chars[x];
00165 } while (osp > os);
00166 }
00167
00168
00169 encoded = result.substr(0, divceil(lengthinbits, 5));
00170 return;
00171 }
00172
00173 void Base32::a2b_l(const string cs, size_t size, const size_t lengthinbits ) {
00174 unsigned long x = 0;
00175
00176 int len = divceil(size*5, 8);
00177
00178
00179
00180
00181
00182
00183
00184 if (len < 128) {
00185 binaryResult = smallBuffer;
00186 }
00187 else {
00188 binaryResult = new unsigned char[len];
00189 }
00190
00191
00192
00193
00194 unsigned char* resp = binaryResult + len;
00195
00196
00197
00198
00199 int csp = size;
00200
00201
00202 switch (csp % 8) {
00203 case 0:
00204 do {
00205 x = revchars[cs[--csp]];
00206 case 7:
00207 x |= revchars[cs[--csp]] << 5;
00208 *--resp = x % 256;
00209 x /= 256;
00210 case 6:
00211 x |= revchars[cs[--csp]] << 2;
00212 case 5:
00213 x |= revchars[cs[--csp]] << 7;
00214 *--resp = x % 256;
00215 x /= 256;
00216 case 4:
00217 x |= revchars[cs[--csp]] << 4;
00218 *--resp = x % 256;
00219 x /= 256;
00220 case 3:
00221 x |= revchars[cs[--csp]] << 1;
00222 case 2:
00223 x |= revchars[cs[--csp]] << 6;
00224 *--resp = x % 256;
00225 x /= 256;
00226 case 1:
00227 x |= revchars[cs[--csp]] << 3;
00228 *--resp = x % 256;
00229 } while (csp);
00230 }
00231
00232
00233 resultLength = divceil(lengthinbits, 8);
00234 return;
00235 }
00236
00237 #ifdef UNIT_TEST
00238 #include <math.h>
00239
00240
00241 uint8* randz(const size_t len)
00242 {
00243 uint8* result = (uint8*)malloc(len);
00244 size_t i;
00245 for (i=0; i<len; i++) {
00246 result[i] = rand() % 256;
00247 }
00248 return result;
00249 }
00250
00251 int main(int argc, char *argv[]) {
00252
00253 int32 resLen;
00254 string a;
00255 const uint8* zrecovered;
00256 uint8 ones[] = {1, 1, 1, 1, 1};
00257
00258
00259 a = Base32(ones, 5*8).getEncoded();
00260
00261
00262 cout << "Encoded 5 ones: '" << a << "', Expected: 'yryonyeb'" << endl;
00263
00264
00265 Base32 *y = new Base32(a);
00266 zrecovered = y->getDecoded(resLen);
00267 if (resLen != 5 && memcmp(ones, zrecovered, 5)) {
00268 printf("Failed basic 5 ones recovery test.\n");
00269 return -1;
00270 }
00271 delete y;
00272
00273 a = Base32(ones, 15).getEncoded();
00274 cout << "Encoded 5 ones, 15 bits only: '" << a << "', Expected: 'yry'" << endl;
00275
00276 y = new Base32(a, 15);
00277 zrecovered = y->getDecoded(resLen);
00278 printf("Decoded 15 bits, result length: %d (should be 2)\n", resLen);
00279 printf("Decoded bytes: %x %x (should be 1 0)\n", zrecovered[0], zrecovered[1]);
00280 delete y;
00281
00282 for (int i = 0; i < 2; i++) {
00283 uint8* z = randz(16);
00284 a = Base32(z, 16*8).getEncoded();
00285
00286 assert (a.size() == Base32::b2alen(16*8));
00287 Base32 *x = new Base32(a);
00288 zrecovered = x->getDecoded(resLen);
00289 if (resLen != 16 && memcmp(z, zrecovered, 16)) {
00290 printf("Failed basic recovery test.\n");
00291 return -1;
00292 }
00293 delete x;
00294 free((void*)z);
00295 }
00296 }
00297 #endif