2012-01-13 13 views
25

मेरे पास एक प्रमाणपत्र (SecCertificateRef) है, मैं जांच सकता हूं कि यह मान्य है या नहीं और मैं SecCertificateCopySubjectSummary का उपयोग करके "सारांश" निकाल सकता हूं।SecCertificateRef: प्रमाणपत्र जानकारी कैसे प्राप्त करें?

"सारांश" वास्तव में क्या है? मैं "ए स्ट्रिंग" शब्द को समझ नहीं पा रहा हूं जिसमें प्रमाणपत्र की सामग्री का मानव-पठनीय सारांश शामिल है। " ऐप्पल दस्तावेज में। मुझे लगता है, वे प्रमाणपत्र में "सीएन" का मतलब है, सही?

वहाँ SecCertificateRef से बाहर स्पष्ट X509-जानकारी पाने के लिए कोई भी तरीका है? क्या एक कीचेन-ऑब्जेक्ट में एक कास्ट मदद करता है?

मैं कुछ इस तरह करना चाहते हैं और मैं विशेष रूप से यूआरएल मैं मैन-इन-द-मिडल हमलों से बचने के लिए प्रस्तुत के साथ तुलना करना "सीएन" पर ध्यान केंद्रित कर रहा हूँ। (या किसी भी बेहतर विचार?)

है यही कारण है कि मैं करना चाहता हूँ:

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 

उत्तर

23

मैं इनाम के लिए एक उत्तर के लिए इंतज़ार नहीं कर सकता, तो मैं एक समाधान अपने आप को मिल गया। के रूप में अन्य लोगों ने कहा, Security.framework आप इस जानकारी को प्राप्त करने के लिए एक रास्ता दे नहीं करता है, तो आप आप के लिए प्रमाण पत्र डेटा पार्स करने के लिए OpenSSL पूछना चाहिए:

#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); 

कहाँ CertificateGetIssuerName और CertificateGetExpiryDate इस प्रकार हैं:

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:
       //             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 हेडर फ़ाइल पढ़कर बाकी को समझने में सक्षम होना चाहिए।

संपादित करें:

यहाँ कैसे प्रमाण पत्र प्राप्त करने के लिए है। मैंने कोई त्रुटि प्रबंधन नहीं किया है, आदि। उदाहरण के लिए, आप 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 
+0

क्या आप कृपया यह स्पष्ट कर सकते हैं कि X509 ऑब्जेक्ट बनाने के लिए आपको NSData कैसे आवश्यक था? "प्रमाण पत्र" क्या है? एनएसडीटा * प्रमाणपत्र डेटा = (एनएसडीएटा *) SecCertificateCopyData (प्रमाणपत्र); – Maggie

+0

ओह, आप इसे चुनौती से प्राप्त कर सकते हैं: NSURLAuthenticationChallenge * चुनौती; SecTrustResultType TrustResult; SecTrustRef ट्रस्ट = challenge.protectionSpace.serverTrust; ओएसएसटैटस गलती = SecTrustEvaluate (विश्वास, और trustResult); SecCertiicateRef प्रमाणपत्र = SecGetLeafCertificate (ट्रस्ट); // SecGetLeafCertificate –

+0

उग के कार्यान्वयन के लिए ऐप्पल दस्तावेज़ देखें, यह बदसूरत है। मुझे इसे मूल उत्तर में रखने दें। –

2

मैं नहीं मानता iOS पर यह करने के लिए एक सार्वजनिक एपीआई है। ओएसएक्स पर X.50 9 जानकारी को अलग करने के लिए SecCertificate एपीआई हैं।

0

बेहतर बस SecCertificateCopyCommonName का उपयोग अपने आवश्यक होस्ट नाम से तुलना करने के सीएन मिलता है।

+1

यह केवल ओएसएक्स है, सवाल आईओएस के बारे में पूछ रहा है। –

+0

आप सही हैं, इसे विस्तार से जांच नहीं किया। – Allen

+1

निश्चित रूप से, एक बहुत ही सीमित अर्थ में। SecCertificate.h में आईओएस पर लगभग 4 तरीके उपलब्ध हैं। –

2

आप थे सही माइकल, आईओएस आप एक X.509 प्रमाणपत्र पर एक पूर्ण काम करने के लिए एपीआई नहीं देंगे। शुक्र है कि यह आपको वास्तविक (ASN.1) एन्कोडेड प्रमाणपत्र डेटा तक पहुंच प्रदान करेगा। वहां से आप अपना खुद का डिकोडिंग (बहुत मज़ेदार नहीं) कर सकते हैं या इसे मौजूदा पुस्तकालय में भेज सकते हैं, जैसे आपने OpenSSL के साथ किया था।

यहाँ मेरी संस्करण .NET फ़्रेमवर्क का उपयोग करता है है। इसका मतलब MonoTouch डेवलपर्स (और मोनोमैक डेवलपर्स भी) द्वारा उपयोग किया जाना है, जिन्हें SecCertificateRef के साथ उनके अनुप्रयोगों में इंटरऑपरेट करने की आवश्यकता है।

public void Show (SecCertificate sc) 
{ 
    // get the SecCertificate "raw", i.e. ASN.1 encoded, data 
    byte[] data = sc.DerData.ToArray<byte>(); 
    // the build the managed X509Certificate2 from it 
    X509Certificate2 cer = new X509Certificate2 (data); 
    // to get all properties/methods available in .NET (pretty exhaustive) 
    Console.WriteLine ("SubjectName: {0}", cer.Subject); 
    Console.WriteLine ("IssuerName: {0}", cer.Issuer); 
    Console.WriteLine ("NotBefore: {0}", cer.NotBefore); 
    Console.WriteLine ("NotAfter: {0}", cer.NotAfter); 
    Console.WriteLine ("SerialNumber: {0}", cer.SerialNumber); 
    // ... 
} 
+1

(हैप्पी श्वास ...) आईओएस विकास के लिए सी # का उपयोग करके यह सुंदर नहीं है! मैंने दिसंबर 2014 में ज़ैमरिन का प्रयास किया था, लेकिन हालांकि यह सी # का उपयोग करने के लिए शानदार है, लेकिन मुझे बस मैक के लिए ज़ैमरिन स्टूडियो भी मेरी कंपनी की सिफारिश करने के लिए अस्थिर पाया गया। इस कोड को देखते हुए, मुझे इसे याद करना शुरू हो रहा है ... –

1

यदि किसी कारण से आप ओपनएसएसएल के बिना ऐसा करना चाहते हैं तो सेब निष्कर्षण कुंजी का उपयोग कर सकते हैं। पहला (विषय) विषय और जारीकर्ता निकालेगा (अधिकतर चीजों के लिए अधिक KSecOIDX509 है, जैसे समाप्ति तिथियां) और उन्हें प्रिंटिंग के लिए पास करें।

 +(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:%@\n\n", labels[i], [NSString stringFromDNwithSubjectName:values]]; 
    } 

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

    return longDesc; 
} 

दूसरा समारोह शीर्ष कोशिश पर एक कुछ भी निकालने आप अपने दस्ताने प्राप्त कर सकते हैं के लिए है: FYI करें

+(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]; 
} 
+0

SecCertificateCopyValues ​​आईओएस पर उपलब्ध है? – Freedom

+4

मुझे डर है कि यह केवल ओएसएक्स – anavarroma

+3

में उपलब्ध है यह केवल ओएस एक्स पर लागू होता है, इसलिए यह सवाल का जवाब नहीं दे रहा है। – Sulthan

0

, आप HTTPS का उपयोग कर रहे संभालने, सीएन खुद के ज्यादातर बेकार है की जाँच, क्योंकि ओएस पहले से ही यह सुनिश्चित करने के लिए जांच करता है कि नाम प्रमाण में मौजूद है। आप सार्वजनिक कुंजी (कुंजी पिनिंग के लिए) की जांच करना चाहते हैं, जिसे आप सीधे प्रमाण पत्र को छूए बिना ट्रस्ट ऑब्जेक्ट से प्राप्त कर सकते हैं।

यदि सार्वजनिक कुंजी पिछली कुंजी से मेल खाती है, तो या तो साइट कानूनी है या किसी ने साइट से पूरी तरह से समझौता किया है।

संबंधित मुद्दे