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進制字節(jié)數(shù)組,tmp用于接收轉(zhuǎn)化后的字符串。為什么要將字節(jié)數(shù)組轉(zhuǎn)化為字符串,我其實也不是很了解,每次都要敲腦袋想半天。只能大致解釋一下:
如圖一buffer指向的內(nèi)存所示,4個字節(jié)里存了4個字符:buffer []= "a!1b",但是字符在內(nèi)存里是沒法像寫在紙上一樣,只能以二進制形式存在,于是就成了這個樣子——"01100001 00100001 00110001 01100010"。這個叫ASCII馬,可自行百度,ASCII馬,此馬甚為有趣。
但是這樣有個問題,就是部分ASCII對應(yīng)的字符無法打印或者不好辨認(rèn),將二進制轉(zhuǎn)換為十六進制方便打印出來。
圖一還有個問題我不懂——tmp = OPENSSL_malloc(len * 3 + 1)。我曾經(jīng)自己實現(xiàn)了一個,但是tmd 啊不,是tmp分配了len*2字節(jié)。腦子好使的講一下。
接下來分析一下為什么先讀取高位后讀取低位。二進制轉(zhuǎn)十六進制有一個好處,就是四個byte可以轉(zhuǎn)化為一個十六進制字符。巧了不是,巧你妹,自己想去。