美文网首页iOS Developer
iOS 用OpenSSL解析X509证书信息

iOS 用OpenSSL解析X509证书信息

作者: LarkNan | 来源:发表于2017-01-15 15:26 被阅读500次

    在解析证书信息之前,需要将证书转换为X509结构体。以下代码中<code>cert</code>为X509证书结构体

    <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>三、解析证书颁发机构</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://地区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(@"颁发机构:%@",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>五、解析证书颁发时间和过期时间</h4>

    解析办法时间需要一个工具方法,因为直接获取时间为格林威治时间。需要把它转化成秒数然后再转化为本地时间。

    <b>将格林威治时间转换成秒数的方法</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};
            
    // 颁发时间
    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(@"颁发时间:%@",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;
    }
    

    全文完

    相关文章

      网友评论

        本文标题:iOS 用OpenSSL解析X509证书信息

        本文链接:https://www.haomeiwen.com/subject/yntdvttx.html