日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS 证书、密钥及信任服务

發(fā)布時(shí)間:2023/12/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS 证书、密钥及信任服务 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

iOS?證書、密鑰及信任服務(wù)

——翻譯自Apple Reference《Certificate,Key,and Trust Services Programming Guide》

?

本章描述并演示了如何使用證書、密鑰和信任服務(wù)去導(dǎo)入一個(gè)indentity,評估證書是否可信,判斷證書失效的原因,以及失效證書的恢復(fù)。

本章按如下順序分別演示了:

導(dǎo)入一個(gè)?identity.

從導(dǎo)入的數(shù)據(jù)中獲得證書.

獲得用于證書評估的策略.

校驗(yàn)證書,根據(jù)指定策略評估證書是否可信.

測試證書中的可恢復(fù)錯(cuò)誤.

判斷證書是否過期.

改變評估條件,忽略過期證書.

重新評估證書.

??“?第2章,Certificate,Key,and Trust Services Concepts”,介紹了證書,密鑰和信任服務(wù)的概念和術(shù)語。關(guān)于證書,密鑰和信任服務(wù)的細(xì)節(jié)內(nèi)容,請參考Certificate,Key,and Trust Services Reference.

從一個(gè).p12文件中提取、評估Identity

?

如果你需要在iOS設(shè)備上使用加密過的identity(一個(gè)密鑰及其關(guān)聯(lián)的證書)進(jìn)行客戶端認(rèn)證,例如——你可以把PKCS#12數(shù)據(jù)以受密碼保護(hù)的文件的方式安全地傳輸?shù)竭@個(gè)設(shè)備上。本節(jié)顯示如何從PKCS#12數(shù)據(jù)中提取identity和trust objects(可信任對象),并評估其可信度。

列表?2-1 顯示了用SecPKCS12Import函數(shù)從.p12文件中提取identity和可信任對象,以及評估其可信度。

列表?2-2 顯示如何從identity中獲取證書并顯示證書信息。每個(gè)列表后都對代碼進(jìn)行了解釋。

在編譯這段代碼時(shí),請確認(rèn)在Xcode工程中加入了Security.framework。

列表???2-1??從PKCS#12數(shù)據(jù)中提取identity和trust對象

??#import <UIKit/UIKit.h>

#import <Security/Security.h>

#import <CoreFoundation/CoreFoundation.h>

?

????NSString *thePath = [[NSBundle mainBundle]

????????????????????????????pathForResource:@"MyIdentity" ofType:@"p12"];

????NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];

????CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;?????????????// 1

?

?????OSStatus status = noErr;

????SecIdentityRef myIdentity;

????SecTrustRef myTrust;

????status = extractIdentityAndTrust(

??????????????????????????????????????inPKCS12Data,

?????????????????????????????????????&myIdentity,

?????????????????????????????????????&myTrust);?????????????????// 2

????if status != 0 ...??//Do some error checking here

?

SecTrustResultType trustResult;

?

?????if (status == noErr) {??????????????????????????????????????// 3

????????status = SecTrustEvaluate(myTrust, &trustResult);

}

?

?

...?????????????????????????????????????????????????????????????// 4

????if (trustResult == kSecTrustResultRecoverableTrustFailure) {

????????...;

????}

?

OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data,????????// 5

?????????????????????????????????SecIdentityRef *outIdentity,

?????????????????????????????????SecTrustRef *outTrust)

{

????OSStatus securityError = errSecSuccess;

?

?

????CFStringRef password = CFSTR("Password");

????const void *keys[] =???{ kSecImportExportPassphrase };

????const void *values[] = { password };

????CFDictionaryRef optionsDictionary = CFDictionaryCreate(

???????????????????????????????????????????????????NULL, keys,

??????????????????????????????????????????????????values, 1,

??????????????????????????????????????????????????NULL, NULL);??// 6

?

?

????CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

????securityError = SecPKCS12Import(inPKCS12Data,

????????????????????????????????????optionsDictionary,

????????????????????????????????????&items);????????????????????// 7

?

?

????//

????if (securityError == 0) {???????????????????????????????????// 8

????????CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);

????????const void *tempIdentity = NULL;

????????tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,

???????????????????????????????????????????????????????kSecImportItemIdentity);

????????*outIdentity = (SecIdentityRef)tempIdentity;

????????const void *tempTrust = NULL;

????????tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);

????????*outTrust = (SecTrustRef)tempTrust;

????}

?

????if (optionsDictionary)

????????CFRelease(optionsDictionary);????????????????????????????// 9

?????[PKCS12Data release];

在這段代碼中?:

檢索PKCS#12文件并獲得數(shù)據(jù)。本例中,該文件位于application bundle中。你也可以通過網(wǎng)絡(luò)方式把文件傳輸給你的應(yīng)用程序。

調(diào)用該函數(shù)獲得identity和trust對象(見步驟5)。

評估證書。這里的信任對象(trust object),包括信任策略和其他用于判斷證書是否可信的信息,都已經(jīng)含在了PKCS數(shù)據(jù)中。要單獨(dú)評估一個(gè)證書是否可信,見列表 2-6。

處理信任結(jié)果。如果信任結(jié)果是kSecTrustResultInvalid,kSecTrustResultDeny,kSecTrustResultFatalTrustFailure,你無法進(jìn)行處理。如果評估結(jié)果是kSecTrustResultRecoverableTrustFailure,你可以從信任失敗中恢復(fù)。參見“從信任失敗中恢復(fù)”。

第2步中調(diào)用的函數(shù)的具體實(shí)現(xiàn)。

構(gòu)造包含了密碼的dictionary,用于傳遞給SecPKCS12Import函數(shù)。注意這里使用的是core foundation中的CFDictionaryRef,與NSDictionary完全等價(jià)。列表 2-9 則是一個(gè)使用NSDictionary的例子。

從PKCS#12數(shù)據(jù)中提取證書、密鑰和trust并將其放到數(shù)組中。

從數(shù)組中取出第1個(gè)dictionary,并從dictionary中取出identity和trust。SecPKCS12Import函數(shù)將PKCS數(shù)據(jù)中的每一個(gè)條目返回為一個(gè)dictionary。本例中,identity被提取到數(shù)組的第1個(gè)元素。

釋放dictionary和PKCS12Data,他們不再被使用。

以下列表顯示如何從identity中獲取證書以及顯示證書信息。編譯本段代碼前請確保在工程中導(dǎo)入了Security.framework。

列表???2-2??顯示證書信息

????//?從identity獲取證書?.

????SecCertificateRef myReturnedCertificate = NULL;

????status = SecIdentityCopyCertificate (myReturnedIdentity,

??????????????????????????????????????&myReturnedCertificate);??// 1

?

????CFStringRef certSummary = SecCertificateCopySubjectSummary

??????????????????????????????????????(myReturnedCertificate);??// 2

?

????NSString* summaryString = [[NSString alloc]

???????????????????????initWithString:(NSString*)certSummary];??// 3

?

????//Display the string

...

?????[summaryString release];???????????????????????????????????// 4

在這段代碼中?:

從identity中提取證書。

從證書中獲取summary摘要信息。

string?轉(zhuǎn)換為NSString。

釋放NSString。

?

獲取和使用持久化的鑰匙串

?

當(dāng)你在鑰匙串中添加或查找一個(gè)條目時(shí),你需要有一個(gè)持久化的引用。因?yàn)槌志没媚鼙WC在程序從啟動到能寫入磁盤這段時(shí)間內(nèi),始終可用。當(dāng)需要反復(fù)在鑰匙串中查找條目時(shí),使用持久化引用更加容易。以下代碼演示如何獲取一個(gè)?identity?的持久化引用。

列表???2-3??獲取identity的持久化引用

CFDataRef persistentRefForIdentity(SecIdentityRef identity)

{

????OSStatus status;

?

????CFTypeRef??identity_handle = NULL;

????const void *keys[] =???{ kSecReturnPersistentRef, kSecValueRef };

????const void *values[] = { kCFBooleanTrue,??????????identity };

????CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values,

??????????????????????????????????????????????2, NULL, NULL);

????status = SecItemAdd(dict, &persistent_ref);

?

????if (dict)

????????CFRelease(dict);

?

????return (CFDataRef)persistent_ref;

}

下面演示使用持久化引用從鑰匙串中檢索identity對象。

列表?2-4??用持久化引用獲取identity對象

SecIdentityRef identityForPersistentRef(CFDataRef persistent_ref)

{

????CFTypeRef???identity_ref?????= NULL;

????const void *keys[] =???{ kSecReturnRef,??kSecValuePersistentRef };

????const void *values[] = { kCFBooleanTrue, persistent_ref };

????CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values,

??????????????????????????????????????????????2, NULL, NULL);

????SecItemCopyMatching(dict, &identity_ref);

?

????if (dict)

????????CFRelease(dict);

?

????return (SecIdentityRef)identity_ref;

}

?

從鑰匙串中查找證書

?

以下代碼演示如何使用證書名(在鑰匙串中用證書名標(biāo)識證書)查找證書。要用持久化引用在鑰匙串中找到一個(gè)條目,參考列表?2-4。要用一個(gè)id字串查找一個(gè)條目,參考“數(shù)據(jù)加密和解密”。

列表?2-5??在鑰匙串中查找證書

????CFTypeRef???certificateRef?????= NULL;??????????????????????// 1

????const char *certLabelString = "Romeo Montegue";

????CFStringRef certLabel = CFStringCreateWithCString(

????????????????????????????????NULL, certLabelString,

????????????????????????????????kCFStringEncodingUTF8);?????????// 2

?

????const void *keys[] =???{ kSecClass, kSecAttrLabel, kSecReturnRef };

????const void *values[] = { kSecClassCertificate, certLabel, kCFBooleanTrue };

????CFDictionaryRef dict = CFDictionaryCreate(NULL, keys,

???????????????????????????????????????????????values, 3,

?????????????????????????????????????????????NULL, NULL);???????// 3

????status = SecItemCopyMatching(dict, &certificateRef);????????// 4

?

????if (dict)

????????CFRelease(dict);

?

在這段代碼中?:

定義變量,存儲證書對象。

定義字符串,存儲證書名。

定義?dictionary,存儲證書查找條件。鍵-值序列中的鍵 kSecReturnRef表明,函數(shù)調(diào)用結(jié)束時(shí)應(yīng)返回一個(gè)鑰匙串條目的引用(當(dāng)查找有結(jié)果時(shí))。

?

在鑰匙串中查找證書。

?

獲取策略對象并評估可信度

?

評估證書可信度之前,必需獲取到一個(gè)證書對象的引用。你可以從一個(gè)identity中提取一個(gè)證書對象(列表 2-2),也可以從DER證書數(shù)據(jù)中創(chuàng)建證書對象(使用SecCertificateCreateWithData函數(shù),見列表 2-6),或者從鑰匙串中查找證書(列表 2-5)。

評估信任度的標(biāo)準(zhǔn)由信任策略(trust policy)指定。列表 3-2 顯示如何獲得用于評估的策略對象。在iOS中有兩種策略可用:Basic X509和SSL(參考AppleX509TP 信任策略)。可以用SecPolicyCreateBasicX509或者SecPolicyCreateSSL函數(shù)獲取策略對象。

下列代碼顯示了獲取策略對象并用于評估證書是否可信。

列表?2-6??獲取策略對象用于評估

????NSString *thePath = [[NSBundle mainBundle]

??????????????????????????pathForResource:@"Romeo Montegue" ofType:@"cer"];

????NSData *certData = [[NSData alloc]

??????????????????????????initWithContentsOfFile:thePath];

????CFDataRef myCertData = (CFDataRef)certData;?????????????????// 1

?

????SecCertificateRef myCert;

????myCert = SecCertificateCreateWithData(NULL, myCertData);????// 2

?

????SecPolicyRef myPolicy = SecPolicyCreateBasicX509();?????????// 3

?

????SecCertificateRef certArray[1] = { myCert };

????CFArrayRef myCerts = CFArrayCreate(

???????????????????????????????????????NULL, (void *)certArray,

???????????????????????????????????????1, NULL);

????SecTrustRef myTrust;

????OSStatus status = SecTrustCreateWithCertificates(

????????????????????????????????????????????????????myCerts,

????????????????????????????????????????????????????myPolicy,

????????????????????????????????????????????????????&myTrust);??// 4

?

????SecTrustResultType trustResult;

????if (status == noErr) {

????????status = SecTrustEvaluate(myTrust, &trustResult);???????// 5

????}

...?????????????????????????????????????????????????????????????// 6

????if (trustResult == kSecTrustResultRecoverableTrustFailure) {

????????...;

????}

...

????if (myPolicy)

????????CFRelease(myPolicy);????????????????????????????????????// 7

在這段代碼中?:

查找證書文件并獲取數(shù)據(jù)。本例中,該文件位于應(yīng)用程序束。但你也可以從網(wǎng)絡(luò)獲取證書。如果證書存在于鑰匙串中,參考“在鑰匙串中查找證書”。

從證書數(shù)據(jù)中創(chuàng)建certificate引用。

創(chuàng)建用于評估證書的策略。

用證書和策略創(chuàng)建信任對象(trust)。如果存在中間證書或者錨證書,應(yīng)把這些證書都包含在certificate數(shù)組中并傳遞給SecTrustCreateWithCertificates函數(shù)。這樣會加快評估的速度。

評估一個(gè)信任對象。

處理信任結(jié)果(trust result)。如果信任結(jié)果是kSecTrustResultInvalid,kSecTrustResultDeny,kSecTrustResultFatalTrustFailure,你無法進(jìn)行處理。如果信任結(jié)果是kSecTrustResultRecoverableTrustFailure,你可以恢復(fù)這個(gè)錯(cuò)誤。參考“從信任失敗中恢復(fù)”。

釋放策略對象。

?

從信任失敗中恢復(fù)

?

信任評估的結(jié)果有多個(gè),這取決于:是否證書鏈中的所有證書都能找到并全都有效,以及用戶對這些證書的信任設(shè)置是什么。信任結(jié)果怎么處理則由你的程序來決定。例如,如果信任結(jié)果是kSecTrustResultConfirm,你可以顯示一個(gè)對話框,詢問用戶是否允許繼續(xù)。

信任結(jié)果kSecTrustResultRecoverableTrustFailure的意思是:信任被否決,但可以通過改變設(shè)置獲得不同結(jié)果。例如,如果證書簽發(fā)過期,你可以改變評估日期以判斷是否證書是有效的同時(shí)文檔是已簽名的。列表 3-4 演示如何改變評估日期。注意 CFDateCreate函數(shù)使用絕對時(shí)間(從2001年1月1日以來的秒數(shù))。你可以用CFGregorianDateGetAbsoluteTime函數(shù)把日歷時(shí)間轉(zhuǎn)換為絕對時(shí)間。

列表?2-7??設(shè)置評估時(shí)間

????????SecTrustResultType trustResult;

????????status = SecTrustEvaluate(myTrust, &trustResult);???????// 1

?

????//Get time used to verify trust

????CFAbsoluteTime trustTime,currentTime,timeIncrement,newTime;

????CFDateRef newDate;

????if (trustResult == kSecTrustResultRecoverableTrustFailure) {// 2

????????trustTime = SecTrustGetVerifyTime(myTrust);?????????????// 3

?????????timeIncrement = 31536000;???????????????????????????????// 4

????????currentTime = CFAbsoluteTimeGetCurrent();???????????????// 5

????????newTime = currentTime - timeIncrement;??????????????????// 6

????????if (trustTime - newTime){????????????????????????????????// 7

????????????newDate = CFDateCreate(NULL, newTime);??????????????// 8

????????????SecTrustSetVerifyDate(myTrust, newDate);????????????// 9

????????????status = SecTrustEvaluate(myTrust, &trustResult);???// 10

????????}

????}

????if (trustResult != kSecTrustResultProceed) {????????????????// 11

...

}

在這段代碼中:

評估證書可信度。參考“獲取策略對象并評估可信度”。

檢查信任評估結(jié)果是否是可恢復(fù)的失敗(?kSecTrustResultRecoverableTrustFailure?)。

取得證書的評估時(shí)間(絕對時(shí)間)。如果證書在評估時(shí)已經(jīng)過期了,則被認(rèn)為無效。

設(shè)置時(shí)間的遞增量為1年(以秒計(jì)算)。

取得當(dāng)前時(shí)間的絕對時(shí)間。

設(shè)置新時(shí)間(第2次評估的時(shí)間)為當(dāng)前時(shí)間減一年。

檢查評估時(shí)間是否大于1年前(最近一次評估是否1年前進(jìn)行的)。如果是,使用新時(shí)間(1年前的時(shí)間)進(jìn)行評估,看證書是否在1年前就已經(jīng)過期。

把新時(shí)間轉(zhuǎn)換為CFDateRef。也可以用NSDate,二者是完全互通的,方法中的NSDate*參數(shù),可以用CFDateRef進(jìn)行傳遞;反之亦可。

設(shè)置信任評估時(shí)間為新時(shí)間(1年前)。

再次進(jìn)行信任評估。如果證書是因?yàn)檫^期(到期時(shí)間在1年內(nèi))導(dǎo)致前次評估失敗,那么這次評估應(yīng)該成功。

再次檢查評估結(jié)果。如果仍不成功,則需要做更進(jìn)一步的操作,比如提示用戶安裝中間證書,或則友好地告知用戶證書校驗(yàn)失敗。

?

數(shù)據(jù)加密和解密

?

證書,密鑰和信任API包含了生產(chǎn)不對稱密鑰對并用于數(shù)據(jù)加密/解密的函數(shù)集。例如,你可能想加密數(shù)據(jù),這些數(shù)據(jù)的備份不能被訪問。或者,你可能想在你的iOS應(yīng)用和桌面應(yīng)用間共享公鑰/私鑰對,以通過網(wǎng)絡(luò)發(fā)送加密數(shù)據(jù)。列表 2-8 顯示如何產(chǎn)生可用于手機(jī)的公/私鑰對。列表 2-9 顯示如何用公鑰加密數(shù)據(jù),列表 2-10 顯示如何用私鑰解密數(shù)據(jù)。注意,這幾個(gè)示例都使用了cocoa對象(如NSMutableDictionary),而本章其他示例使用了core framework對象(如CFMutableDictionaryRef),二者是等價(jià)的。

?

列表?2-8??生成密鑰對

static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey/0";

static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey/0";

????????????????????????????????????????????????????????????????// 1

?

- (void)generateKeyPairPlease

{

????OSStatus status = noErr;

????NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];

????NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];

????NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];

?????????????????????????????????????????????????????????????????// 2

?

????NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier

????????????????????????????????length:strlen((const char *)publicKeyIdentifier)];

????NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier

???????????????????????????????length:strlen((const char *)privateKeyIdentifier)];

????????????????????????????????????????????????????????????????// 3

?

????SecKeyRef publicKey = NULL;

????SecKeyRef privateKey = NULL;?????????????????????????????????// 4

?

????[keyPairAttr setObject:(id)kSecAttrKeyTypeRSA

???????????????????????????????????forKey:(id)kSecAttrKeyType]; // 5

????[keyPairAttr setObject:[NSNumber numberWithInt:1024]

?????????????????????????????forKey:(id)kSecAttrKeySizeInBits]; // 6

?

????[privateKeyAttr setObject:[NSNumber numberWithBool:YES]

???????????????????????????????forKey:(id)kSecAttrIsPermanent]; // 7

????[privateKeyAttr setObject:privateTag

????????????????????????????forKey:(id)kSecAttrApplicationTag]; // 8

?

????[publicKeyAttr setObject:[NSNumber numberWithBool:YES]

???????????????????????????????forKey:(id)kSecAttrIsPermanent]; // 9

????[publicKeyAttr setObject:publicTag

????????????????????????????forKey:(id)kSecAttrApplicationTag]; // 10

?

????[keyPairAttr setObject:privateKeyAttr

???????????????????????????????forKey:(id)kSecPrivateKeyAttrs]; // 11

????[keyPairAttr setObject:publicKeyAttr

????????????????????????????????forKey:(id)kSecPublicKeyAttrs]; // 12

?

????status = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr,

??????????????????????????????????????&publicKey, &privateKey); // 13

//????error handling...

?

?

????if(privateKeyAttr) [privateKeyAttr release];

????if(publicKeyAttr) [publicKeyAttr release];

????if(keyPairAttr) [keyPairAttr release];

????if(publicKey) CFRelease(publicKey);

????if(privateKey) CFRelease(privateKey);???????????????????????// 14

}

在這段代碼中?:

定義公/私鑰id的字符串變量,以便后面使用。

定義dictionary,用于傳遞SecKeyGeneratePair函數(shù)中的第1個(gè)參數(shù)。

把第1步中定義的字符串轉(zhuǎn)換為NSData對象。

為公/私鑰對準(zhǔn)備SecKeyRef對象。

設(shè)置密鑰對的密鑰類型為RSA。

設(shè)置密鑰對的密鑰長度為1024。

設(shè)置私鑰的持久化屬性(即是否存入鑰匙串)為YES。

把1-3步中的identifier放到私鑰的dictionary中。

設(shè)置公鑰的持久化屬性(即是否存入鑰匙串)為YES。

把1-3步中的identifier放到公鑰的dictionary中。

把私鑰的屬性集(dictionary)加到密鑰對的屬性集(dictionary)中。

把公鑰的屬性集(dictionary)加到密鑰對的屬性集(dictionary)中。

產(chǎn)生密鑰對。

釋放無用對象。

你可以把公鑰發(fā)送給任何人,他們可以用它來加密數(shù)據(jù)。假設(shè)你安全地保存了私鑰,則只有你能解密這些數(shù)據(jù)。以下代碼演示如何用公鑰加密數(shù)據(jù)。可以用從設(shè)備上產(chǎn)生的公鑰(見后面代碼),或者從證書中提取的公鑰(發(fā)送給你的證書或者已經(jīng)在鑰匙串中的證書)。用SecTrustCopyPublicKey函數(shù)可以從證書中提取公鑰。下面假設(shè)這個(gè)密鑰由設(shè)備產(chǎn)生并已放到鑰匙串中。

列表?2-9??用公鑰加密數(shù)據(jù)

- (void)encryptWithPublicKey

{

????OSStatus status = noErr;

?

????size_t cipherBufferSize;

????uint8_t *cipherBuffer;?????????????????????// 1

?

// [cipherBufferSize]

????const uint8_t nonce[] = "the quick brown fox jumps

??????????????????????????????????????????over the lazy dog/0"; // 2

?

????SecKeyRef publicKey = NULL;?????????????????????????????????// 3

?

????NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier

?????????????length:strlen((const char *)publicKeyIdentifier)]; // 4

?

????NSMutableDictionary *queryPublicKey =

????????????????????????????[[NSMutableDictionary alloc] init]; // 5

?

????[queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass];

????[queryPublicKey setObject:publicTag forKey:(id)kSecAttrApplicationTag];

????[queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];

????[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];

?????????????????????????????????????????????????????????????????// 6

?

????status = SecItemCopyMatching

????((CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey); // 7

?

//??Allocate a buffer

?

????cipherBufferSize = cipherBufferSize(publicKey);

????cipherBuffer = malloc(cipherBufferSize);

?

//??Error handling

?

????if (cipherBufferSize < sizeof(nonce)) {

????????// Ordinarily, you would split the data up into blocks

????????// equal to cipherBufferSize, with the last block being

????????// shorter. For simplicity, this example assumes that

????????// the data is short enough to fit.

????????printf("Could not decrypt.??Packet too large./n");

????????return;

????}

?

????// Encrypt using the public.

????status = SecKeyEncrypt(????publicKey,

????????????????????????????????kSecPaddingPKCS1,

????????????????????????????????nonce,

????????????????????????????????(size_t) sizeof(nonce)/sizeof(nonce[0]),

????????????????????????????????cipherBuffer,

????????????????????????????????&cipherBufferSize

????????????????????????????????);???????????????????????????????// 8

?

//??Error handling

//??Store or transmit the encrypted text

?

????if(publicKey) CFRelease(publicKey);

????if(queryPublicKey) [queryPublicKey release];????????????????// 9

????free(cipherBuffer);

}

在這段代碼中?:

定義緩存,用于放入加密文本。

指定要加密的文本。

定義SecKeyRef,用于公鑰。

定義NSData對象,存儲公鑰的identifier(見列表 2-8 的第1、3、8步),該id在鑰匙串中唯一。

定義dictionary,用于從鑰匙串中查找公鑰。

設(shè)置dictionary的鍵-值屬性。屬性中指定,鑰匙串條目類型為“密鑰”,條目identifier為第4步中指定的字符串,密鑰類型為RSA,函數(shù)調(diào)用結(jié)束返回查找到的條目引用。

調(diào)用SecItemCopyMatching函數(shù)進(jìn)行查找。

加密數(shù)據(jù), 返回結(jié)果用PKCS1格式對齊。

釋放不用的變量。

The following code sample shows how to decrypt data. This sample uses the private key corresponding to the public key used to encrypt the data, and assumes you already have the cipher text created in the preceding example. It gets the private key from the keychain using the same technique as used in the preceding example to get the public key.

下面代碼演示如何解密。本例采用與加密數(shù)據(jù)的公鑰對的私鑰進(jìn)行解密,并且密文為上面例子中的加密結(jié)果。從鑰匙串中獲取私鑰,采用與上例相同的技術(shù)。

?

列表?2-10??用私鑰解密

- (void)decryptWithPrivateKey

{

????OSStatus status = noErr;

?

????size_t plainBufferSize;;

????uint8_t *plainBuffer;

?

????SecKeyRef privateKey = NULL;

?

????NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier

????????????????????????????length:strlen((const char *)privateKeyIdentifier)];

?

?????NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];

?

????// Set the private key query dictionary.

????[queryPrivateKey setObject:(id)kSecClassKey forKey:(id)kSecClass];

????[queryPrivateKey setObject:privateTag forKey:(id)kSecAttrApplicationTag];

????[queryPrivateKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];

????[queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];

????????????????????????????????????????????????????????????????// 1

?

????status = SecItemCopyMatching

??((CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKey); // 2

?

????if (plainBufferSize < cipherBufferSize) {

????????// Ordinarily, you would split the data up into blocks

????????// equal to plainBufferSize, with the last block being

????????// shorter. For simplicity, this example assumes that

????????// the data is short enough to fit.

????????printf("Could not decrypt.??Packet too large./n");

????????return;

????}

?

//??Allocate the buffer

????plainBufferSize = SecKeyGetBlockSize(privateKey);

????plainBuffer = malloc(plainBufferSize)

?

//??Error handling

?

????status = SecKeyDecrypt(????privateKey,

????????????????????????????????kSecPaddingPKCS1,

????????????????????????????????cipherBuffer,

?????????????????????????????????cipherBufferSize,

????????????????????????????????plainBuffer,

????????????????????????????????&plainBufferSize

????????????????????????????????);??????????????????????????????// 3

?

//??Error handling

//??Store or display the decrypted text

?

????if(publicKey) CFRelease(publicKey);

????if(privateKey) CFRelease(privateKey);

????if(queryPublicKey) [queryPublicKey release];

????if(queryPrivateKey) [queryPrivateKey release];??????????????// 4

}

在這段代碼中?:

準(zhǔn)備dictionary,用于從鑰匙串查找私鑰。

在鑰匙串中找到私鑰。

解密數(shù)據(jù)。

釋放無用的變量。

總結(jié)

以上是生活随笔為你收集整理的iOS 证书、密钥及信任服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。