iOS 使用OpenSSL 读取P12证书信息

1、OpenSSL 库使用pod 方式引入:

pod 'OpenSSL-Universal'

2、准备一个p12证书

示例:develop.p12, 密码: 123456

3、引入相关的头文件:

#import 
#import 
#import 
#import 

4、读取p12证书相关信息:

-  (void)readP12Info {
      NSString *filePath = [[NSBundle mainBundle]     pathForResource:@"develop" ofType:@"p12"];
      NSString *password = @"123456";

      PKCS12 *p12 = NULL; //p12对像:包含证书信息和秘钥
      X509* usrCert = NULL; //证书信息
      EVP_PKEY* pkey = NULL; //秘钥
      STACK_OF(X509)* ca = NULL; //证书信息栈
      BIO*bio = NULL; //BIO是封装了许多类型I/O接口细节的一种应用接口,可以和SSL连接、非加密的网络连接以及文件IO进行透明的连接。 
      //BIO更多信息:https://blog.csdn.net/liao20081228/article/details/77193729/

      OpenSSL_add_all_algorithms();
      SSLeay_add_all_algorithms();
      ERR_load_crypto_strings();
    
      bio = BIO_new_file([filePath UTF8String], "r");
      p12 = d2i_PKCS12_bio(bio, NULL); //得到p12结构
      PKCS12_parse(p12, [password UTF8String], &pkey, &usrCert, &ca); //得到x509结构

      //序列号
      NSString *serialNumber = [self __getSerialNumberString:usrCert];
      //证书拥有者信息
      NSString *userName = [self __getUserName:usrCert];
      //颁发机构
      NSString *issuserInfo = [self __getIssuserInfo:usrCert];
      //生效时间
      NSDate *beginDate = [self __getSignBeginDate:usrCert];
      //过期时间
      NSDate *expiryDate = [self __getExpiryDate:usrCert];
      //SHA-1
      NSString *sha1 = [self __sha1:usrCert];
      //版本号
      NSString *version = [self __getVersion:usrCert];

      BIO_free_all(bio);
      PKCS12_free(p12);
      EVP_PKEY_free(pkey);
      X509_free(usrCert);
}
//版本号
- (long)__getVersion:(X509 *)cert {
    long version = X509_get_version(cert);
    return version;
}
///序列号
- (NSString *)__getSerialNumberString:(X509*)usrCert {
    ASN1_INTEGER *serial = X509_get_serialNumber(usrCert);
    BIGNUM *bignum = ASN1_INTEGER_to_BN(serial, NULL);
    char *res = BN_bn2hex(bignum);
    NSString *serialStr = [NSString stringWithUTF8String:res];
    return serialStr;
}

///证书拥有者信息
- (NSString *)__getUserName:(X509 *)usrCert {
    char szOutCN[256]={0};
    X509_NAME *name = NULL;
    name = usrCert->cert_info->subject;
    X509_NAME_get_text_by_NID(name,NID_commonName,szOutCN,256);
    NSString *nameStr = [NSString stringWithUTF8String:szOutCN];
    return nameStr;
}

///颁发机构
- (NSString *)__getIssuserInfo:(X509 *)usrCert {
    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(usrCert);
    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]];
                self.info.country = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_stateOrProvinceName://省ST
                [issuerInfo appendString:[NSString stringWithFormat:@"ST=%s,",msginfo]];
                self.info.province = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_localityName://地区L
                [issuerInfo appendString:[NSString stringWithFormat:@"L=%s,",msginfo]];
                self.info.region = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_organizationName://组织O=
                [issuerInfo appendString:[NSString stringWithFormat:@"O=%s,",msginfo]];
                self.info.organization = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_organizationalUnitName://单位OU
                [issuerInfo appendString:[NSString stringWithFormat:@"OU=%s,",msginfo]];
                self.info.unit = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_commonName://通用名CN
                [issuerInfo appendString:[NSString stringWithFormat:@"CN=%s",msginfo]];
                self.info.commonName = [NSString stringWithFormat:@"%s",msginfo];
                break;
                
            case NID_pkcs9_emailAddress://Mail
                break;
        }
    }
    return issuerInfo;
}

///开始颁发的时间
- (NSDate *)__getSignBeginDate:(X509 *)cert {
    ASN1_TIME *start = NULL;
    time_t ttStart = {0};
    // 颁发时间
    start = X509_get_notBefore(cert);
    ttStart = [self __skf_ext_ASN1_GetTimeT:start];
    // 格林威治时间与北京时间相差八小时,所以加八小时。
    ttStart = ttStart + 8 * 60 * 60;
    NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:ttStart];
    return startDate;
}

///有效时间
- (NSDate *)__getExpiryDate:(X509 *)cert {
    ASN1_TIME *end = NULL;
    time_t ttEnd = {0};
    
    // 过期时间
    end = X509_get_notAfter(cert);
    ttEnd = [self __skf_ext_ASN1_GetTimeT:end];
    ttEnd = ttEnd + 8 * 60 * 60;
    NSDate *endDate = [NSDate dateWithTimeIntervalSince1970:ttEnd];
    return endDate;
}

///格林威治时间转本地时间
- (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);
}
//指纹信息
- (NSString*) __sha1:(X509 *)cert {
    PKCS12_SAFEBAG *safeBag = PKCS12_x5092certbag(cert);
    NSData *certData = [NSData dataWithBytes: safeBag->value.bag->value.x509cert->data   length:safeBag->value.bag->value.x509cert->length];
    
    unsigned char sha1Buffer[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(certData.bytes, (unsigned int)certData.length, sha1Buffer);
    NSMutableString *fingerprint = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; ++i){
        [fingerprint appendFormat:@"%02x ",sha1Buffer[i]];
    }
    NSString *fingerString = [fingerprint stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    fingerString = [fingerString stringByReplacingOccurrencesOfString:@" " withString:@""];
    PKCS12_SAFEBAG_free(safeBag);
    return fingerString.uppercaseString;
}

备注:想要获取更多信息可以去X509对象中获取。

你可能感兴趣的:(iOS 使用OpenSSL 读取P12证书信息)