2015-10-16 9 views
11

मेरी स्थिर पुस्तकालय में मेरे पास लाइसेंस फ़ाइल है। जो मैं सुनिश्चित करना चाहता हूं कि स्वयं द्वारा उत्पन्न किया गया है (और बदला नहीं गया है)। तो विचार मैंने जो पढ़ा है उससे आरएसए हस्ताक्षर का उपयोग करना था।आरएसए हस्ताक्षर आईओएस

मैं इंटरनेट पर देखा है और यह है कि क्या मैं के साथ आया है:

प्रथम सूचना मैं here पाया साथ निजी कुंजी और आत्म हस्ताक्षरित प्रमाणपत्र जनरेट कर रहा है।

// Generate private key 
openssl genrsa -out private_key.pem 2048 -sha256 

// Generate certificate request 
openssl req -new -key private_key.pem -out certificate_request.pem -sha256 

// Generate public certificate 
openssl x509 -req -days 2000 -in certificate_request.pem -signkey private_key.pem -out certificate.pem -sha256 

// Convert it to cer format so iOS kan work with it 
openssl x509 -outform der -in certificate.pem -out certificate.cer -sha256 

उसके बाद, मैं एक लाइसेंस फ़ाइल (सामग्री के रूप में एक तारीख और एप्लिकेशन पहचानकर्ता के साथ) बना सकते हैं और जानकारी के आधार पर तो जैसे उस फ़ाइल के लिए एक हस्ताक्षर उत्पन्न पाया here:

// Store the sha256 of the licence in a file 
openssl dgst -sha256 licence.txt > hash 

// And generate a signature file for that hash with the private key generated earlier 
openssl rsautl -sign -inkey private_key.pem -keyform PEM -in hash > signature.sig 

कौन सा मैं लगता है कि सब ठीक काम करता है। मुझे कोई त्रुटि नहीं मिलती है और चाबियाँ और प्रमाणपत्र और अन्य फाइलें अपेक्षित होती हैं।

अगला मैं अपने आवेदन में certificate.cer, signature.sig और license.txt कॉपी करता हूं।

अब मैं यह जांचना चाहता हूं कि हस्ताक्षर पर हस्ताक्षर किए गए हैं और license.txt के लिए मान्य है या नहीं। मैं यह काफी मुश्किल किसी भी अच्छे उदाहरण खोजने के लिए मिल गया है, लेकिन यह है कि क्या मैं वर्तमान में है:

Seucyrity.Framework मुझे पता चला एक SecKeyRef का उपयोग करता RSA कुंजी/प्रमाण पत्र के संदर्भ के लिए और SecKeyRawVerify एक हस्ताक्षर सत्यापित करने के।

मेरे पास फ़ाइल से सार्वजनिक कुंजी लोड करने के लिए निम्न विधि है।

- (SecKeyRef)publicKeyFromFile:(NSString *) path 
{ 
    NSData *myCertData = [[NSFileManager defaultManager] contentsAtPath:path]; 
    CFDataRef myCertDataRef = (__bridge CFDataRef) myCertData; 

    SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorDefault, myCertDataRef); 
    CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &cert, 1, NULL); 
    SecPolicyRef policy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    SecTrustCreateWithCertificates(certs, policy, &trust); 
    SecTrustResultType trustResult; 
    SecTrustEvaluate(trust, &trustResult); 
    SecKeyRef pub_key_leaf = SecTrustCopyPublicKey(trust); 

    if (trustResult == kSecTrustResultRecoverableTrustFailure) 
    { 
     NSLog(@"I think this is the problem"); 
    } 
    return pub_key_leaf; 
} 

कौन सा this पर आधारित है अतः पोस्ट।

// Get the licence data 
NSString *licencePath = [[NSBundle mainBundle] pathForResource:@"licence" ofType:@"txt"]; 
NSData *data = [[NSFileManager defaultManager] contentsAtPath:licencePath]; 

// Get the signature data 
NSString *signaturePath = [[NSBundle mainBundle] pathForResource:@"signature" ofType:@"sig"]; 
NSData *signature = [[NSFileManager defaultManager] contentsAtPath:signaturePath]; 

// Get the public key 
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
SecKeyRef publicKey = [self publicKeyFromFile:publicKeyPath]; 

// Check if the signature is valid with this public key for this data 
BOOL result = PKCSVerifyBytesSHA256withRSA(data, signature, publicKey); 

if (result) 
{ 
    NSLog(@"Alright All good!"); 
} 
else 
{ 
    NSLog(@"Something went wrong!"); 
} 

वर्तमान में यह हमेशा कहते हैं:

हस्ताक्षर सत्यापन के लिए मैं निम्नलिखित समारोह

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey); 
    const void* signedHashBytes = [signature bytes]; 

    size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH; 
    uint8_t* hashBytes = malloc(hashBytesSize); 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { 
     return nil; 
    } 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1SHA256, 
             hashBytes, 
             hashBytesSize, 
             signedHashBytes, 
             signedHashBytesSize); 

    return status == errSecSuccess; 
} 

कौन से here

लिया जाता है अपने प्रोजेक्ट में मैं कोड तो जैसे फोन मिला : "कुछ गलत हो गया!" हालांकि मुझे यकीन नहीं है कि क्या। मुझे पता चला कि सार्वजनिक कुंजी लाने वाली विधि में विश्वास परिणाम kSecTrustResultRecoverableTrustFailure है जो मुझे लगता है कि समस्या है। Apple documentation में मैंने पाया कि एक प्रमाणपत्र का परिणाम हो सकता है जो समाप्त हो चुका है। हालांकि यह मामला यहां प्रतीत नहीं होता है। लेकिन शायद मेरे प्रमाण पत्र को उत्पन्न करने के तरीके में कुछ गड़बड़ है?

मेरा प्रश्न नीचे उबलता है, मैं क्या गलत कर रहा हूं, और मैं इसे कैसे ठीक कर सकता हूं? मुझे इस काफी स्पैस और पढ़ने के लिए कड़ी मेहनत पर प्रलेखन मिलता है।

मेरे पास uploaded जेनरेट किए गए प्रमाणपत्र और यहां संदर्भित कोड के साथ एक आईओएस प्रोजेक्ट है। शायद यह काम में आ सकता है।

+1

आप लिस्टिंग 3 को देखें, तो आपके द्वारा इंगित दस्तावेज में 5, आप इसे "ऑलस्टैटस बिट्स" सूचीबद्ध करेंगे। क्या आप समझ सकते हैं कि जब आप उस त्रुटि का सामना करते हैं तो स्थिति बिट्स क्या होती हैं? –

+0

हाय, जब मैं उस कोड को शामिल करने का प्रयास करता हूं तो पहली त्रुटियों में से एक यह है कि 'AllStatusBits' का' CSSM_TP_APPLE_CERT_STATUS' प्रकार अज्ञात है और मुझे उस प्रकार को प्राप्त करने के लिए एक कार्यरत हेडर फ़ाइल नहीं मिल रही है। इंटरनेट पर मैंने पाया कि यह '# आयात <सुरक्षा/cssmapple.h> हो सकता है, लेकिन वह आईओएस पर मौजूद नहीं है (अब और?)। - मैंने [अपलोड किया गया] (http://up.indev.nl/RTR4y0Ou0L.zip) कोड और प्रमाणपत्र के साथ मेरी परियोजना, शायद यह मदद करता है। – Matthijn

+0

हां, मैंने अभी दो बार चेक किया है, लेकिन मैंने [पहले से ही] (http://up.indev.nl/C5OHOFziPO.png) सुरक्षा ढांचे को जोड़ा है। हो सकता है कि आईओएस संस्करण में कहीं और स्थानांतरित हो गया हो? – Matthijn

उत्तर

8

समस्या हस्ताक्षर फ़ाइल बनाने के तरीके पर झूठ बोल रही है; उसी चरण के बाद मैं बाइनरी समतुल्य signature.sig फ़ाइल का उत्पादन करने में सक्षम था।

hash फाइल के अंदर देख कर हम openssl कुछ उपसर्ग जोड़ने (और हेक्स एनकोड हैश) देख सकते हैं:

$ cat hash 
SHA256(licence.txt)= 652b23d424dd7106b66f14c49bac5013c74724c055bc2711521a1ddf23441724 

तो signature.sig कि पर आधारित है और license.txt

पर नहीं अपने नमूना का उपयोग करके और साथ हस्ताक्षर किए जाने फ़ाइल बनाने:

openssl dgst -sha256 -sign certificates/private_key.pem licence.txt > signature.sig 

हैशिंग & हस्ताक्षर करने काएं पी सही हो जाता है, और नमूना आउटपुट: Alright All good!


मेरी फाइल के अंतिम राज्य, अगर पुनश्च में

- (SecKeyRef)publicKeyFromFile:(NSString *) path 
{ 
    NSData * certificateData = [[NSFileManager defaultManager] contentsAtPath:path]; 
    SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData); 
    SecPolicyRef secPolicy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    SecTrustCreateWithCertificates(certificateFromFile, secPolicy, &trust); 
    SecTrustResultType resultType; 
    SecTrustEvaluate(trust, &resultType); 
    SecKeyRef publicKey = SecTrustCopyPublicKey(trust); 
    return publicKey; 
} 

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], digest)) 
     return NO; 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1SHA256, 
             digest, 
             CC_SHA256_DIGEST_LENGTH, 
             [signature bytes], 
             [signature length]); 

    return status == errSecSuccess; 
} 

: malloc रिसाव


संपादित किया गया था:

अपनी वर्तमान signature.sig फ़ाइल को काम करने के लिए I-i रों, आप openssl (जोड़ने उपसर्ग, हेक्स-हैश, और एक नई पंक्ति \n) के रूप में एक ही चरण का उत्पादन किया है, तो kSecPaddingPKCS1 साथ SecKeyRawVerify को यह डेटा पास और नहीं kSecPaddingPKCS1SHA256:

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], digest)) 
     return NO; 

    NSMutableString *hashFile = [NSMutableString stringWithFormat:@"SHA256(licence.txt)= "]; 
    for (NSUInteger index = 0; index < sizeof(digest); ++index) 
     [hashFile appendFormat:@"%02x", digest[index]]; 

    [hashFile appendString:@"\n"]; 
    NSData *hashFileData = [hashFile dataUsingEncoding:NSNonLossyASCIIStringEncoding]; 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1, 
             [hashFileData bytes], 
             [hashFileData length], 
             [signature bytes], 
             [signature length]); 

    return status == errSecSuccess; 
} 
+0

आप अभी भी 'SecTrustEvaluate' में 'kSecTrustResultRecoverableTrustFailure' प्राप्त करते हैं, लेकिन हाँ यह हस्ताक्षर सफलतापूर्वक सत्यापित कर रहा है – Lefteris

+0

मुझे लगता है कि kSecTrustResultRecoverableTrustFailure समस्या यह है कि आपका प्रमाणपत्र स्वयं हस्ताक्षरित है, यदि आप चाहते हैं कि यह सही ट्रस्ट श्रृंखला में सफल हो वैध है; आपको एक (ऐप्पल) भरोसेमंद प्राधिकारी से प्रमाण पत्र प्राप्त करना होगा। (ver * s * gn या like) – blld

+0

या मेजबान आईओएस डिवाइस पर अपना प्रमाणपत्र इंस्टॉल करें (जो एक विकल्प प्रतीत नहीं होता है) – blld

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