iOS에서 OpenSSL로 X509 인증서 정보 분석

5989 단어
인증서 정보를 분석하기 전에 인증서를 X509 구조체로 변환해야 합니다.다음 코드cert는 X509 인증서 구조체입니다.

1. 인증서 서열 번호 분석

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);

2. 인증서 소유자 정보 분석(사용자 이름)

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);

3. 인증서 발급 기구를 분석한다.

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);

4. 인증서 키 알고리즘 분석

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);

5. 해석 증서 발급 시간과 기한


해석 방법 시간은 직접 얻는 시간이 그리니치 시간이기 때문에 도구 방법이 필요합니다.그것을 초수로 바꾸고 현지 시간으로 바꿔야 한다.
그리니치 시간을 초수로 바꾸는 방법의 원래 방법 주소: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);
}

해석 시간 방법

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);
self.dateFormatter 게으름 피우는 방법
- (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;
}

전문이 끝나다

좋은 웹페이지 즐겨찾기