00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "CSConfig.h"
00024 #include <ctype.h>
00025
00026 #include "CSGlobal.h"
00027 #include "CSString.h"
00028
00029 #include "CSEncode.h"
00030
00031 static const u_char base64URLMap[64] = {
00032 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00033 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00034 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00035 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00036 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00037 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00038 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00039 '4', '5', '6', '7', '8', '9', '-', '_'
00040 };
00041 static const u_char base64STDMap[64] = {
00042 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00043 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00044 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00045 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00046 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00047 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00048 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00049 '4', '5', '6', '7', '8', '9', '+', '/'
00050 };
00051
00052 static const u_char decodeBase64Map[128] = {
00053 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00054 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00055 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00056 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00057 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00058 0XFF, 0XFF, 0XFF, 0X3E, 0XFF, 0X3E, 0XFF, 0X3F,
00059 0X34, 0X35, 0X36, 0X37, 0X38, 0X39, 0X3A, 0X3B,
00060 0X3C, 0X3D, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00061 0XFF, 0X00, 0X01, 0X02, 0X03, 0X04, 0X05, 0X06,
00062 0X07, 0X08, 0X09, 0X0A, 0X0B, 0X0C, 0X0D, 0X0E,
00063 0X0F, 0X10, 0X11, 0X12, 0X13, 0X14, 0X15, 0X16,
00064 0X17, 0X18, 0X19, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F,
00065 0XFF, 0X1A, 0X1B, 0X1C, 0X1D, 0X1E, 0X1F, 0X20,
00066 0X21, 0X22, 0X23, 0X24, 0X25, 0X26, 0X27, 0X28,
00067 0X29, 0X2A, 0X2B, 0X2C, 0X2D, 0X2E, 0X2F, 0X30,
00068 0X31, 0X32, 0X33, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
00069 };
00070
00071
00072 static bool base64Encoded(const u_char *data, size_t len, const u_char *vc)
00073 {
00074 if (len % 4)
00075 return false;
00076
00077 size_t i = len;
00078
00079 while ( i && data[i-1] == '=') i--;
00080
00081 if ( (len - i) > 2)
00082 return false;
00083
00084 for (; i ; i--, data++) {
00085 if (((*data < 'A') || (*data > 'Z')) &&
00086 ((*data < 'a') || (*data > 'z')) &&
00087 ((*data < '0') || (*data > '9')) &&
00088 ((*data != vc[0]) && (*data != vc[1])))
00089 return false;
00090 }
00091
00092 return true;
00093 }
00094
00095
00096 static char *genericBase64Encode(const void *data, size_t len, char *encode_buffer, size_t encode_buffer_len, const u_char base64Map[])
00097 {
00098 u_char *wptr, *rptr, *encoding;
00099 size_t size;
00100 enter_();
00101
00102 size = ((len + 2) / 3) * 4 +1;
00103 if ((encode_buffer != NULL) && (encode_buffer_len < size))
00104 CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Base64 encode buffer is too small.");
00105
00106 if (encode_buffer)
00107 encoding = (u_char *) encode_buffer;
00108 else
00109 encoding = (u_char *) cs_malloc(size);
00110
00111 size--;
00112 encoding[size] = 0;
00113
00114 wptr= encoding;
00115 rptr = (u_char *) data;
00116
00117 while (len/3) {
00118 wptr[0] = base64Map[rptr[0] >>2];
00119 wptr[1] = base64Map[((rptr[0] & 0X03) <<4) + (rptr[1] >> 4)];
00120 wptr[2] = base64Map[((rptr[1] & 0X0F) <<2) + (rptr[2] >> 6)];
00121 wptr[3] = base64Map[(rptr[2] & 0X3F)];
00122 rptr += 3;
00123 wptr += 4;
00124 len -=3;
00125 }
00126
00127 if (len) {
00128 wptr[0] = base64Map[rptr[0] >>2];
00129
00130 if (len == 1) {
00131 wptr[1] = base64Map[(rptr[0] & 0x03) << 4];
00132 wptr[2] = wptr[3] = '=';
00133 } else {
00134 wptr[1] = base64Map[((rptr[0] & 0X03) <<4) + (rptr[1] >> 4)];
00135 wptr[2] = base64Map[(rptr[1] & 0X0F) <<2];
00136 wptr[3] = '=';
00137 }
00138
00139 }
00140
00141 return_((char*)encoding);
00142 }
00143
00144
00145 static void *genericBase64Decode(const char *data, size_t len, void *decode_buffer, size_t decode_buffer_len, const u_char base64Map[])
00146 {
00147 u_char *wptr, *rptr, *decoding;
00148 enter_();
00149
00150 rptr = (u_char *) data;
00151
00152 if (!base64Encoded(rptr, len, base64Map +62))
00153 CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "String was not Base64 encoded.");
00154
00155 if ((decode_buffer != NULL) && (decode_buffer_len < ((len/ 4) * 3)))
00156 CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Base64 decoded buffer is too small.");
00157
00158 if (decode_buffer)
00159 decoding = (u_char *) decode_buffer;
00160 else
00161 decoding = (u_char *) cs_malloc((len/ 4) * 3);
00162
00163 wptr= decoding;
00164
00165 while (rptr[len-1] == '=')
00166 len--;
00167
00168 while (len/4) {
00169 wptr[0] = ( ((decodeBase64Map[rptr[0]] << 2) & 0xFF) | ((decodeBase64Map[rptr[1]] >> 4) & 0x03) );
00170 wptr[1] = ( ((decodeBase64Map[rptr[1]] << 4) & 0xFF) | ((decodeBase64Map[rptr[2]] >> 2) & 0x0F) );
00171 wptr[2] = ( ((decodeBase64Map[rptr[2]] << 6) & 0xFF) | (decodeBase64Map[rptr[3]] & 0x3F) );
00172
00173 rptr += 4;
00174 wptr += 3;
00175 len -=4;
00176 }
00177
00178 if (len) {
00179 wptr[0] = ( ((decodeBase64Map[rptr[0]] << 2) & 0xFF) | ((decodeBase64Map[rptr[1]] >> 4) & 0x03) );
00180 if (len == 2)
00181 wptr[1] = ( ((decodeBase64Map[rptr[1]] << 4) & 0xFF) | ((decodeBase64Map[rptr[2]] >> 2) & 0x0F) );
00182 }
00183
00184 return_(decoding);
00185 }
00186
00187
00188 char *base64Encode(const void *data, size_t len, char *encode_buffer, size_t encode_buffer_len)
00189 {
00190 return genericBase64Encode(data, len, encode_buffer, encode_buffer_len, base64STDMap);
00191 }
00192
00193
00194 void *base64Decode(const char *data, size_t len, void *decode_buffer, size_t decode_buffer_len)
00195 {
00196 return genericBase64Decode(data, len, decode_buffer, decode_buffer_len, base64STDMap);
00197 }
00198
00199
00200 char *base64UrlEncode(const void *data, size_t len, char *encode_buffer, size_t encode_buffer_len)
00201 {
00202 return genericBase64Encode(data, len, encode_buffer, encode_buffer_len, base64URLMap);
00203 }
00204
00205
00206 void *base64UrlDecode(const char *data, size_t len, void *decode_buffer, size_t decode_buffer_len)
00207 {
00208 return genericBase64Decode(data, len, decode_buffer, decode_buffer_len, base64URLMap);
00209 }
00210
00211 #ifdef NOT_USED
00212
00213 void hmac_md5(u_char *text, size_t text_len, u_char *key, size_t key_len, Md5Digest *digest)
00214 {
00215 CSMd5 md5;
00216 unsigned char k_ipad[65];
00217
00218
00219 unsigned char k_opad[65];
00220
00221
00222 unsigned char tk[16];
00223 int i;
00224
00225
00226 if (key_len > 64) {
00227 CSMd5 tmd5;
00228
00229 md5.md5_init();
00230 md5.md5_append(key, key_len);
00231 md5.md5_digest(digest);
00232
00233 key = digest->val;
00234 key_len = 16;
00235 }
00236
00237
00238 memset(k_ipad, 0, sizeof(k_ipad));
00239 memset(k_opad, 0, sizeof(k_opad));
00240
00241 memcpy(k_ipad, key, key_len);
00242 memcpy(k_opad, key, key_len);
00243
00244
00245 for (i=0; i<64; i++) {
00246 k_ipad[i] ^= 0x36;
00247 k_opad[i] ^= 0x5c;
00248 }
00249
00250
00251
00252 md5.md5_init();
00253 md5.md5_append(k_ipad, 64);
00254 md5.md5_append(text, strlen(text));
00255 md5.md5_digest(digest);
00256
00257
00258
00259
00260 md5.md5_init();
00261 md5.md5_append(k_opad, 64);
00262 md5.md5_append((u_char*)digest, 16);
00263 md5.md5_digest(digest);
00264
00265 }
00266
00267 #endif // NOT_USED
00268
00269
00270 void hmac_sha1(const char *text, const char *key, Sha1Digest *digest)
00271 {
00272 CSSha1 sha1;
00273 size_t key_len = strlen(key);
00274 unsigned char k_ipad[65];
00275
00276
00277 unsigned char k_opad[65];
00278
00279
00280 int i;
00281
00282
00283 if (key_len > 64) {
00284 CSMd5 tmd5;
00285
00286 sha1.sha1_reset();
00287 sha1.sha1_input(key, key_len);
00288 sha1.sha1_digest(digest);
00289
00290 key = (char *) digest->val;
00291 key_len = 16;
00292 }
00293
00294
00295 memset(k_ipad, 0, sizeof(k_ipad));
00296 memset(k_opad, 0, sizeof(k_opad));
00297
00298 memcpy(k_ipad, key, key_len);
00299 memcpy(k_opad, key, key_len);
00300
00301
00302 for (i=0; i<64; i++) {
00303 k_ipad[i] ^= 0x36;
00304 k_opad[i] ^= 0x5c;
00305 }
00306
00307
00308
00309
00310 sha1.sha1_reset();
00311 sha1.sha1_input(k_ipad, 64);
00312 sha1.sha1_input(text, strlen(text));
00313 sha1.sha1_digest(digest);
00314
00315
00316
00317
00318
00319 sha1.sha1_reset();
00320 sha1.sha1_input(k_opad, 64);
00321 sha1.sha1_input(digest, 20);
00322 sha1.sha1_digest(digest);
00323 }
00324
00325
00326
00327 CSString *signature(const char *text, const char *key)
00328 {
00329 Sha1Digest digest;
00330 char *encoding;
00331 CSString *signed_str;
00332
00333 memset(&digest, 0, sizeof(digest));
00334 hmac_sha1(text, key, &digest);
00335
00336 encoding = base64Encode(digest.val, SHA1_HASH_SIZE);
00337 signed_str = CSString::newString(encoding);
00338 cs_free(encoding);
00339 return signed_str;
00340 }
00341
00342
00343
00344
00345 CSString *urlEncode(CSString *src)
00346 {
00347 const char *hex = "0123456789ABCDEF", *start, *ptr;
00348 char encoded[3];
00349 CSStringBuffer *url;
00350
00351 enter_();
00352 push_(src);
00353
00354 new_(url, CSStringBuffer(10));
00355 push_(url);
00356
00357 start = ptr = src->getCString();
00358 encoded[0] = '%';
00359
00360 while(*ptr) {
00361 if (!isalnum(*ptr)) {
00362 switch (*ptr) {
00363 case '.':
00364 case '!':
00365 case '*':
00366 case '~':
00367 case '\'':
00368 case '(':
00369 case ')':
00370 case '_':
00371 case '-':
00372 case '/':
00373 break;
00374 default:
00375 url->append(start, ptr-start);
00376 start = ptr +1;
00377 encoded[1] = hex[*ptr/16];
00378 encoded[2] = hex[*ptr%16];
00379 url->append(encoded, 3);
00380 }
00381 }
00382 ptr++;
00383 }
00384 url->append(start, ptr-start);
00385
00386 CSString *safe_str = CSString::newString(url->getCString());
00387
00388 release_(url);
00389 release_(src);
00390 return_(safe_str);
00391 }