OpenSSL里提供了提供了两个API
char *hex_to_string(const unsigned char *buffer, long len)
unsigned char *string_to_hex(const char *str,long *len)
源码如下:
<code><p>
356 /* hex string utilities */
357
358 /* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
359 * hex representation
360 * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
361 */
362
363 char *hex_to_string(const unsigned char *buffer, long len)
364 {
365 char *tmp, *q;
366 const unsigned char *p;
367 int i;
368 const static char hexdig[] = "0123456789ABCDEF";
369 if(!buffer || !len) return NULL;
370 if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
371 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
372 return NULL;
373 }
374 q = tmp;
375 for(i = 0, p = buffer; i < len; i++,p++) {
376 *q++ = hexdig[(*p >> 4) & 0xf];
377 *q++ = hexdig[*p & 0xf];
378 *q++ = ':';
379 }
380 q[-1] = 0;
381 #ifdef CHARSET_EBCDIC
382 ebcdic2ascii(tmp, tmp, q - tmp - 1);
383 #endif
384
385 return tmp;
386 }
387
388 /* Give a string of hex digits convert to
389 * a buffer
390 */
391
392 unsigned char *string_to_hex(const char *str, long *len)
393 {
394 unsigned char *hexbuf, *q;
395 unsigned char ch, cl, *p;
396 if(!str) {
397 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
398 return NULL;
399 }
400 if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
401 for(p = (unsigned char *)str, q = hexbuf; *p;) {
402 ch = *p++;
403 #ifdef CHARSET_EBCDIC
404 ch = os_toebcdic[ch];
405 #endif
406 if(ch == ':') continue;
407 cl = *p++;
408 #ifdef CHARSET_EBCDIC
409 cl = os_toebcdic[cl];
410 #endif
411 if(!cl) {
412 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
413 OPENSSL_free(hexbuf);
414 return NULL;
415 }
416 if(isupper(ch)) ch = tolower(ch);
417 if(isupper(cl)) cl = tolower(cl);
418
419 if((ch >= '0') && (ch <= '9')) ch -= '0';
420 else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
421 else goto badhex;
422
423 if((cl >= '0') && (cl <= '9')) cl -= '0';
424 else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
425 else goto badhex;
426
427 *q++ = (ch << 4) | cl;
428 }
429
430 if(len) *len = q - hexbuf;
431
432 return hexbuf;
433
434 err:
435 if(hexbuf) OPENSSL_free(hexbuf);
436 X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
437 return NULL;
438
439 badhex:
440 OPENSSL_free(hexbuf);
441 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
442 return NULL;
443
444 }
</p></code>
本人语言能力略差,因此做图分析hex_to_string
如图一所示,buffer指向16进制字节数组,tmp用于接收转化后的字符串。为什么要将字节数组转化为字符串,我其实也不是很了解,每次都要敲脑袋想半天。只能大致解释一下:
如图一buffer指向的内存所示,4个字节里存了4个字符:buffer []= "a!1b",但是字符在内存里是没法像写在纸上一样,只能以二进制形式存在,于是就成了这个样子——"01100001 00100001 00110001 01100010"。这个叫ASCII马,可自行百度,ASCII马,此马甚为有趣。
但是这样有个问题,就是部分ASCII对应的字符无法打印或者不好辨认,将二进制转换为十六进制方便打印出来。
图一还有个问题我不懂——tmp = OPENSSL_malloc(len * 3 + 1)。我曾经自己实现了一个,但是tmd 啊不,是tmp分配了len*2字节。脑子好使的讲一下。
接下来分析一下为什么先读取高位后读取低位。二进制转十六进制有一个好处,就是四个byte可以转化为一个十六进制字符。巧了不是,巧你妹,自己想去。