iOS Openssl 获取证书信息及验签

获取证书数据获取

+(NSDictionary *)getCertInfoWithCerData:(NSData *)certData json:(NSString *)json{
    if (!certData||certData.length < 10) {
        return nil;
    }
    NSMutableDictionary * cerInfo = [NSMutableDictionary dictionary];
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
    const unsigned char *certificateDataBytes = (const unsigned char *)[certData bytes];
    X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [certData length]);
    if (certificateX509 == NULL) {
        return nil;
    }
    ASN1_INTEGER *serial = X509_get_serialNumber(certificateX509);
    BIGNUM *btn = ASN1_INTEGER_to_BN(serial, NULL);
    char *res = BN_bn2hex(btn);
    printX509(certificateX509);

    NSString *serialStr = [NSString stringWithUTF8String:res];
    NSLog(@"序列号:%@",serialStr);
    cerInfo[@"codeSignTime"] = [self getSignTimeStringWithJson:json];
    cerInfo[@"name"] = [NSString stringWithFormat:@"%@",@"SM3WITHSM2"];
    cerInfo[@"OID"] = @"1.2.156.10197.1.501";
    cerInfo[@"decodeName"] = @"X.509";
    cerInfo[@"serialNumber"] = [NSString stringFromHexString:serialStr];

    id publicKey11 = nil;
    SecCertificateRef certificate;
    certificate = cert;
    SecCertificateRef certificates[1];
    CFArrayRef tempCertificates = nil;
    SecPolicyRef policy = nil;
    SecTrustRef trust = nil;
    SecTrustResultType result;
    if (certificate != NULL) {
        certificates[0] = certificate;
        tempCertificates = CFArrayCreate(NULL, (const void **)certificates, 1, NULL);
        policy = SecPolicyCreateBasicX509();
        SecTrustCreateWithCertificates(tempCertificates, policy, &trust);
        SecTrustEvaluate(trust, &result);
        // 获得公钥对象
        publicKey11 = (__bridge_transfer id)SecTrustCopyPublicKey(trust);
    }

    if (CFArrayGetCount(tempCertificates) > 0) {
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(tempCertificates, 0);
        NSDictionary * certInfo = (__bridge_transfer NSDictionary *)identityDict;   
        NSString *   userId = [self getUintNameWithCertInfo:certInfo];
        NSLog(@"certUserID:%@",userId);
        cerInfo[@"userId"] = userId;
        cerInfo[@"hostName"] = userId;
    }

    NSDate * signStartDate = CertificateSignBeginDate(certificateX509);
    cerInfo[@"signNameStartTime"] = [NSString stringWithFormat:@"%@ +8'00'",[self localStringFromUTCDate:signStartDate]];
    NSDate * effectiveDate = CertificateGetExpiryDate(certificateX509);
    NSLog(@"Time:%@",effectiveDate);
    cerInfo[@"signNameEndTime"] = [NSString stringWithFormat:@"%@ +8'00'",[self localStringFromUTCDate:effectiveDate]];
    NSString * signName = CertificateGetIssuerName(certificateX509);
    cerInfo[@"signName"] = signName;
    NSLog(@"name:%@",signName);
    int version = X509_get_version(certificateX509);
    NSLog(@"版本号:%ld",version);
    cerInfo[@"version"] = [NSString stringWithFormat:@"%ld",version + 1];

    /// 获取公钥
    NSData * keyData  =  [self getPublicKeyBitsFromKey:(__bridge SecKeyRef)(publicKey11)];
    NSString * keyHasString = [self hexStringFromData:keyData];
    NSLog(@"公钥key:%@",keyHasString);
    cerInfo[@"publicKey"] = keyHasString;
    NSString * dealKey  = [keyHasString substringFromIndex:2];
    cerInfo[@"px"] = [dealKey substringToIndex:64];
    cerInfo[@"py"] = [dealKey substringFromIndex:64];

//颁发者信息
    cerInfo[@"subObjectInfo"] = CertificateGetSubjectInfo(certificateX509);
//ca机构信息
    cerInfo[@"CAInfoString"] = CertificateCertCaName(certificateX509);
    NSLog(@"证书信息:%@",cerInfo);
    return cerInfo;
}

///颁发结构名称

static NSString* CertificateGetIssuerName(X509*certificateX509)
{
    NSString*issuer =nil;
    if(certificateX509 !=NULL) {
        X509_NAME*issuerX509Name =X509_get_issuer_name(certificateX509);
        if(issuerX509Name !=NULL) {
            charszOutCN[256]={0};
            X509_NAME_get_text_by_NID(issuerX509Name,NID_commonName,szOutCN,256);
            //    NSString *nameStr = [NSString stringWithUTF8String:szOutCN];
            int nid =OBJ_txt2nid("O");// organization
            int index =X509_NAME_get_index_by_NID(issuerX509Name, nid, -1);
            X509_NAME_ENTRY*issuerNameEntry =X509_NAME_get_entry(issuerX509Name, index);
            if(issuerNameEntry) {
                ASN1_STRING*issuerNameASN1 =X509_NAME_ENTRY_get_data(issuerNameEntry);
                if(issuerNameASN1 !=NULL) {
                    unsigned char*issuerName =ASN1_STRING_data(issuerNameASN1);
                    issuer = [NSString stringWithUTF8String:(char*)issuerName];
                }
            }
            int nid1 =OBJ_txt2nid("CN");// organization
            int index1 =X509_NAME_get_index_by_NID(issuerX509Name, nid1, -1);
            X509_NAME_ENTRY*issuerNameEntry11 =X509_NAME_get_entry(issuerX509Name, index1);
            if(issuerNameEntry11) {
                ASN1_STRING*issuerNameASN11 =X509_NAME_ENTRY_get_data(issuerNameEntry11);
                if(issuerNameASN11 !=NULL) {
                    unsigned char*issuerName =ASN1_STRING_data(issuerNameASN11);
                    issuer = [NSString stringWithUTF8String:(char*)issuerName];
                }
            }
        }
    }
    return issuer;
}
  • ///CA机构信息
static NSString* CertificateCertCaName(X509*certificateX509)

{

//    O 组织
//    L地区
//    ST省
//    C国家
//    OU单位
//    CN通用名

    NSMutableString  *issuer = [NSMutableString new];
    if(certificateX509 !=NULL) {
        X509_NAME*issuerX509Name =X509_get_issuer_name(certificateX509);
        if(issuerX509Name !=NULL) {
            charszOutCN[256]={0};
            X509_NAME_get_text_by_NID(issuerX509Name,NID_commonName,szOutCN,256);

            //            NSString *nameStr = [NSString stringWithUTF8String:szOutCN];
            long nid =OBJ_txt2nid("C");// organization
            int index =X509_NAME_get_index_by_NID(issuerX509Name, nid, -1);
            X509_NAME_ENTRY*issuerNameEntry =X509_NAME_get_entry(issuerX509Name, index);
            if(issuerNameEntry) {
                ASN1_STRING*issuerNameASN1 =X509_NAME_ENTRY_get_data(issuerNameEntry);
                if(issuerNameASN1 !=NULL) {
                    unsigned char*issuerName =ASN1_STRING_data(issuerNameASN1);
                    [issuer appendFormat:@"C=%@,",[NSString stringWithUTF8String:(char*)issuerName]];

                }
            }
            long nid2 =OBJ_txt2nid("O");// organization
            int index2 =X509_NAME_get_index_by_NID(issuerX509Name, nid2, -1);
            X509_NAME_ENTRY*issuerNameEntry1 =X509_NAME_get_entry(issuerX509Name, index2);
            if(issuerNameEntry1) {
                ASN1_STRING*issuerNameASN11 =X509_NAME_ENTRY_get_data(issuerNameEntry1);
                if(issuerNameASN11 !=NULL) {
                    unsigned char*issuerName2 =ASN1_STRING_data(issuerNameASN11);
                    [issuer appendFormat:@"O=%@,",[NSString stringWithUTF8String:(char*)issuerName2]];
                }
            }

            int nid3 =OBJ_txt2nid("CN");// CN
            int index3 =X509_NAME_get_index_by_NID(issuerX509Name, nid3, -1);
            X509_NAME_ENTRY*issuerNameEntry3 =X509_NAME_get_entry(issuerX509Name, index3);
            if(issuerNameEntry3) {
                ASN1_STRING*issuerNameASN13 =X509_NAME_ENTRY_get_data(issuerNameEntry3);
                if(issuerNameASN13 !=NULL) {
                    unsigned char*issuerName3 =ASN1_STRING_data(issuerNameASN13);
                    [issuer appendFormat:@"CN=%@",[NSString stringWithUTF8String:(char*)issuerName3]];

                }
            }

            int nid4 =OBJ_txt2nid("title");// Title
            int index4 =X509_NAME_get_index_by_NID(issuerX509Name, nid4, -1);
            X509_NAME_ENTRY*issuerNameEntry4 =X509_NAME_get_entry(issuerX509Name, index4);
            if(issuerNameEntry4) {
                ASN1_STRING*issuerNameASN14 =X509_NAME_ENTRY_get_data(issuerNameEntry4);
                if(issuerNameASN14 !=NULL) {
                    unsigned char*issuerName4 =ASN1_STRING_data(issuerNameASN14);
                    [issuer appendFormat:@"/title=%@",[NSString stringWithUTF8String:(char*)issuerName4]];
                }
            }
        }
    }
    return issuer;
}

///主题信息获取

static NSString  * CertificateGetSubjectInfo(X509*certificateX509){

    NSMutableString * subObjectName = [NSMutableString string];

    X509_NAME*name =X509_get_subject_name(certificateX509);

    if(name !=NULL) {

        charszOutCN[256]={0};
        X509_NAME_get_text_by_NID(name,NID_commonName,szOutCN,256);
        long nid =OBJ_txt2nid("ST");// organization
        int index =X509_NAME_get_index_by_NID(name, nid, -1);

//        int loc = X509_get_ext_by_NID(certificateX509, NID_crl_distribution_points, -1);
//        X509_EXTENSION *ext = X509_get_ext(certificateX509, loc);
//        ASN1_OCTET_STRING *os = X509_EXTENSION_get_data(ext);
//        ASN1_STRING *s = X509_EXTENSION_get_data(ext);
//        const unsigned char *data = ASN1_STRING_data(s);
//        long length = ASN1_STRING_length(s);
//      NSString *sss = [NSString stringWithUTF8String:(char*)data];
        X509_NAME_ENTRY*subNameEntry =X509_NAME_get_entry(name, index);
        if(subNameEntry) {
            ASN1_STRING*subNameASN1 =X509_NAME_ENTRY_get_data(subNameEntry);
            if(subNameASN1 !=NULL) {
                unsigned char*issuerName =ASN1_STRING_data(subNameASN1);
                [subObjectName appendFormat:@"ST=%@,",[NSString stringWithUTF8String:(char*)issuerName]];
            }
        }

        long nidL =OBJ_txt2nid("L");// organization
        int indexL =X509_NAME_get_index_by_NID(name, nidL, -1);
        X509_NAME_ENTRY*subNameEntryL =X509_NAME_get_entry(name, indexL);
        if(subNameEntryL) {
            ASN1_STRING*subNameASN1L =X509_NAME_ENTRY_get_data(subNameEntryL);
            if(subNameASN1L !=NULL) {
                unsigned char*issuerName =ASN1_STRING_data(subNameASN1L);
                [subObjectName appendFormat:@"L=%@,",[NSString stringWithUTF8String:(char*)issuerName]];
            }
        }

        long nidE =OBJ_txt2nid("emailAddress");// organization
        int indexE =X509_NAME_get_index_by_NID(name, nidE, -1);
        X509_NAME_ENTRY*subNameEntryE =X509_NAME_get_entry(name, indexE);
        if(subNameEntryE) {
            ASN1_STRING*subNameASN1E =X509_NAME_ENTRY_get_data(subNameEntryE);
            if(subNameASN1E !=NULL) {
                unsigned char*issuerName =ASN1_STRING_data(subNameASN1E);
                [subObjectName appendFormat:@"E=%@,",[NSString stringWithUTF8String:(char*)issuerName]];
            }
        }

        long nidT =OBJ_txt2nid("telephoneNumber");// organization
        int indexT =X509_NAME_get_index_by_NID(name, nidT, -1);
        X509_NAME_ENTRY*subNameEntryT =X509_NAME_get_entry(name, indexT);
        if(subNameEntryT) {
            ASN1_STRING*subNameASN1T =X509_NAME_ENTRY_get_data(subNameEntryT);
            if(subNameASN1T !=NULL) {
                unsigned char*issuerName =ASN1_STRING_data(subNameASN1T);
                [subObjectName appendFormat:@"TelephoneNumber=%@,",[NSString stringWithUTF8String:(char*)issuerName]];
            }
        }
        long nidC =OBJ_txt2nid("CN");// organization
        int indexC =X509_NAME_get_index_by_NID(name, nidC, -1);
        X509_NAME_ENTRY*subNameEntryC =X509_NAME_get_entry(name, indexC);
        if(subNameEntryC) {
            ASN1_STRING*subNameASN1C =X509_NAME_ENTRY_get_data(subNameEntryC);
            if(subNameASN1C !=NULL) {
                unsigned char*issuerName =ASN1_STRING_data(subNameASN1C);
                [subObjectName appendFormat:@"CN=%@",[NSString stringWithUTF8String:(char*)issuerName]];
            }
        }
    }

    return subObjectName;
}

/// 证书的过期日期时间

static NSDate*CertificateGetExpiryDate(X509*certificateX509)
{

    NSDate*expiryDate =nil;

    if(certificateX509 !=NULL) {
        ASN1_TIME*certificateExpiryASN1 =X509_get_notAfter(certificateX509);
        if(certificateExpiryASN1 !=NULL) {
            ASN1_GENERALIZEDTIME*certificateExpiryASN1Generalized =ASN1_TIME_to_generalizedtime(certificateExpiryASN1,NULL);
            if(certificateExpiryASN1Generalized !=NULL) {
                unsigned char*certificateExpiryData =ASN1_STRING_data(certificateExpiryASN1Generalized);
                // ASN1 generalized times look like this: "20131114230046Z"
                //                                format:  YYYYMMDDHHMMSS
                //                              indices:  01234567890123
                //                                                  1111
                // There are other formats (e.g. specifying partial seconds or
                // time zones) but this is good enough for our purposes since
                // we only use the date and not the time.
                //
                // (Source: http://www.obj-sys.com/asn1tutorial/node14.html)
                NSString*expiryTimeStr = [NSString stringWithUTF8String:(char*)certificateExpiryData];
                NSDateComponents*expiryDateComponents = [[NSDateComponents alloc]init];
                expiryDateComponents.year  = [[expiryTimeStr substringWithRange:NSMakeRange(0,4)]intValue];
                expiryDateComponents.month  = [[expiryTimeStr substringWithRange:NSMakeRange(4,2)]intValue];
                expiryDateComponents.day    = [[expiryTimeStr substringWithRange:NSMakeRange(6,2)]intValue];
                expiryDateComponents.hour  = [[expiryTimeStr substringWithRange:NSMakeRange(8,2)]intValue];
                expiryDateComponents.minute= [[expiryTimeStr substringWithRange:NSMakeRange(10,2)]intValue];
                expiryDateComponents.second= [[expiryTimeStr substringWithRange:NSMakeRange(12,2)]intValue];
                NSCalendar*calendar = [NSCalendar currentCalendar];
                expiryDate = [calendar dateFromComponents:expiryDateComponents];
                //                [expiryDateComponents release];
            }
        }
    }

    return expiryDate;
}

///获取证书生效日期

static NSDate  * CertificateSignBeginDate(X509* certificateX509){

    NSDate*signDate =nil;
    if(certificateX509 !=NULL) {
        ASN1_TIME*certificateExpiryASN1 =X509_get_notBefore(certificateX509);
        if(certificateExpiryASN1 !=NULL) {
            ASN1_GENERALIZEDTIME*certificateExpiryASN1Generalized =ASN1_TIME_to_generalizedtime(certificateExpiryASN1,NULL);
            if(certificateExpiryASN1Generalized !=NULL) {
                unsigned char*certificateExpiryData =ASN1_STRING_data(certificateExpiryASN1Generalized);
                // (Source: http://www.obj-sys.com/asn1tutorial/node14.html)
                NSString*expiryTimeStr = [NSString stringWithUTF8String:(char*)certificateExpiryData];
                NSDateComponents*expiryDateComponents = [[NSDateComponents alloc]init];
                expiryDateComponents.year  = [[expiryTimeStr substringWithRange:NSMakeRange(0,4)]intValue];
                expiryDateComponents.month  = [[expiryTimeStr substringWithRange:NSMakeRange(4,2)]intValue];
                expiryDateComponents.day    = [[expiryTimeStr substringWithRange:NSMakeRange(6,2)]intValue];
                expiryDateComponents.hour  = [[expiryTimeStr substringWithRange:NSMakeRange(8,2)]intValue];
                expiryDateComponents.minute= [[expiryTimeStr substringWithRange:NSMakeRange(10,2)]intValue];
                expiryDateComponents.second= [[expiryTimeStr substringWithRange:NSMakeRange(12,2)]intValue];
                NSCalendar*calendar = [NSCalendar currentCalendar];
                signDate = [calendar dateFromComponents:expiryDateComponents];
            }
        }
    }
    return signDate;
}
static inline char itoh(int i) {
    if(i >9)return'A'+ (i -10);
    return'0'+ i;
}

验签过程:

  EC_GROUP *sm2p256real = new_ec_group(1, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC","28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",

                                         "1");

    unsigned long_outlen;

    NSString* uid = [self dealWithSubName:userIdjson:json];
    NSString* removeSiginJsonStr = [NSString dealWithCodeJson:json];
    //    unsigned char _result[256];
    siginStr = [siginStr uppercaseString];
    NSData* siginData = [self dataFromHexString:siginStr];
    _outlen = [siginData length];
    NSString* px = publicKeyX;
    NSString* py = publicKeyY;
    if(!JZYT_sm2_verify(sm2p256real,
                         "",
                         [px cStringUsingEncoding:NSUTF8StringEncoding],
                         [py cStringUsingEncoding:NSUTF8StringEncoding],
                         [uid cStringUsingEncoding:NSUTF8StringEncoding],
                         [removeSiginJsonStr cStringUsingEncoding:NSUTF8StringEncoding], siginData.bytes,_outlen)){
        returnNO;

    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容

  • PKI 基础知识 (摘自Microsoft Windows 2000 Server白皮书,2000年7月5日发布)...
    right_33cb阅读 953评论 0 1
  • MSP(Membership Service Provider)成员管理服务提供商 名词: 1。CSR(Cerif...
    小蜗牛爬楼梯阅读 2,078评论 0 0
  • 1 概述 本文之所以称之为半自动化,是因为证书的申请并非日常工作,只是一段时间才需要申请,同时,在创建证书和办法证...
    ghbsunny阅读 2,153评论 0 1
  • 2018.3.17 周六 深夜拉窗帘,突然发现窗外的地是湿的。 原来是下雨了。 这是今年的第一场雨。 这是第一场...
    我写写阅读 343评论 3 27
  • 阅读如此重要,那么班级应该如何开展阅读活动呢,下面是我初步制定的几个阅读方案。 1.营造出一个书香氛围 1)制作书...
    双阳480王美元阅读 181评论 0 2