美文网首页
Get certificate infomation

Get certificate infomation

作者: ienos | 来源:发表于2020-03-28 15:29 被阅读0次

    举个🌰,比如说我们希望通过 App 获取存储在沙盒下的证书过期时间

    获取本地证书

    非 P12 证书获取

    1.通过本地路径获取证书数据 Data
    2.通过证书 Data 获取 CertificateRef

    NSData *certData = [NSData dataWithContentsOfFile:path];
    //    if (certData.length == 0) return ;
    SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
    //    if (!certRef) return ;
    CFRelease(certRef);
    

    P12 证书获取方式

    1. 通过路径获取证书数据 Data
    2. 通过 Import PCK 方法获取证书数组 CertIdentifyTrustDictArrays
    3. 通过证书的 Identify 创建 CertificateRef
    CFDictionaryRef secImportOptions = (__bridge CFDictionaryRef) @{(__bridge id) kSecImportExportPassphrase : psk};
    CFArrayRef secImportItems = NULL; // 证书列表
    NSData *pk12Data = [NSData dataWithContentsOfFile:path];
    OSStatus status = SecPKCS12Import((__bridge CFDataRef) pk12Data, (CFDictionaryRef) secImportOptions, &secImportItems);
    if (status == errSecSuccess
        && secImportItems && CFArrayGetCount(secImportItems) > 0) {
        // Identify
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(secImportItems,0);
        const void*tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
        SecIdentityRef identify = (SecIdentityRef)tempIdentity;
        SecCertificateRef certRef;
        OSStatus status = SecIdentityCopyCertificate(identify, &certRef);
        if (status == errSecSuccess) {
            SecCertificateRef certRef = SecCertificateCopyData(certRef);
            CFRelease(certRef);
        }
    }
    

    通过 SecCertificateRef 获取证书信息

    目前暂未找到 Security Framework 有相关 Api

    所以使用了开源库 Openssl-iOS GitHub

    Openssl-iOS 的使用

    下载完成后,打开项目根目录,推荐使用 Go2shell 工具,可以直接打开终端并进入当前目录路径下

    运行 shell 脚本 ./build-libssl.sh 进行编译输出

    最后在 lib 下找到 libssl.a、libcrypto.a 拉到项目中的 Framework
    然后将 include 文件夹拉到项目文件夹中,但是可以不用拉到 .xcodeproj / .xcworkspace 中

    最后一步,在 Target 中的 BuildSetting 搜索🔍 Header Search Paths 然后将 include 文件路径拖进去

    这样就可以使用 Openssl-iOS

    修改支持的指令集 [Optional]

    我下载的那个版本中,build-libssl.sh 中定义了 Target 编译的指令集
    DEFAULTTARGETS 字段中只支持 ios64-cross-arm64 ios64-cross-arm64e

    后面导致我使用该库的项目中打包出现了报错,但是我使用真机编译运行的时候没有问题

    原因就是因为我的项目中默认支持 armv7s,armv7,而在 Openssl-iOS 编译的时候静态库没有带这两个
    该设置项在 TARGET -> Build Settings -> Architectures -> Valid Architectures 中


    修改 build-libssl.h 中的 DEFAULTTARGETS

    DEFAULTTARGETS="ios-cross-armv7s ios-cross-armv7 ios-sim-cross-x86_64 ios64-cross-arm64 ios64-cross-arm64e tvos-sim-cross-x86_64 tvos64-cross-arm64"

    自己可根据需要进行增删

    armv7 和 armv7s 是属于 32位 CPU, iOS 系统版本中,32 位仅支持到 iOS 10,所以如果使用 armv7 和 armv7s,需要同时修改 IOS_MIN_SDK_VERSION

    IOS_MIN_SDK_VERSION="10.0" // 10.0 以下都可以

    编译过程中可能会报错,Openssl-iOS 会输出对应 .log 日志,可以根据对应问题进行修改

    通过 Openssl-iOS 获取证书时间

    通过上面获取到的 SecCertificateRef 初始化 NSData,然后进行获取证书信息

    初始化成 X509 还可以获取其他证书信息

    NSData *data = CFBridgingRelease(SecCertificateCopyData(certRef));
    const unsigned char *certificateDataBytes = [data bytes];
    X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [data length]);
    ASN1_TIME *not_before = X509_getm_notBefore(certificateX509);
    ASN1_TIME *not_after = X509_getm_notAfter(certificateX509);
    /// 证书过期时间
    char not_after_str[DATE_LEN];
    convert_ASN1TIME(not_after, not_after_str, DATE_LEN);
    
    /// 证书创建时间
    char not_before_str[DATE_LEN];
    convert_ASN1TIME(not_before, not_before_str, DATE_LEN);
    
    // 将时间转换为时间戳
    NSMutableString *beforeString = [[NSMutableString alloc]initWithFormat:@"%s", not_before_str];
    NSMutableString *afterString = [[NSMutableString alloc]initWithFormat:@"%s", not_after_str];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"MM dd  hh:mm:ss yyyy zzz"];
    NSDate *afterDate = [formatter dateFromString:afterString];
    NSTimeInterval afterTimeStamp = afterDate.timeIntervalSince1970;
    

    convert_ASN1TIME 用于将 ASN1_Time 转换为 char[]

    int convert_ASN1TIME(ASN1_TIME *t, char* buf, size_t len)
    {
        int rc;
        BIO *b = BIO_new(BIO_s_mem());
        rc = ASN1_TIME_print(b, t);
        if (rc <= 0) {
            BIO_free(b);
            return EXIT_FAILURE;
        }
        rc = BIO_gets(b, buf, len);
        if (rc <= 0) {
            BIO_free(b);
            return EXIT_FAILURE;
        }
        BIO_free(b);
        return EXIT_SUCCESS;
    }
    

    Security API 中获取证书内容

    相关文章

      网友评论

          本文标题:Get certificate infomation

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