English 中文(简体)
SecCertifate 参考:如何获得证书信息?
原标题:SecCertificateRef: How to get the certificate information?

我有证书(SecCertificateRef),我可以检查它是否有效,我可以使用SecCertificateCopy Subjectmmary取得“摘要”。

“消费”究竟是什么? 我不理解“在 Apple果文件中包含一份人类可读的证书内容摘要”这一术语。 我认为,它们意味着证书中的“CN”正确?

Is there any method to get the clear X509-information out of SecCertificateRef? Does a cast to a keychain-object help?

我想有这样的内容,我尤其注重“CN”与我为避免人为攻击而提交的URL相比较。 (是否有任何更好的想法?)

这是我想要做到的:

Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=XY, ST=Austria, L=Graz, O=TrustMe Ltd, OU=Certificate Authority, CN=CA/[email protected]
        Validity
            Not Before: Oct 29 17:39:10 2000 GMT
            Not After : Oct 29 17:39:10 2001 GMT
        Subject: C=DE, ST=Austria, L=Vienna, O=Home, OU=Web Lab, CN=anywhere.com/[email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:c4:40:4c:6e:14:1b:61:36:84:24:b2:61:c0:b5:
                    d7:e4:7a:a5:4b:94:ef:d9:5e:43:7f:c1:64:80:fd:
                    9f:50:41:6b:70:73:80:48:90:f3:58:bf:f0:4c:b9:
                    90:32:81:59:18:16:3f:19:f4:5f:11:68:36:85:f6:
                    1c:a9:af:fa:a9:a8:7b:44:85:79:b5:f1:20:d3:25:
                    7d:1c:de:68:15:0c:b6:bc:59:46:0a:d8:99:4e:07:
                    50:0a:5d:83:61:d4:db:c9:7d:c3:2e:eb:0a:8f:62:
                    8f:7e:00:e1:37:67:3f:36:d5:04:38:44:44:77:e9:
                    f0:b4:95:f5:f9:34:9f:f8:43
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                email:[email protected]
            Netscape Comment:
                mod_ssl generated test server certificate
            Netscape Cert Type:
                SSL Server
    Signature Algorithm: md5WithRSAEncryption
        12:ed:f7:b3:5e:a0:93:3f:a0:1d:60:cb:47:19:7d:15:59:9b:
        3b:2c:a8:a3:6a:03:43:d0:85:d3:86:86:2f:e3:aa:79:39:e7:
        82:20:ed:f4:11:85:a3:41:5e:5c:8d:36:a2:71:b6:6a:08:f9:
        cc:1e:da:c4:78:05:75:8f:9b:10:f0:15:f0:9e:67:a0:4e:a1:
        4d:3f:16:4c:9b:19:56:6a:f2:af:89:54:52:4a:06:34:42:0d:
        d5:40:25:6b:b0:c0:a2:03:18:cd:d1:07:20:b6:e5:c5:1e:21:
        44:e7:c5:09:d2:d5:94:9d:6c:13:07:2f:3b:7c:4c:64:90:bf:
        ff:8e
最佳回答

我不得不等待对oun的回答,因此我找到了解决办法。 正如其他人所说的那样,安全。 框架没有给你提供获取这一信息的途径,因此,你需要请开放式特别安全局向你们提供证书数据:

#import <openssl/x509.h>

// ...

NSData *certificateData = (NSData *) SecCertificateCopyData(certificate);

const unsigned char *certificateDataBytes = (const unsigned char *)[certificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [certificateData length]);

NSString *issuer = CertificateGetIssuerName(certificateX509);
NSDate *expiryDate = CertificateGetExpiryDate(certificateX509);

www.un.org/Depts/DGACM/index_spanish.htm

static NSString * CertificateGetIssuerName(X509 *certificateX509)
{
    NSString *issuer = nil;
    if (certificateX509 != NULL) {
        X509_NAME *issuerX509Name = X509_get_issuer_name(certificateX509);

        if (issuerX509Name != NULL) {
            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];
                }
            }
        }
    }

    return issuer;
}

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

我实际上只需要发行人的组织名称和截止日期,这样,所有法典都包含在下文。 但是,根据这一点,你应当能够读到<条码>x509.h头版。

<><>Edit>:

这里是如何获得证书的。 我没有错处理,等等。 例如,请查看<代码>trustResult,err等。

NSURLAuthenticationChallenge *challenge;
SecTrustResultType trustResult;
SecTrustRef trust = challenge.protectionSpace.serverTrust;
OSStatus err = SecTrustEvaluate(trust, &trustResult);
SecCertificateRef certificate = SecGetLeafCertificate(trust); // See Apple docs for implementation of SecGetLeafCertificate
问题回答

更公正地利用SecCertificateCopyCommonName,使CN能够与你所需要的东道名称进行比较。

If for some reason you want to do this without OpenSSL one can use the apple extraction keys. The first one will extract (just) the Subject and Issuer (there are more kSecOIDX509 s for most other things, like expiry dates) and pass them for printing.

     +(NSString*)stringFromCerificateWithLongwindedDescription:(SecCertificateRef) certificateRef {
   if (certificateRef == NULL)
       return @"";

    CFStringRef commonNameRef;
    OSStatus status;
    if ((status=SecCertificateCopyCommonName(certificateRef, &commonNameRef)) != errSecSuccess) {
        NSLog(@"Could not extract name from cert: %@", 
              SecCopyErrorMessageString(status, NULL));
        return @"Unreadable cert";            
    };

    CFStringRef summaryRef = SecCertificateCopySubjectSummary(certificateRef);
    if (summaryRef == NULL)
        summaryRef = CFRetain(commonNameRef);

    CFErrorRef error;

    const void *keys[] = { kSecOIDX509V1SubjectName, kSecOIDX509V1IssuerName };
    const void *labels[] = { "Subject", "Issuer" };
    CFArrayRef keySelection = CFArrayCreate(NULL, keys , sizeof(keys)/sizeof(keys[0]), &kCFTypeArrayCallBacks);

    CFDictionaryRef vals = SecCertificateCopyValues(certificateRef, keySelection,&error);
    NSMutableString *longDesc = [[NSMutableString alloc] init];

    for(int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
        CFDictionaryRef dict = CFDictionaryGetValue(vals, keys[i]);
        CFArrayRef values = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
        if (values == NULL)
            continue;
        [longDesc appendFormat:@"%s:%@

", labels[i], [NSString stringFromDNwithSubjectName:values]];
    }

    CFRelease(vals);
    CFRelease(summaryRef);
    CFRelease(commonNameRef);

    return longDesc;
}

The second function is an over the top try to extract anything you can get your mittens on:

+(NSString *)stringFromDNwithSubjectName:(CFArrayRef)array {
    NSMutableString * out = [[NSMutableString alloc] init];
    const void *keys[] = { kSecOIDCommonName, kSecOIDEmailAddress, kSecOIDOrganizationalUnitName, kSecOIDOrganizationName, kSecOIDLocalityName, kSecOIDStateProvinceName, kSecOIDCountryName };
    const void *labels[] = { "CN", "E", "OU", "O", "L", "S", "C", "E" };

    for(int i = 0; i < NVOID(keys);  i++) {
        for (CFIndex n = 0 ; n < CFArrayGetCount(array); n++) {
            CFDictionaryRef dict = CFArrayGetValueAtIndex(array, n);
            if (CFGetTypeID(dict) != CFDictionaryGetTypeID())
                continue;
            CFTypeRef dictkey = CFDictionaryGetValue(dict, kSecPropertyKeyLabel);
            if (!CFEqual(dictkey, keys[i]))
                continue;
            CFStringRef str = (CFStringRef) CFDictionaryGetValue(dict, kSecPropertyKeyValue);
            [out appendFormat:@"%s=%@ ", labels[i], (__bridge NSString*)str];
        }
    }
    return [NSString stringWithString:out];
}

我不相信公众有这样的信息。 关于OSX,有多个<代码>SecCertificate的APIC,以收集X.509信息。

FYI, assuming you re using HTTPS, checking the CN yourself is mostly useless, because the OS already checks to make sure the name is present in the cert. You re more likely to want to check the public key (for key pinning), which you can get from the trust object without touching the certificate directly.

如果公用钥匙与先前的钥匙相匹配,那么该场址要么是合法化的,要么有人彻底破坏该场址。





相关问题
List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code: - (...

iPhone NSUserDefaults persistance difficulty

In my app i have a bunch of data i store in the NSUserdefaults. This information consists of an NSObject (Object1) with NSStrings and NSNumbers and also 2 instances of yet another object (Object2). ...

Writing a masked image to disk as a PNG file

Basically I m downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them. I m using the masking code everyone seems to point at which can be found ...

Resize UIImage with aspect ratio?

I m using this code to resize an image on the iPhone: CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0); UIGraphicsBeginImageContext(screenRect.size); [value drawInRect:screenRect blendMode:...

Allowing interaction with a UIView under another UIView

Is there a simple way of allowing interaction with a button in a UIView that lies under another UIView - where there are no actual objects from the top UIView on top of the button? For instance, ...

热门标签