iOS|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 = https://www.it610.com/article/[NSData dataWithBytes: safeBag->value.bag->value.x509cert->datalength: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对象中获取。

    推荐阅读