0

私のアプリでは、証明書に基づいてユーザーを認証する必要があります。これが私のやり方です 1. まず、証明書をサンドボックスにエクスポートします。2. 次に、証明書から SecIdentityRef を抽出してキーチェーンに追加し、後でサンドボックスから証明書を削除します。3. この ID を NSURL 接続の認証チャレンジに実際に渡すと、意味のある情報を提供せずにアプリがクラッシュします。

以下は、関連するすべてのコード スニペットです。

//Exporting the certificate into the app and extracting the identity from it

- (void)importCertificateIntoKeychain:(NSString *)Password
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Certificates"];
    NSString *certFolderName = [[[[NSUserDefaults standardUserDefaults] objectForKey:@"CertificatePath"] lastPathComponent]stringByDeletingPathExtension];
    NSString *path = [NSString stringWithFormat:@"%@/%@",dataPath,certFolderName];
    NSArray*array = [[NSFileManager defaultManager]
                     contentsOfDirectoryAtPath:
                     path
                     error:nil];
    NSString *thePath;
    NSString *fileName;
    for (int i=0;i<array.count;i++) {
        if ([[array objectAtIndex:i]hasSuffix:@".pfx"]) {
            fileName= [array objectAtIndex:i];
            thePath = [NSString stringWithFormat:@"%@/%@",path,fileName];
        }
    }

    SecIdentityRef identityApp = nil;

    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    NSString *pwd = Password;
    CFStringRef password = (CFStringRef)CFBridgingRetain(pwd);
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
    CFRelease(options);
    CFRelease(password);
    if (securityError == errSecSuccess) {
        NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        SecCertificateRef certificate = NULL;
        SecIdentityCopyCertificate (identityApp, &certificate);

       OSStatus status = errSecSuccess;

        CFTypeRef persistent_ref = NULL;
        const void *keys[] = { kSecReturnPersistentRef, kSecValueRef };
        const void *values[] = { kCFBooleanTrue, identityApp };
        CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values,
                                                             2, NULL, NULL);
        status = SecItemAdd(dict, &persistent_ref);
        NSLog(@"Status %ld",status);

        if (dict)
        CFRelease(dict);
        [Utils deleteCertificateFromInboxFolder];
    } else {
        NSLog(@"Error opening Certificate.");
        [Utils displayAlertWithTitle:@"Wrong Password" andMessage:@"Error opening certificate"];
    }
}

認証チャレンジでこの資格情報を渡す

if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
    {
        fprintf(stderr, "identities:\n");
        fprintf(stderr, "certificates:\n");
        NSLog(@"NSURLAuthenticationMethodClientCertificate");

        SecIdentityRef identity;
        identity = (__bridge SecIdentityRef)([self _dumpCredentialsOfSecClass:kSecClassIdentity printSelector:@selector(_printIdentity:attributes:)]);
        SecCertificateRef certificate1 = NULL;
        OSStatus *stat = SecIdentityCopyCertificate (identity, &certificate1);
        //const void *certs[] = {certificate1};

        SecCertificateRef certArray[1] = { certificate1 };
        CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
        CFRelease(certificate1);
        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity
                                                                 certificates:(__bridge NSArray *)myCerts
                                                                  persistence:NSURLCredentialPersistencePermanent];
        CFRelease(myCerts);

//        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
//        
//        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistenceNone];
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}

この資格情報を NSURLChallenge 送信者に渡すと、アプリがクラッシュします。

ここに画像の説明を入力

どんな助けでも大歓迎です!!!

4

2 に答える 2