iOS 用OpenSSL解析X509證書信息

在解析證書信息之前颈嚼,需要將證書轉(zhuǎn)換為X509結(jié)構(gòu)體。以下代碼中<code>cert</code>為X509證書結(jié)構(gòu)體

<h4>一、解析證書序列號</h4>

ASN1_INTEGER *serial = X509_get_serialNumber(cert);
BIGNUM *btn = ASN1_INTEGER_to_BN(serial, NULL);
char *res = BN_bn2hex(btn);
NSString *serialStr = [NSString stringWithUTF8String:res];
NSLog(@"序列號:%@",serialStr);

<h4>二冯痢、解析證書擁有者信息(用戶名)</h4>

char szOutCN[256]={0};
X509_NAME *name = NULL;
name = cert->cert_info->subject;      
X509_NAME_get_text_by_NID(name,NID_commonName,szOutCN,256)
NSString *nameStr = [NSString stringWithUTF8String:szOutCN];
NSLog(@"用戶名:%@",nameStr);

<h4>三、解析證書頒發(fā)機(jī)構(gòu)</h4>

X509_NAME_ENTRY *name_entry;
long Nid;
unsigned char msginfo[1024];
int msginfoLen;
        
NSMutableString *issuerInfo = [[NSMutableString alloc] init];
NSMutableString *certCN = [[NSMutableString alloc] init];
        
X509_NAME *issuer = X509_get_issuer_name(cert);
int entriesNum = sk_X509_NAME_ENTRY_num(issuer->entries);
for (int i = 0; i < entriesNum; i++) {
    name_entry = sk_X509_NAME_ENTRY_value(issuer->entries, i);
            
    Nid = OBJ_obj2nid(name_entry->object);
    msginfoLen = name_entry->value->length;
    memcpy(msginfo,name_entry->value->data,msginfoLen);
    msginfo[msginfoLen]='\0';
            
    switch(Nid)
    {
        case NID_countryName://國家C
                    [issuerInfo appendString:[NSString stringWithFormat:@"C=%s,",msginfo]];
                    [certCN appendString:[NSString stringWithFormat:@"C=%s",msginfo]];
                    break;
                    
        case NID_stateOrProvinceName://省ST
                    [issuerInfo appendString:[NSString stringWithFormat:@"ST=%s,",msginfo]];
                    break;
                    
        case NID_localityName://地區(qū)L
                    [issuerInfo appendString:[NSString stringWithFormat:@"L=%s,",msginfo]];
                    break;
                    
        case NID_organizationName://組織O=
                    [issuerInfo appendString:[NSString stringWithFormat:@"O=%s,",msginfo]];
                    break;
                    
        case NID_organizationalUnitName://單位OU
                    [issuerInfo appendString:[NSString stringWithFormat:@"OU=%s,",msginfo]];
                    break;
                    
        case NID_commonName://通用名CN
                    [issuerInfo appendString:[NSString stringWithFormat:@"CN=%s",msginfo]];
                    break;
                    
        case NID_pkcs9_emailAddress://Mail
                    break;
                    
            }
}

NSLog(@"頒發(fā)機(jī)構(gòu):%@",issuerInfo);

<h4>四框杜、解析證書密鑰算法</h4>

EVP_PKEY *pk = NULL;
pk = X509_get_pubkey(cert);
NSString *pulType;
        
if (EVP_PKEY_RSA == pk->type) {
    pulType = @"RSA";
} else if (EVP_PKEY_EC == pk->type) {
    pulType = @"EC";
} else if (EVP_PKEY_DSA == pk->type) {
    pulType = @"DSA";
} else if (EVP_PKEY_DH == pk->type) {
    pulType = @"DH";
} else {
    pulType = @"UNKNOWN";
}

NSLog(@"密鑰算法:%@",pulType);

<h4>五浦楣、解析證書頒發(fā)時間和過期時間</h4>

解析辦法時間需要一個工具方法,因?yàn)橹苯荧@取時間為格林威治時間咪辱。需要把它轉(zhuǎn)化成秒數(shù)然后再轉(zhuǎn)化為本地時間振劳。

<b>將格林威治時間轉(zhuǎn)換成秒數(shù)的方法</b>
原方法地址:http://stackoverflow.com/questions/10975542/asn1-time-to-time-t-conversion

- (time_t)skf_ext_ASN1_GetTimeT:(ASN1_TIME *)time {
    struct tm t;
    const char* str = (const char*) time->data;
    size_t i = 0;
    
    memset(&t, 0, sizeof(t));
    
    if (time->type == V_ASN1_UTCTIME) {/* two digit year */
        t.tm_year = (str[i++] - '0') * 10;
        t.tm_year += (str[i++] - '0');
        if (t.tm_year < 70)
            t.tm_year += 100;
    } else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year */
        t.tm_year = (str[i++] - '0') * 1000;
        t.tm_year+= (str[i++] - '0') * 100;
        t.tm_year+= (str[i++] - '0') * 10;
        t.tm_year+= (str[i++] - '0');
        t.tm_year -= 1900;
    }
    t.tm_mon  = (str[i++] - '0') * 10;
    t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1.
    t.tm_mday = (str[i++] - '0') * 10;
    t.tm_mday+= (str[i++] - '0');
    t.tm_hour = (str[i++] - '0') * 10;
    t.tm_hour+= (str[i++] - '0');
    t.tm_min  = (str[i++] - '0') * 10;
    t.tm_min += (str[i++] - '0');
    t.tm_sec  = (str[i++] - '0') * 10;
    t.tm_sec += (str[i++] - '0');
    
    /* Note: we did not adjust the time based on time zone information */
    return mktime(&t);
}

<b>解析時間方法</b>


ASN1_TIME *start = NULL;
ASN1_TIME *end = NULL;
time_t ttStart = {0};
time_t ttEnd = {0};
        
// 頒發(fā)時間
start = X509_get_notBefore(cert);
ttStart = [self skf_ext_ASN1_GetTimeT:start];
// 格林威治時間與北京時間相差八小時,所以加八小時油狂。
ttStart = ttStart + 8 * 60 * 60; 
NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:ttStart];
NSString *startDateStr = [self.dateFormatter stringFromDate:startDate];
NSLog(@"頒發(fā)時間:%@",startDateStr);

// 過期時間
end = X509_get_notAfter(cert);
ttEnd = [self skf_ext_ASN1_GetTimeT:end];
ttEnd = ttEnd + 8 * 60 * 60;
NSDate *endDate = [NSDate dateWithTimeIntervalSince1970:ttEnd];
NSString *endDateStr = [self.dateFormatter stringFromDate:endDate];
NSLog(@"過期時間:%@",endDateStr);

<b><code>self.dateFormatter</code>懶加載方法</b>

- (NSDateFormatter *)dateFormatter
{
    if (!_dateFormatter) {
        _dateFormatter = [[NSDateFormatter alloc] init];
        NSTimeZone *zone = [NSTimeZone localTimeZone];
        [_dateFormatter setTimeZone:zone];
        [_dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    }
    return _dateFormatter;
}

全文完

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末历恐,一起剝皮案震驚了整個濱河市庐杨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夹供,老刑警劉巖灵份,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哮洽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸟辅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門氛什,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人枪眉,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵医瘫,是天一觀的道長。 經(jīng)常有香客問我畔濒,道長,這世上最難降的妖魔是什么艇潭? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮迄汛,結(jié)果婚禮上隔心,老公的妹妹穿的比我還像新娘硬霍。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布戈毒。 她就那樣靜靜地躺著命贴,像睡著了一般胚泌。 火紅的嫁衣襯著肌膚如雪章喉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天身坐,我揣著相機(jī)與錄音秸脱,去河邊找鬼。 笑死部蛇,一個胖子當(dāng)著我的面吹牛摊唇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涯鲁,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巷查,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抹腿?” 一聲冷哼從身側(cè)響起岛请,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幢踏,沒想到半個月后髓需,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡房蝉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年僚匆,在試婚紗的時候發(fā)現(xiàn)自己被綠了微渠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡咧擂,死狀恐怖逞盆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情松申,我是刑警寧澤云芦,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站贸桶,受9級特大地震影響舅逸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜皇筛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一琉历、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧水醋,春花似錦旗笔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惶桐,卻和暖如春撮弧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耀盗。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工想虎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叛拷。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像岂却,于是被迫代替她去往敵國和親忿薇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容