iOS 证书、密钥及信任服务
iOS?證書、密鑰及信任服務
——翻譯自Apple Reference《Certificate,Key,and Trust Services Programming Guide》
?
本章描述并演示了如何使用證書、密鑰和信任服務去導入一個indentity,評估證書是否可信,判斷證書失效的原因,以及失效證書的恢復。
本章按如下順序分別演示了:
導入一個?identity.
從導入的數據中獲得證書.
獲得用于證書評估的策略.
校驗證書,根據指定策略評估證書是否可信.
測試證書中的可恢復錯誤.
判斷證書是否過期.
改變評估條件,忽略過期證書.
重新評估證書.
??“?第2章,Certificate,Key,and Trust Services Concepts”,介紹了證書,密鑰和信任服務的概念和術語。關于證書,密鑰和信任服務的細節內容,請參考Certificate,Key,and Trust Services Reference.
從一個.p12文件中提取、評估Identity
?
如果你需要在iOS設備上使用加密過的identity(一個密鑰及其關聯的證書)進行客戶端認證,例如——你可以把PKCS#12數據以受密碼保護的文件的方式安全地傳輸到這個設備上。本節顯示如何從PKCS#12數據中提取identity和trust objects(可信任對象),并評估其可信度。
列表?2-1 顯示了用SecPKCS12Import函數從.p12文件中提取identity和可信任對象,以及評估其可信度。
列表?2-2 顯示如何從identity中獲取證書并顯示證書信息。每個列表后都對代碼進行了解釋。
在編譯這段代碼時,請確認在Xcode工程中加入了Security.framework。
列表???2-1??從PKCS#12數據中提取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文件并獲得數據。本例中,該文件位于application bundle中。你也可以通過網絡方式把文件傳輸給你的應用程序。
調用該函數獲得identity和trust對象(見步驟5)。
評估證書。這里的信任對象(trust object),包括信任策略和其他用于判斷證書是否可信的信息,都已經含在了PKCS數據中。要單獨評估一個證書是否可信,見列表 2-6。
處理信任結果。如果信任結果是kSecTrustResultInvalid,kSecTrustResultDeny,kSecTrustResultFatalTrustFailure,你無法進行處理。如果評估結果是kSecTrustResultRecoverableTrustFailure,你可以從信任失敗中恢復。參見“從信任失敗中恢復”。
第2步中調用的函數的具體實現。
構造包含了密碼的dictionary,用于傳遞給SecPKCS12Import函數。注意這里使用的是core foundation中的CFDictionaryRef,與NSDictionary完全等價。列表 2-9 則是一個使用NSDictionary的例子。
從PKCS#12數據中提取證書、密鑰和trust并將其放到數組中。
從數組中取出第1個dictionary,并從dictionary中取出identity和trust。SecPKCS12Import函數將PKCS數據中的每一個條目返回為一個dictionary。本例中,identity被提取到數組的第1個元素。
釋放dictionary和PKCS12Data,他們不再被使用。
以下列表顯示如何從identity中獲取證書以及顯示證書信息。編譯本段代碼前請確保在工程中導入了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?轉換為NSString。
釋放NSString。
?
獲取和使用持久化的鑰匙串
?
當你在鑰匙串中添加或查找一個條目時,你需要有一個持久化的引用。因為持久化引用能保證在程序從啟動到能寫入磁盤這段時間內,始終可用。當需要反復在鑰匙串中查找條目時,使用持久化引用更加容易。以下代碼演示如何獲取一個?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;
}
?
從鑰匙串中查找證書
?
以下代碼演示如何使用證書名(在鑰匙串中用證書名標識證書)查找證書。要用持久化引用在鑰匙串中找到一個條目,參考列表?2-4。要用一個id字串查找一個條目,參考“數據加密和解密”。
列表?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表明,函數調用結束時應返回一個鑰匙串條目的引用(當查找有結果時)。
?
在鑰匙串中查找證書。
?
獲取策略對象并評估可信度
?
評估證書可信度之前,必需獲取到一個證書對象的引用。你可以從一個identity中提取一個證書對象(列表 2-2),也可以從DER證書數據中創建證書對象(使用SecCertificateCreateWithData函數,見列表 2-6),或者從鑰匙串中查找證書(列表 2-5)。
評估信任度的標準由信任策略(trust policy)指定。列表 3-2 顯示如何獲得用于評估的策略對象。在iOS中有兩種策略可用:Basic X509和SSL(參考AppleX509TP 信任策略)。可以用SecPolicyCreateBasicX509或者SecPolicyCreateSSL函數獲取策略對象。
下列代碼顯示了獲取策略對象并用于評估證書是否可信。
列表?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
在這段代碼中?:
查找證書文件并獲取數據。本例中,該文件位于應用程序束。但你也可以從網絡獲取證書。如果證書存在于鑰匙串中,參考“在鑰匙串中查找證書”。
從證書數據中創建certificate引用。
創建用于評估證書的策略。
用證書和策略創建信任對象(trust)。如果存在中間證書或者錨證書,應把這些證書都包含在certificate數組中并傳遞給SecTrustCreateWithCertificates函數。這樣會加快評估的速度。
評估一個信任對象。
處理信任結果(trust result)。如果信任結果是kSecTrustResultInvalid,kSecTrustResultDeny,kSecTrustResultFatalTrustFailure,你無法進行處理。如果信任結果是kSecTrustResultRecoverableTrustFailure,你可以恢復這個錯誤。參考“從信任失敗中恢復”。
釋放策略對象。
?
從信任失敗中恢復
?
信任評估的結果有多個,這取決于:是否證書鏈中的所有證書都能找到并全都有效,以及用戶對這些證書的信任設置是什么。信任結果怎么處理則由你的程序來決定。例如,如果信任結果是kSecTrustResultConfirm,你可以顯示一個對話框,詢問用戶是否允許繼續。
信任結果kSecTrustResultRecoverableTrustFailure的意思是:信任被否決,但可以通過改變設置獲得不同結果。例如,如果證書簽發過期,你可以改變評估日期以判斷是否證書是有效的同時文檔是已簽名的。列表 3-4 演示如何改變評估日期。注意 CFDateCreate函數使用絕對時間(從2001年1月1日以來的秒數)。你可以用CFGregorianDateGetAbsoluteTime函數把日歷時間轉換為絕對時間。
列表?2-7??設置評估時間
????????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
...
}
在這段代碼中:
評估證書可信度。參考“獲取策略對象并評估可信度”。
檢查信任評估結果是否是可恢復的失敗(?kSecTrustResultRecoverableTrustFailure?)。
取得證書的評估時間(絕對時間)。如果證書在評估時已經過期了,則被認為無效。
設置時間的遞增量為1年(以秒計算)。
取得當前時間的絕對時間。
設置新時間(第2次評估的時間)為當前時間減一年。
檢查評估時間是否大于1年前(最近一次評估是否1年前進行的)。如果是,使用新時間(1年前的時間)進行評估,看證書是否在1年前就已經過期。
把新時間轉換為CFDateRef。也可以用NSDate,二者是完全互通的,方法中的NSDate*參數,可以用CFDateRef進行傳遞;反之亦可。
設置信任評估時間為新時間(1年前)。
再次進行信任評估。如果證書是因為過期(到期時間在1年內)導致前次評估失敗,那么這次評估應該成功。
再次檢查評估結果。如果仍不成功,則需要做更進一步的操作,比如提示用戶安裝中間證書,或則友好地告知用戶證書校驗失敗。
?
數據加密和解密
?
證書,密鑰和信任API包含了生產不對稱密鑰對并用于數據加密/解密的函數集。例如,你可能想加密數據,這些數據的備份不能被訪問。或者,你可能想在你的iOS應用和桌面應用間共享公鑰/私鑰對,以通過網絡發送加密數據。列表 2-8 顯示如何產生可用于手機的公/私鑰對。列表 2-9 顯示如何用公鑰加密數據,列表 2-10 顯示如何用私鑰解密數據。注意,這幾個示例都使用了cocoa對象(如NSMutableDictionary),而本章其他示例使用了core framework對象(如CFMutableDictionaryRef),二者是等價的。
?
列表?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函數中的第1個參數。
把第1步中定義的字符串轉換為NSData對象。
為公/私鑰對準備SecKeyRef對象。
設置密鑰對的密鑰類型為RSA。
設置密鑰對的密鑰長度為1024。
設置私鑰的持久化屬性(即是否存入鑰匙串)為YES。
把1-3步中的identifier放到私鑰的dictionary中。
設置公鑰的持久化屬性(即是否存入鑰匙串)為YES。
把1-3步中的identifier放到公鑰的dictionary中。
把私鑰的屬性集(dictionary)加到密鑰對的屬性集(dictionary)中。
把公鑰的屬性集(dictionary)加到密鑰對的屬性集(dictionary)中。
產生密鑰對。
釋放無用對象。
你可以把公鑰發送給任何人,他們可以用它來加密數據。假設你安全地保存了私鑰,則只有你能解密這些數據。以下代碼演示如何用公鑰加密數據。可以用從設備上產生的公鑰(見后面代碼),或者從證書中提取的公鑰(發送給你的證書或者已經在鑰匙串中的證書)。用SecTrustCopyPublicKey函數可以從證書中提取公鑰。下面假設這個密鑰由設備產生并已放到鑰匙串中。
列表?2-9??用公鑰加密數據
- (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,用于從鑰匙串中查找公鑰。
設置dictionary的鍵-值屬性。屬性中指定,鑰匙串條目類型為“密鑰”,條目identifier為第4步中指定的字符串,密鑰類型為RSA,函數調用結束返回查找到的條目引用。
調用SecItemCopyMatching函數進行查找。
加密數據, 返回結果用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.
下面代碼演示如何解密。本例采用與加密數據的公鑰對的私鑰進行解密,并且密文為上面例子中的加密結果。從鑰匙串中獲取私鑰,采用與上例相同的技術。
?
列表?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
}
在這段代碼中?:
準備dictionary,用于從鑰匙串查找私鑰。
在鑰匙串中找到私鑰。
解密數據。
釋放無用的變量。
總結
以上是生活随笔為你收集整理的iOS 证书、密钥及信任服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: layoutSubviews 详解
- 下一篇: dnf贝奇NPC位置在哪里 dnf贝奇N