snej@0: //
snej@0: //  MYCryptoTest.m
snej@0: //  MYCrypto-iPhone
snej@0: //
snej@0: //  Created by Jens Alfke on 4/1/09.
snej@0: //  Copyright 2009 Jens Alfke. All rights reserved.
snej@0: //
snej@0: 
snej@3: #import "MYPublicKey.h"
snej@3: #import "MYPrivateKey.h"
snej@0: #import "MYKeychain.h"
snej@0: #import "MYDigest.h"
snej@4: #import "MYIdentity.h"
snej@12: #if !TARGET_OS_IPHONE
snej@8: #import "MYCrypto+Cocoa.h"
snej@12: #endif
snej@0: #import "MYCrypto_Private.h"
snej@0: 
snej@0: 
snej@0: #if DEBUG
snej@0: 
snej@11: 
snej@11: #define kTestCaseRSAKeySize 2048
snej@11: 
snej@0: #pragma mark -
snej@0: #pragma mark KEYCHAIN:
snej@0: 
snej@0: 
snej@0: TestCase(MYKeychain) {
snej@0:     MYKeychain *kc = [MYKeychain defaultKeychain];
snej@0:     Log(@"Default keychain = %@", kc);
snej@0:     CAssert(kc);
snej@2: #if !MYCRYPTO_USE_IPHONE_API
snej@0:     CAssert(kc.path);
snej@0: #endif
snej@0:     
snej@0:     kc = [MYKeychain allKeychains];
snej@0:     Log(@"All-keychains = %@", kc);
snej@0:     CAssert(kc);
snej@2: #if !MYCRYPTO_USE_IPHONE_API
snej@0:     CAssertEq(kc.path,nil);
snej@1: #endif
snej@0: }
snej@0: 
snej@0: 
jens@23: TestCase(Enumerate) {
jens@23:     RequireTestCase(EnumeratePublicKeys);
jens@23:     RequireTestCase(EnumeratePrivateKeys);
jens@23:     RequireTestCase(EnumerateSymmetricKeys);
jens@23:     RequireTestCase(EnumerateCerts);
jens@23:     RequireTestCase(EnumerateIdentities);
jens@23: }
jens@23: 
jens@23: 
jens@23: TestCase(EnumeratePublicKeys) {
snej@0:     RequireTestCase(MYKeychain);
snej@0:     NSEnumerator *e = [[MYKeychain allKeychains] enumeratePublicKeys];
snej@0:     Log(@"Public Key Enumerator = %@", e);
snej@0:     CAssert(e);
snej@0:     for (MYPublicKey *key in e) {
jens@23:         Log(@"Trying public key %@", key.keyRef);
jens@23:         @try{
jens@23:             Log(@"Found %@ -- name=%@", key, key.name);
jens@23:         }@catch (NSException *x) {
jens@23:             Warn(@"Caught %@",x); //TEMP
jens@23:         }
snej@0:     }
jens@23: }
jens@23: 
jens@23: TestCase(EnumeratePrivateKeys) {
jens@23:     RequireTestCase(MYKeychain);
jens@23:     NSEnumerator *e = [[MYKeychain allKeychains] enumeratePrivateKeys];
snej@0:     Log(@"Key-Pair Enumerator = %@", e);
snej@0:     CAssert(e);
snej@3:     for (MYPrivateKey *key in e) {
jens@23:         Log(@"Found %@ -- name=%@ --> %@", key, key.name, key.publicKey);
jens@23:         CAssert(key.publicKey);
snej@0:     }
jens@23: }
jens@23: 
jens@23: TestCase(EnumerateSymmetricKeys) {
jens@23:     RequireTestCase(MYKeychain);
jens@23:     NSEnumerator *e = [[MYKeychain allKeychains] enumerateSymmetricKeys];
snej@0:     Log(@"Symmetric Key Enumerator = %@", e);
snej@0:     CAssert(e);
snej@0:     for (MYSymmetricKey *key in e) {
snej@0:         Log(@"Found %@ -- name=%@", key, key.name);
snej@0:     }
snej@0: }
snej@0: 
snej@0: 
snej@0: TestCase(EnumerateCerts) {
snej@0:     RequireTestCase(MYKeychain);
snej@0:     NSEnumerator *e = [[MYKeychain allKeychains] enumerateCertificates];
snej@0:     Log(@"Enumerator = %@", e);
snej@0:     CAssert(e);
snej@0:     for (MYCertificate *cert in e) {
jens@23:         Log(@"Found %@ -- name=%@, email=%@", cert, cert.commonName, cert.emailAddresses);
jens@23:         CAssert(cert.publicKey);
snej@0:     }
snej@0: }
snej@0: 
snej@4: TestCase(EnumerateIdentities) {
snej@4:     RequireTestCase(MYKeychain);
snej@4:     NSEnumerator *e = [[MYKeychain allKeychains] enumerateIdentities];
snej@4:     Log(@"Enumerator = %@", e);
snej@4:     CAssert(e);
snej@4:     for (MYIdentity *ident in e) {
snej@8:         Log(@"Found %@\n\tcommonName=%@\n\temails=(%@)\n\tkey=%@",
snej@4:             ident, ident.commonName, 
snej@5: #if TARGET_OS_IPHONE
snej@5:             nil,
snej@5: #else
snej@4:             [ident.emailAddresses componentsJoinedByString: @", "],
snej@5: #endif
snej@4:             ident.privateKey);
snej@4:     }
snej@4: }
snej@4: 
snej@0: 
snej@0: #pragma mark -
snej@0: #pragma mark SYMMETRIC KEYS:
snej@0: 
snej@0: 
snej@12: static void testSymmetricKey( CCAlgorithm algorithm, unsigned sizeInBits, MYKeychain *inKeychain ) {
snej@2:     NSAutoreleasePool *pool = [NSAutoreleasePool new];
snej@12:     MYSymmetricKey *key = nil;
snej@12:     @try{
snej@12:         Log(@"--- Testing %3u-bit #%i %s", sizeInBits, (int)algorithm,
snej@12:             (inKeychain ?", in keychain" :""));
snej@12:         // Generate key:
snej@12:         if (inKeychain)
snej@12:             key = [inKeychain generateSymmetricKeyOfSize: sizeInBits algorithm: algorithm];
snej@12:         else
snej@12:             key = [MYSymmetricKey generateSymmetricKeyOfSize: sizeInBits algorithm: algorithm];
snej@12:         Log(@"Created %@", key);
jens@23:         CAssert(key);
snej@12:         CAssertEq(key.algorithm, algorithm);
snej@12:         CAssertEq(key.keySizeInBits, sizeInBits);
snej@12:     #if !TARGET_OS_IPHONE
snej@12:         CAssert(key.cssmKey != NULL);
snej@12:     #endif
snej@12:         
snej@12:         NSData *keyData = key.keyData;
snej@12:         Log(@"Key data = %@", keyData);
snej@12:         CAssertEq(keyData.length, sizeInBits/8);
snej@12:         
snej@12:         // Encrypt a small amount of text:
snej@12:         Log(@"Testing encryption / decryption ...");
snej@12:         NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@12:         NSData *encrypted = [key encryptData: cleartext];
snej@12:         Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted);
snej@12:         CAssert(encrypted.length >= cleartext.length);
snej@12:         NSData *decrypted = [key decryptData: encrypted];
snej@12:         CAssertEqual(decrypted, cleartext);
snej@12:         
snej@12:         // Encrypt large binary data:
snej@12:         cleartext = [NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"];
snej@12:         CAssert(cleartext);
snej@12:         encrypted = [key encryptData: cleartext];
snej@12:         Log(@"Encrypted = %u bytes", encrypted.length);
snej@12:         CAssert(encrypted.length >= cleartext.length);
snej@12:         decrypted = [key decryptData: encrypted];
snej@12:         CAssertEqual(decrypted, cleartext);
snej@12:         
snej@12:     #if 1
snej@12:         Log(@"Testing initWithKeyData:...");
snej@12:         MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithKeyData: keyData algorithm: algorithm];
snej@12:         CAssert(key2);
snej@12:         Log(@"Key from data = %@",key2);
snej@12:         CAssertEqual(key2.keyData, keyData);
snej@12:         CAssertEq(key2.algorithm, algorithm);
snej@12:         CAssertEq(key2.keySizeInBits, sizeInBits);
snej@2:         decrypted = [key2 decryptData: encrypted];
snej@2:         CAssertEqual(decrypted, cleartext);
snej@12:         [key2 release];
snej@12:     #endif
snej@12: 
snej@12:     #if !TARGET_OS_IPHONE
jens@16: #if 1 // TEMP-ORARILY OUT OF ORDER
snej@12:         // Try exporting and importing a wrapped key:
snej@12:         Log(@"Testing export/import...");
snej@13:         NSData *exported = [key exportWrappedKeyWithPassphrasePrompt: @"Export symmetric key with passphrase:"];
snej@12:         Log(@"Exported key: %@", exported);
snej@13:     #if 1
snej@12:         CAssert(exported);
snej@12:     #else
snej@12:         if (!exported)
snej@12:             Warn(@"Unable to export wrapped key");
snej@12:         else
snej@12:     #endif
snej@12:         {
snej@12:             CAssert(exported);
jens@16:             MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithWrappedKeyData: exported];
snej@12:             Log(@"Reconstituted as %@", key2);
snej@12:             CAssertEqual(key2.keyData,key.keyData);
snej@12:             decrypted = [key2 decryptData: encrypted];
snej@12:             CAssertEqual(decrypted, cleartext);
snej@12:         }
snej@13: #endif 0
snej@12:     #endif
snej@12:     }@finally{
snej@12:         [key removeFromKeychain];
snej@12:     }
snej@2:     [pool drain];
snej@2: }
snej@2: 
snej@2: 
snej@0: TestCase(MYSymmetricKey) {
snej@0:     #define kNTests 11
snej@0:     static const CCAlgorithm kTestAlgorithms[kNTests] = {
snej@0:         kCCAlgorithmAES128, kCCAlgorithmAES128, kCCAlgorithmAES128,
snej@0:         kCCAlgorithmDES, kCCAlgorithm3DES,
snej@0:         kCCAlgorithmCAST, kCCAlgorithmCAST, kCCAlgorithmCAST,
snej@0:         kCCAlgorithmRC4, kCCAlgorithmRC4, kCCAlgorithmRC4};
snej@0:     
snej@0:     static const unsigned kTestBitSizes[kNTests] = {
snej@0:         128, 192, 256,
snej@0:         64, 3*64,
snej@0:         40, 80, 128,
snej@0:         32, 200, 512*8};
snej@0: 
snej@12:     for (int useKeychain=0; useKeychain<=1; useKeychain++)
snej@12:         for (int testNo=0; testNo<kNTests; testNo++) 
snej@12:             testSymmetricKey(kTestAlgorithms[testNo], 
snej@12:                              kTestBitSizes[testNo],
snej@12:                              useKeychain ?[MYKeychain defaultKeychain] :nil);
snej@12: }
snej@12: 
snej@12: 
snej@14: #if !TARGET_OS_IPHONE
snej@12: TestCase(MYSymmetricKeyPassphrase) {
snej@12:     Log(@"Prompting for raw passphrase --");
snej@12:     NSString *rawPassphrase = [MYSymmetricKey promptForPassphraseWithAlertTitle: @"Raw Passphrase Test" 
snej@12:                                                                     alertPrompt: @"Enter the passphrase 'Testing':"
snej@12:                                                                        creating: YES];
snej@12:     Log(@"You entered: '%@'", rawPassphrase);
snej@12:     CAssertEqual(rawPassphrase, @"Testing");
snej@12:     
snej@12:     Log(@"Prompting for passphrase for key --");
snej@12:     MYSymmetricKey *key = [MYSymmetricKey generateFromUserPassphraseWithAlertTitle: @"Symmetric Key Passphrase Test Case" 
snej@12:                                                                        alertPrompt: @"Please enter a passphrase to generate a key:"
snej@12:                                                                           creating: YES
snej@12:                                                                               salt: @"wahooma"];
snej@12:     Log(@"Key from passphrase = %@", key);
snej@12:     CAssert(key);
snej@12: 
snej@12:     // Encrypt a small amount of text:
snej@12:     Log(@"Testing encryption / decryption ...");
snej@12:     NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@12:     NSData *encrypted = [key encryptData: cleartext];
snej@12:     Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted);
snej@12:     CAssert(encrypted.length >= cleartext.length);
snej@12:     NSData *decrypted = [key decryptData: encrypted];
snej@12:     CAssertEqual(decrypted, cleartext);
snej@12:     
snej@12:     // Now test decryption by re-entered passphrase:
snej@12:     Log(@"Testing decryption using re-entered passphrase...");
snej@12:     MYSymmetricKey *key2 = [MYSymmetricKey generateFromUserPassphraseWithAlertTitle: @"Symmetric Key Passphrase Test Case" 
snej@12:                                                                         alertPrompt: @"Please re-enter the same passphrase:" 
snej@12:                                                                            creating: NO
snej@12:                                                                                salt: @"wahooma"];
snej@12:     Log(@"Key from passphrase = %@", key2);
snej@12:     CAssert(key2);
snej@12:     decrypted = [key2 decryptData: encrypted];
snej@12:     CAssertEqual(decrypted, cleartext);
snej@0: }
snej@14: #endif
snej@0: 
snej@0: 
snej@0: #pragma mark -
snej@0: #pragma mark KEY-PAIRS:
snej@0: 
snej@0: 
snej@8: static void TestUseKeyPair(MYPrivateKey *pair) {
snej@8:     Log(@"---- TestUseKeyPair { %@ , %@ }.", pair, pair.publicKey);
snej@0:     CAssert(pair);
snej@0:     CAssert(pair.keyRef);
snej@3:     MYPublicKey *publicKey = pair.publicKey;
snej@3:     CAssert(publicKey.keyRef);
snej@0:     
snej@8:     NSData *pubKeyData = publicKey.keyData;
snej@8:     Log(@"Public key = %@ (%u bytes)",pubKeyData,pubKeyData.length);
snej@8:     CAssert(pubKeyData);
snej@8:     
jens@21:     NSData *modulus;
jens@21:     unsigned exponent;
jens@21:     CAssert([publicKey getModulus: &modulus exponent: &exponent]);
jens@21:     Log(@"Modulus = %@", modulus);
jens@21:     Log(@"Exponent = %u", exponent);
jens@21:     CAssertEq(modulus.length, 2048U/8);
jens@21:     CAssertEq(exponent,65537U); // this is what CDSA always seems to use
jens@21:     
snej@8:     MYSHA1Digest *pubKeyDigest = publicKey.publicKeyDigest;
snej@8:     Log(@"Public key digest = %@",pubKeyDigest);
snej@8:     CAssertEqual(pair.publicKeyDigest, pubKeyDigest);
snej@8:     
snej@8:     Log(@"SHA1 of pub key = %@", pubKeyData.my_SHA1Digest.asData);
snej@14:     CAssertEqual(pubKeyData.my_SHA1Digest,pubKeyDigest);
snej@8:     
snej@8:     // Let's sign data:
snej@8:     NSData *data = [@"This is a test. This is only a test!" dataUsingEncoding: NSUTF8StringEncoding];
snej@8:     NSData *sig = [pair signData: data];
snej@8:     Log(@"Signature = %@ (%u bytes)",sig,sig.length);
snej@8:     CAssert(sig);
snej@8:     CAssert( [publicKey verifySignature: sig ofData: data] );
snej@8:     
snej@8:     // Now let's encrypt...
snej@13:     NSData *crypted = [publicKey rawEncryptData: data];
snej@8:     Log(@"Encrypted = %@ (%u bytes)",crypted,crypted.length);
snej@8:     CAssert(crypted);
snej@13:     CAssertEqual([pair rawDecryptData: crypted], data);
snej@8:     Log(@"Verified decryption.");
snej@8:     
snej@8:     // Test creating a standalone public key:
snej@8:     MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: publicKey.keyRef];
snej@8:     CAssert( [pub verifySignature: sig ofData: data] );
snej@8:     Log(@"Verified signature.");
snej@8:     
snej@8:     // Test creating a public key from data:
snej@8:     Log(@"Reconstituting public key from data...");
snej@8:     pub = [[MYPublicKey alloc] initWithKeyData: pubKeyData];
snej@8:     CAssert(pub);
snej@8:     CAssertEqual(pub.keyData, pubKeyData);
snej@8:     CAssertEqual(pub.publicKeyDigest, pubKeyDigest);
snej@8:     CAssert( [pub verifySignature: sig ofData: data] );
jens@21:     [pub release];
snej@8:     Log(@"Verified signature from reconstituted key.");
jens@21:     
jens@21:     // Test creating a public key from modulus+exponent:
jens@21:     Log(@"Reconstituting public key from modulus+exponent...");
jens@21:     pub = [[MYPublicKey alloc] initWithModulus: modulus exponent: exponent];
jens@21:     CAssertEqual(pub.keyData, pubKeyData);
jens@21:     [pub release];
snej@8: }
snej@8: 
snej@8: 
snej@14: static void TestWrapSessionKey( MYPrivateKey *privateKey ) {
snej@14: #if !TARGET_OS_IPHONE
snej@13:     MYSymmetricKey *sessionKey = [MYSymmetricKey generateSymmetricKeyOfSize: 128 algorithm:kCCAlgorithmAES128];
snej@13:     CAssert(sessionKey);
snej@14:     NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@14:     NSData *encrypted = [sessionKey encryptData: cleartext];
snej@14: 
snej@13:     Log(@"Wrapping session key %@, %@", sessionKey, sessionKey.keyData);
snej@13:     NSData *wrapped = [privateKey.publicKey wrapSessionKey: sessionKey];
snej@13:     Log(@"Wrapped session key = %u bytes: %@", wrapped.length,wrapped);
snej@13:     CAssert(wrapped.length >= 128/8);
snej@13:     
snej@13:     MYSymmetricKey *unwrappedKey = [privateKey unwrapSessionKey: wrapped
snej@13:                                                   withAlgorithm: kCCAlgorithmAES128
snej@13:                                                      sizeInBits: 128];
snej@13:     Log(@"Unwrapped session key = %@, %@", unwrappedKey, unwrappedKey.keyData);
snej@13:     CAssert(unwrappedKey);
snej@14:     CAssertEq(unwrappedKey.algorithm, sessionKey.algorithm);
snej@14:     CAssertEq(unwrappedKey.keySizeInBits, sessionKey.keySizeInBits);
snej@13:     CAssertEqual(unwrappedKey.keyData, sessionKey.keyData);
snej@14: 
snej@14:     Log(@"Verifying that unwrapped key works");
snej@14:     NSData *decrypted = [unwrappedKey decryptData: encrypted];
snej@14:     CAssertEqual(decrypted, cleartext);
snej@14: #endif
snej@13: }
snej@13: 
snej@13: 
snej@8: TestCase(MYGenerateKeyPair) {
snej@8:     RequireTestCase(MYKeychain);
snej@8:     
snej@8:     Log(@"Generating key pair...");
snej@11:     MYPrivateKey *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: kTestCaseRSAKeySize];
snej@8:     MYPublicKey *publicKey = pair.publicKey;
snej@8:     Log(@"...created { %@ , %@ }.", pair, publicKey);
snej@8:     
snej@0:     @try{
snej@8:         TestUseKeyPair(pair);
snej@14:         TestWrapSessionKey(pair);
snej@3:         
snej@3:         [pair setName: @"Test KeyPair Label"];
snej@3:         CAssertEqual(pair.name, @"Test KeyPair Label");
snej@3:         CAssertEqual(publicKey.name, @"Test KeyPair Label");
snej@3: #if !TARGET_OS_IPHONE
snej@3:         [pair setComment: @"This key-pair was generated automatically by a test case."];
snej@3:         CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
snej@3:         CAssertEqual(publicKey.comment, @"This key-pair was generated automatically by a test case.");
snej@3: #endif
snej@3:         [pair setAlias: @"TestCase@mooseyard.com"];
snej@3:         CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
snej@3:         CAssertEqual(publicKey.alias, @"TestCase@mooseyard.com");
snej@0:         
snej@0:         CAssert([pair removeFromKeychain]);
snej@0:         Log(@"Removed key-pair.");
snej@0:         pair = nil;
snej@0:         
snej@0:     }@finally {
snej@0:         if (pair) {
snej@0:             if ([pair removeFromKeychain])
snej@0:                 Log(@"Removed key-pair from keychain.");
snej@0:             else
snej@0:                 Warn(@"Unable to remove test key-pair from keychain");
snej@0:         }
snej@0:     }
snej@0: }
snej@0: 
snej@0: 
snej@12: #if !TARGET_OS_IPHONE
snej@8: TestCase(MYUseIdentity) {
snej@8:     MYIdentity *me = nil;//[MYIdentity preferredIdentityForName: @"MYCryptoTest"];
snej@8:     if (!me) {
snej@8:         NSArray *idents = [[[MYKeychain allKeychains] enumerateIdentities] allObjects];
snej@8:         SFChooseIdentityPanel *panel = [SFChooseIdentityPanel sharedChooseIdentityPanel];
snej@8:         [panel setAlternateButtonTitle: @"Cancel"];
snej@8:         if ([panel my_runModalForIdentities: idents 
snej@8:                                     message: @"Choose an identity for the MYEncoder test case:"]
snej@8:             != NSOKButton) {
snej@8:             [NSException raise: NSGenericException format: @"User canceled"];
snej@8:         }
snej@8:         me = [panel my_identity];
snej@8:         [me makePreferredIdentityForName: @"MYCryptoTest"];
snej@8:     }
snej@8:     CAssert(me,@"No default identity has been set up in the Keychain");
snej@8:     TestUseKeyPair(me.privateKey);
snej@8: }
snej@12: #endif
snej@8: 
snej@0: 
snej@0: #pragma mark -
snej@0: #pragma mark KEYPAIR EXPORT:
snej@0: 
snej@0: 
snej@0: static void testKeyPairExportWithPrompt(BOOL withPrompt) {
snej@0:     MYKeychain *keychain = [MYKeychain allKeychains];
snej@0:     Log(@"Generating key pair...");
snej@11:     MYPrivateKey *pair = [keychain generateRSAKeyPairOfSize: kTestCaseRSAKeySize];
snej@0:     CAssert(pair);
snej@0:     CAssert(pair.keyRef);
snej@3:     CAssert(pair.publicKey.keyRef);
snej@0:     Log(@"...created pair.");
snej@0:     
snej@0:     @try{
snej@3:         NSData *pubKeyData = pair.publicKey.keyData;
snej@11:         CAssert(pubKeyData.length >= kTestCaseRSAKeySize/8);
snej@0:         [pair setName: @"Test KeyPair Label"];
snej@0:         CAssertEqual(pair.name, @"Test KeyPair Label");
snej@0: #if !TARGET_OS_IPHONE
snej@0:         [pair setComment: @"This key-pair was generated automatically by a test case."];
snej@0:         CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
snej@0: #endif
snej@0:         [pair setAlias: @"TestCase@mooseyard.com"];
snej@0:         CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
snej@0:         
snej@0: #if !TARGET_OS_IPHONE
snej@0:         Log(@"Exporting key-pair...");
snej@0:         NSString *passphrase = @"passphrase";
snej@0:         NSData *privKeyData;
snej@0:         if (withPrompt)
snej@3:             privKeyData = [pair exportKey];
snej@0:         else
snej@3:             privKeyData = [pair _exportKeyInFormat: kSecFormatWrappedOpenSSL
snej@3:                                           withPEM: YES
snej@3:                                        passphrase: passphrase];
snej@0:         Log(@"Exported data = %@ (%u bytes)", privKeyData,privKeyData.length);
snej@0:         CAssert(privKeyData);
snej@0:         [privKeyData writeToFile: @"ExportedPrivKey" atomically: YES];
snej@0: #endif
snej@0:         
snej@0:         // Check key lookup:
snej@0:         Log(@"Looking up public key of pair in keychain...");
snej@0:         MYSHA1Digest *digest = pair.publicKeyDigest;
snej@0:         MYPublicKey *foundKey = [keychain publicKeyWithDigest: digest];
snej@3:         CAssertEqual(foundKey, pair.publicKey);
snej@3:         CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.publicKey]);
snej@3:         MYPrivateKey *foundPair = [keychain privateKeyWithDigest: digest];
snej@0:         CAssertEqual(foundPair, pair);
snej@3:         CAssert([keychain.enumeratePrivateKeys.allObjects containsObject: pair]);
snej@0:         
snej@0:         Log(@"Removing key-pair from keychain...");
snej@0:         CAssert([pair removeFromKeychain]);
snej@0:         pair = nil;
snej@0:         CAssert([keychain publicKeyWithDigest: digest] == nil);
snej@0:         
snej@0: #if !TARGET_OS_IPHONE
snej@0:         Log(@"Importing key-pair...");
snej@0:         if (withPrompt) {
snej@0:             pair = [keychain importPublicKey: pubKeyData 
snej@0:                                   privateKey: privKeyData];
snej@0:         } else {
snej@3:             pair = [[[MYPrivateKey alloc] _initWithKeyData: privKeyData
snej@3:                                              publicKeyData: pubKeyData
snej@3:                                                forKeychain: keychain.keychainRefOrDefault
snej@3:                                                 passphrase: passphrase]
snej@0:                     autorelease];
snej@0:         }
snej@0:         CAssert(pair);
snej@3:         CAssertEqual(pair.publicKey.keyData, pubKeyData);
snej@0: #endif
snej@0:     }@finally {
snej@0:         if (pair) {
snej@0:             if ([pair removeFromKeychain])
snej@0:                 Log(@"Removed key-pair from keychain.");
snej@0:             else
snej@0:                 Warn(@"Unable to remove test key-pair from keychain");
snej@0:         }
snej@0:     }
snej@0: }
snej@0: 
snej@0: TestCase(KeyPairExport) {
snej@0:     RequireTestCase(MYKeychain);
snej@12:     RequireTestCase(MYGenerateKeyPair);
snej@0:     testKeyPairExportWithPrompt(NO);
snej@0: }
snej@0: 
snej@0: TestCase(KeyPairExportWithUI) {
snej@0:     RequireTestCase(KeyPairExport);
snej@0:     testKeyPairExportWithPrompt(YES);
snej@0: }
snej@0: 
snej@0: 
snej@0: #endif DEBUG
snej@0: