MYCryptoTest.m
author Jens Alfke <jens@mooseyard.com>
Fri Aug 07 11:24:53 2009 -0700 (2009-08-07)
changeset 28 54b373aa65ab
parent 23 39fec79de6e8
permissions -rw-r--r--
Fixed iPhone OS build. (issue 3)
snej@0
     1
//
snej@0
     2
//  MYCryptoTest.m
snej@0
     3
//  MYCrypto-iPhone
snej@0
     4
//
snej@0
     5
//  Created by Jens Alfke on 4/1/09.
snej@0
     6
//  Copyright 2009 Jens Alfke. All rights reserved.
snej@0
     7
//
snej@0
     8
snej@3
     9
#import "MYPublicKey.h"
snej@3
    10
#import "MYPrivateKey.h"
snej@0
    11
#import "MYKeychain.h"
snej@0
    12
#import "MYDigest.h"
snej@4
    13
#import "MYIdentity.h"
snej@12
    14
#if !TARGET_OS_IPHONE
snej@8
    15
#import "MYCrypto+Cocoa.h"
snej@12
    16
#endif
snej@0
    17
#import "MYCrypto_Private.h"
snej@0
    18
snej@0
    19
snej@0
    20
#if DEBUG
snej@0
    21
snej@11
    22
snej@11
    23
#define kTestCaseRSAKeySize 2048
snej@11
    24
snej@0
    25
#pragma mark -
snej@0
    26
#pragma mark KEYCHAIN:
snej@0
    27
snej@0
    28
snej@0
    29
TestCase(MYKeychain) {
snej@0
    30
    MYKeychain *kc = [MYKeychain defaultKeychain];
snej@0
    31
    Log(@"Default keychain = %@", kc);
snej@0
    32
    CAssert(kc);
snej@2
    33
#if !MYCRYPTO_USE_IPHONE_API
snej@0
    34
    CAssert(kc.path);
snej@0
    35
#endif
snej@0
    36
    
snej@0
    37
    kc = [MYKeychain allKeychains];
snej@0
    38
    Log(@"All-keychains = %@", kc);
snej@0
    39
    CAssert(kc);
snej@2
    40
#if !MYCRYPTO_USE_IPHONE_API
snej@0
    41
    CAssertEq(kc.path,nil);
snej@1
    42
#endif
snej@0
    43
}
snej@0
    44
snej@0
    45
jens@26
    46
#if MYCRYPTO_USE_IPHONE_API
jens@26
    47
TestCase(RemoveAll) {
jens@26
    48
    RequireTestCase(MYKeychain);
jens@26
    49
    MYKeychain *kc = [MYKeychain defaultKeychain];
jens@26
    50
    CAssert([kc removeAllCertificates]);
jens@26
    51
    CAssert([kc removeAllKeys]);
jens@26
    52
}
jens@26
    53
#endif
jens@26
    54
jens@26
    55
jens@23
    56
TestCase(Enumerate) {
jens@23
    57
    RequireTestCase(EnumeratePublicKeys);
jens@23
    58
    RequireTestCase(EnumeratePrivateKeys);
jens@23
    59
    RequireTestCase(EnumerateSymmetricKeys);
jens@23
    60
    RequireTestCase(EnumerateCerts);
jens@23
    61
    RequireTestCase(EnumerateIdentities);
jens@23
    62
}
jens@23
    63
jens@23
    64
jens@23
    65
TestCase(EnumeratePublicKeys) {
snej@0
    66
    RequireTestCase(MYKeychain);
snej@0
    67
    NSEnumerator *e = [[MYKeychain allKeychains] enumeratePublicKeys];
snej@0
    68
    Log(@"Public Key Enumerator = %@", e);
snej@0
    69
    CAssert(e);
snej@0
    70
    for (MYPublicKey *key in e) {
jens@23
    71
        Log(@"Trying public key %@", key.keyRef);
jens@23
    72
        @try{
jens@23
    73
            Log(@"Found %@ -- name=%@", key, key.name);
jens@23
    74
        }@catch (NSException *x) {
jens@23
    75
            Warn(@"Caught %@",x); //TEMP
jens@23
    76
        }
snej@0
    77
    }
jens@23
    78
}
jens@23
    79
jens@23
    80
TestCase(EnumeratePrivateKeys) {
jens@23
    81
    RequireTestCase(MYKeychain);
jens@23
    82
    NSEnumerator *e = [[MYKeychain allKeychains] enumeratePrivateKeys];
snej@0
    83
    Log(@"Key-Pair Enumerator = %@", e);
snej@0
    84
    CAssert(e);
snej@3
    85
    for (MYPrivateKey *key in e) {
jens@23
    86
        Log(@"Found %@ -- name=%@ --> %@", key, key.name, key.publicKey);
jens@23
    87
        CAssert(key.publicKey);
snej@0
    88
    }
jens@23
    89
}
jens@23
    90
jens@23
    91
TestCase(EnumerateSymmetricKeys) {
jens@23
    92
    RequireTestCase(MYKeychain);
jens@23
    93
    NSEnumerator *e = [[MYKeychain allKeychains] enumerateSymmetricKeys];
snej@0
    94
    Log(@"Symmetric Key Enumerator = %@", e);
snej@0
    95
    CAssert(e);
snej@0
    96
    for (MYSymmetricKey *key in e) {
snej@0
    97
        Log(@"Found %@ -- name=%@", key, key.name);
snej@0
    98
    }
snej@0
    99
}
snej@0
   100
snej@0
   101
snej@0
   102
TestCase(EnumerateCerts) {
snej@0
   103
    RequireTestCase(MYKeychain);
snej@0
   104
    NSEnumerator *e = [[MYKeychain allKeychains] enumerateCertificates];
snej@0
   105
    Log(@"Enumerator = %@", e);
snej@0
   106
    CAssert(e);
snej@0
   107
    for (MYCertificate *cert in e) {
jens@26
   108
        Log(@"Found %@ -- key=%@, name=%@, email=%@", cert,
jens@26
   109
            cert.publicKey, cert.commonName, cert.emailAddresses);
jens@23
   110
        CAssert(cert.publicKey);
jens@26
   111
        
jens@26
   112
#if MYCRYPTO_USE_IPHONE_API
jens@26
   113
        // Verify that cert has public-key-hash attribute:
jens@26
   114
        NSData *digestData = [MYKeychainItem _getAttribute: kSecAttrPublicKeyHash 
jens@26
   115
                                                    ofItem: cert.certificateRef];
jens@26
   116
        CAssert(digestData, @"SecCertificateRef missing kSecAttrPublicKeyHash");
jens@26
   117
        MYSHA1Digest *digest = [MYSHA1Digest digestFromDigestData: digestData];
jens@26
   118
        CAssertEqual(digest, cert.publicKey.publicKeyDigest);
jens@26
   119
        Log(@"kSecAttrPublicKeyHash matches: %@", digest);
jens@26
   120
#else
jens@26
   121
        MYSHA1Digest *digest = cert.publicKey.publicKeyDigest;
jens@26
   122
#endif
jens@26
   123
        // Verify that certificateWithDigest will find it:
jens@26
   124
        MYCertificate *cert2 = [[MYKeychain allKeychains] certificateWithDigest: digest];
jens@26
   125
        Log(@"certificateWithDigest(%@) returned %@", digest,cert2);
jens@26
   126
        CAssert(cert2);
jens@26
   127
        CAssertEqual(cert2.certificateData, cert.certificateData);
snej@0
   128
    }
snej@0
   129
}
snej@0
   130
snej@4
   131
TestCase(EnumerateIdentities) {
snej@4
   132
    RequireTestCase(MYKeychain);
snej@4
   133
    NSEnumerator *e = [[MYKeychain allKeychains] enumerateIdentities];
snej@4
   134
    Log(@"Enumerator = %@", e);
snej@4
   135
    CAssert(e);
snej@4
   136
    for (MYIdentity *ident in e) {
snej@8
   137
        Log(@"Found %@\n\tcommonName=%@\n\temails=(%@)\n\tkey=%@",
snej@4
   138
            ident, ident.commonName, 
snej@4
   139
            [ident.emailAddresses componentsJoinedByString: @", "],
snej@4
   140
            ident.privateKey);
jens@26
   141
        
jens@26
   142
        // Verify that identityWithDigest will find it:
jens@26
   143
        MYSHA1Digest *digest = ident.publicKey.publicKeyDigest;
jens@26
   144
        MYIdentity *ident2 = [[MYKeychain allKeychains] identityWithDigest:digest];
jens@26
   145
        Log(@"identityWithDigest(%@) returned %@", digest,ident2);
jens@26
   146
        CAssert(ident2);
jens@26
   147
        CAssertEqual(ident2.certificateData, ident.certificateData);
snej@4
   148
    }
snej@4
   149
}
snej@4
   150
snej@0
   151
snej@0
   152
#pragma mark -
snej@0
   153
#pragma mark SYMMETRIC KEYS:
snej@0
   154
snej@0
   155
snej@12
   156
static void testSymmetricKey( CCAlgorithm algorithm, unsigned sizeInBits, MYKeychain *inKeychain ) {
snej@2
   157
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
snej@12
   158
    MYSymmetricKey *key = nil;
snej@12
   159
    @try{
snej@12
   160
        Log(@"--- Testing %3u-bit #%i %s", sizeInBits, (int)algorithm,
snej@12
   161
            (inKeychain ?", in keychain" :""));
snej@12
   162
        // Generate key:
snej@12
   163
        if (inKeychain)
snej@12
   164
            key = [inKeychain generateSymmetricKeyOfSize: sizeInBits algorithm: algorithm];
snej@12
   165
        else
snej@12
   166
            key = [MYSymmetricKey generateSymmetricKeyOfSize: sizeInBits algorithm: algorithm];
snej@12
   167
        Log(@"Created %@", key);
jens@23
   168
        CAssert(key);
snej@12
   169
        CAssertEq(key.algorithm, algorithm);
snej@12
   170
        CAssertEq(key.keySizeInBits, sizeInBits);
snej@12
   171
    #if !TARGET_OS_IPHONE
snej@12
   172
        CAssert(key.cssmKey != NULL);
snej@12
   173
    #endif
snej@12
   174
        
snej@12
   175
        NSData *keyData = key.keyData;
snej@12
   176
        Log(@"Key data = %@", keyData);
snej@12
   177
        CAssertEq(keyData.length, sizeInBits/8);
snej@12
   178
        
snej@12
   179
        // Encrypt a small amount of text:
snej@12
   180
        Log(@"Testing encryption / decryption ...");
snej@12
   181
        NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@12
   182
        NSData *encrypted = [key encryptData: cleartext];
snej@12
   183
        Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted);
snej@12
   184
        CAssert(encrypted.length >= cleartext.length);
snej@12
   185
        NSData *decrypted = [key decryptData: encrypted];
snej@12
   186
        CAssertEqual(decrypted, cleartext);
snej@12
   187
        
snej@12
   188
        // Encrypt large binary data:
snej@12
   189
        cleartext = [NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"];
snej@12
   190
        CAssert(cleartext);
snej@12
   191
        encrypted = [key encryptData: cleartext];
snej@12
   192
        Log(@"Encrypted = %u bytes", encrypted.length);
snej@12
   193
        CAssert(encrypted.length >= cleartext.length);
snej@12
   194
        decrypted = [key decryptData: encrypted];
snej@12
   195
        CAssertEqual(decrypted, cleartext);
snej@12
   196
        
snej@12
   197
    #if 1
snej@12
   198
        Log(@"Testing initWithKeyData:...");
snej@12
   199
        MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithKeyData: keyData algorithm: algorithm];
snej@12
   200
        CAssert(key2);
snej@12
   201
        Log(@"Key from data = %@",key2);
snej@12
   202
        CAssertEqual(key2.keyData, keyData);
snej@12
   203
        CAssertEq(key2.algorithm, algorithm);
snej@12
   204
        CAssertEq(key2.keySizeInBits, sizeInBits);
snej@2
   205
        decrypted = [key2 decryptData: encrypted];
snej@2
   206
        CAssertEqual(decrypted, cleartext);
snej@12
   207
        [key2 release];
snej@12
   208
    #endif
snej@12
   209
snej@12
   210
    #if !TARGET_OS_IPHONE
snej@12
   211
        // Try exporting and importing a wrapped key:
snej@12
   212
        Log(@"Testing export/import...");
snej@13
   213
        NSData *exported = [key exportWrappedKeyWithPassphrasePrompt: @"Export symmetric key with passphrase:"];
snej@12
   214
        Log(@"Exported key: %@", exported);
snej@13
   215
    #if 1
snej@12
   216
        CAssert(exported);
snej@12
   217
    #else
snej@12
   218
        if (!exported)
snej@12
   219
            Warn(@"Unable to export wrapped key");
snej@12
   220
        else
snej@12
   221
    #endif
snej@12
   222
        {
snej@12
   223
            CAssert(exported);
jens@16
   224
            MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithWrappedKeyData: exported];
snej@12
   225
            Log(@"Reconstituted as %@", key2);
snej@12
   226
            CAssertEqual(key2.keyData,key.keyData);
snej@12
   227
            decrypted = [key2 decryptData: encrypted];
snej@12
   228
            CAssertEqual(decrypted, cleartext);
snej@12
   229
        }
snej@12
   230
    #endif
snej@12
   231
    }@finally{
snej@12
   232
        [key removeFromKeychain];
snej@12
   233
    }
snej@2
   234
    [pool drain];
snej@2
   235
}
snej@2
   236
snej@2
   237
snej@0
   238
TestCase(MYSymmetricKey) {
snej@0
   239
    #define kNTests 11
snej@0
   240
    static const CCAlgorithm kTestAlgorithms[kNTests] = {
snej@0
   241
        kCCAlgorithmAES128, kCCAlgorithmAES128, kCCAlgorithmAES128,
snej@0
   242
        kCCAlgorithmDES, kCCAlgorithm3DES,
snej@0
   243
        kCCAlgorithmCAST, kCCAlgorithmCAST, kCCAlgorithmCAST,
snej@0
   244
        kCCAlgorithmRC4, kCCAlgorithmRC4, kCCAlgorithmRC4};
snej@0
   245
    
snej@0
   246
    static const unsigned kTestBitSizes[kNTests] = {
snej@0
   247
        128, 192, 256,
snej@0
   248
        64, 3*64,
snej@0
   249
        40, 80, 128,
snej@0
   250
        32, 200, 512*8};
snej@0
   251
snej@12
   252
    for (int useKeychain=0; useKeychain<=1; useKeychain++)
snej@12
   253
        for (int testNo=0; testNo<kNTests; testNo++) 
snej@12
   254
            testSymmetricKey(kTestAlgorithms[testNo], 
snej@12
   255
                             kTestBitSizes[testNo],
snej@12
   256
                             useKeychain ?[MYKeychain defaultKeychain] :nil);
snej@12
   257
}
snej@12
   258
snej@12
   259
snej@14
   260
#if !TARGET_OS_IPHONE
snej@12
   261
TestCase(MYSymmetricKeyPassphrase) {
snej@12
   262
    Log(@"Prompting for raw passphrase --");
snej@12
   263
    NSString *rawPassphrase = [MYSymmetricKey promptForPassphraseWithAlertTitle: @"Raw Passphrase Test" 
snej@12
   264
                                                                    alertPrompt: @"Enter the passphrase 'Testing':"
snej@12
   265
                                                                       creating: YES];
snej@12
   266
    Log(@"You entered: '%@'", rawPassphrase);
snej@12
   267
    CAssertEqual(rawPassphrase, @"Testing");
snej@12
   268
    
snej@12
   269
    Log(@"Prompting for passphrase for key --");
snej@12
   270
    MYSymmetricKey *key = [MYSymmetricKey generateFromUserPassphraseWithAlertTitle: @"Symmetric Key Passphrase Test Case" 
snej@12
   271
                                                                       alertPrompt: @"Please enter a passphrase to generate a key:"
snej@12
   272
                                                                          creating: YES
snej@12
   273
                                                                              salt: @"wahooma"];
snej@12
   274
    Log(@"Key from passphrase = %@", key);
snej@12
   275
    CAssert(key);
snej@12
   276
snej@12
   277
    // Encrypt a small amount of text:
snej@12
   278
    Log(@"Testing encryption / decryption ...");
snej@12
   279
    NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@12
   280
    NSData *encrypted = [key encryptData: cleartext];
snej@12
   281
    Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted);
snej@12
   282
    CAssert(encrypted.length >= cleartext.length);
snej@12
   283
    NSData *decrypted = [key decryptData: encrypted];
snej@12
   284
    CAssertEqual(decrypted, cleartext);
snej@12
   285
    
snej@12
   286
    // Now test decryption by re-entered passphrase:
snej@12
   287
    Log(@"Testing decryption using re-entered passphrase...");
snej@12
   288
    MYSymmetricKey *key2 = [MYSymmetricKey generateFromUserPassphraseWithAlertTitle: @"Symmetric Key Passphrase Test Case" 
snej@12
   289
                                                                        alertPrompt: @"Please re-enter the same passphrase:" 
snej@12
   290
                                                                           creating: NO
snej@12
   291
                                                                               salt: @"wahooma"];
snej@12
   292
    Log(@"Key from passphrase = %@", key2);
snej@12
   293
    CAssert(key2);
snej@12
   294
    decrypted = [key2 decryptData: encrypted];
snej@12
   295
    CAssertEqual(decrypted, cleartext);
snej@0
   296
}
snej@14
   297
#endif
snej@0
   298
snej@0
   299
snej@0
   300
#pragma mark -
snej@0
   301
#pragma mark KEY-PAIRS:
snej@0
   302
snej@0
   303
snej@8
   304
static void TestUseKeyPair(MYPrivateKey *pair) {
snej@8
   305
    Log(@"---- TestUseKeyPair { %@ , %@ }.", pair, pair.publicKey);
snej@0
   306
    CAssert(pair);
snej@0
   307
    CAssert(pair.keyRef);
snej@3
   308
    MYPublicKey *publicKey = pair.publicKey;
snej@3
   309
    CAssert(publicKey.keyRef);
snej@0
   310
    
snej@8
   311
    NSData *pubKeyData = publicKey.keyData;
snej@8
   312
    Log(@"Public key = %@ (%u bytes)",pubKeyData,pubKeyData.length);
snej@8
   313
    CAssert(pubKeyData);
snej@8
   314
    
jens@21
   315
    NSData *modulus;
jens@21
   316
    unsigned exponent;
jens@21
   317
    CAssert([publicKey getModulus: &modulus exponent: &exponent]);
jens@21
   318
    Log(@"Modulus = %@", modulus);
jens@21
   319
    Log(@"Exponent = %u", exponent);
jens@21
   320
    CAssertEq(modulus.length, 2048U/8);
jens@21
   321
    CAssertEq(exponent,65537U); // this is what CDSA always seems to use
jens@21
   322
    
snej@8
   323
    MYSHA1Digest *pubKeyDigest = publicKey.publicKeyDigest;
snej@8
   324
    Log(@"Public key digest = %@",pubKeyDigest);
snej@8
   325
    CAssertEqual(pair.publicKeyDigest, pubKeyDigest);
snej@8
   326
    
snej@8
   327
    Log(@"SHA1 of pub key = %@", pubKeyData.my_SHA1Digest.asData);
snej@14
   328
    CAssertEqual(pubKeyData.my_SHA1Digest,pubKeyDigest);
snej@8
   329
    
snej@8
   330
    // Let's sign data:
snej@8
   331
    NSData *data = [@"This is a test. This is only a test!" dataUsingEncoding: NSUTF8StringEncoding];
snej@8
   332
    NSData *sig = [pair signData: data];
snej@8
   333
    Log(@"Signature = %@ (%u bytes)",sig,sig.length);
snej@8
   334
    CAssert(sig);
snej@8
   335
    CAssert( [publicKey verifySignature: sig ofData: data] );
snej@8
   336
    
snej@8
   337
    // Now let's encrypt...
snej@13
   338
    NSData *crypted = [publicKey rawEncryptData: data];
snej@8
   339
    Log(@"Encrypted = %@ (%u bytes)",crypted,crypted.length);
snej@8
   340
    CAssert(crypted);
snej@13
   341
    CAssertEqual([pair rawDecryptData: crypted], data);
snej@8
   342
    Log(@"Verified decryption.");
snej@8
   343
    
snej@8
   344
    // Test creating a standalone public key:
snej@8
   345
    MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: publicKey.keyRef];
snej@8
   346
    CAssert( [pub verifySignature: sig ofData: data] );
snej@8
   347
    Log(@"Verified signature.");
snej@8
   348
    
snej@8
   349
    // Test creating a public key from data:
snej@8
   350
    Log(@"Reconstituting public key from data...");
snej@8
   351
    pub = [[MYPublicKey alloc] initWithKeyData: pubKeyData];
snej@8
   352
    CAssert(pub);
snej@8
   353
    CAssertEqual(pub.keyData, pubKeyData);
snej@8
   354
    CAssertEqual(pub.publicKeyDigest, pubKeyDigest);
snej@8
   355
    CAssert( [pub verifySignature: sig ofData: data] );
jens@21
   356
    [pub release];
snej@8
   357
    Log(@"Verified signature from reconstituted key.");
jens@21
   358
    
jens@21
   359
    // Test creating a public key from modulus+exponent:
jens@21
   360
    Log(@"Reconstituting public key from modulus+exponent...");
jens@21
   361
    pub = [[MYPublicKey alloc] initWithModulus: modulus exponent: exponent];
jens@21
   362
    CAssertEqual(pub.keyData, pubKeyData);
jens@21
   363
    [pub release];
snej@8
   364
}
snej@8
   365
snej@8
   366
snej@14
   367
static void TestWrapSessionKey( MYPrivateKey *privateKey ) {
snej@14
   368
#if !TARGET_OS_IPHONE
snej@13
   369
    MYSymmetricKey *sessionKey = [MYSymmetricKey generateSymmetricKeyOfSize: 128 algorithm:kCCAlgorithmAES128];
snej@13
   370
    CAssert(sessionKey);
snej@14
   371
    NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
snej@14
   372
    NSData *encrypted = [sessionKey encryptData: cleartext];
snej@14
   373
snej@13
   374
    Log(@"Wrapping session key %@, %@", sessionKey, sessionKey.keyData);
snej@13
   375
    NSData *wrapped = [privateKey.publicKey wrapSessionKey: sessionKey];
snej@13
   376
    Log(@"Wrapped session key = %u bytes: %@", wrapped.length,wrapped);
snej@13
   377
    CAssert(wrapped.length >= 128/8);
snej@13
   378
    
snej@13
   379
    MYSymmetricKey *unwrappedKey = [privateKey unwrapSessionKey: wrapped
snej@13
   380
                                                  withAlgorithm: kCCAlgorithmAES128
snej@13
   381
                                                     sizeInBits: 128];
snej@13
   382
    Log(@"Unwrapped session key = %@, %@", unwrappedKey, unwrappedKey.keyData);
snej@13
   383
    CAssert(unwrappedKey);
snej@14
   384
    CAssertEq(unwrappedKey.algorithm, sessionKey.algorithm);
snej@14
   385
    CAssertEq(unwrappedKey.keySizeInBits, sessionKey.keySizeInBits);
snej@13
   386
    CAssertEqual(unwrappedKey.keyData, sessionKey.keyData);
snej@14
   387
snej@14
   388
    Log(@"Verifying that unwrapped key works");
snej@14
   389
    NSData *decrypted = [unwrappedKey decryptData: encrypted];
snej@14
   390
    CAssertEqual(decrypted, cleartext);
snej@14
   391
#endif
snej@13
   392
}
snej@13
   393
snej@13
   394
snej@8
   395
TestCase(MYGenerateKeyPair) {
snej@8
   396
    RequireTestCase(MYKeychain);
snej@8
   397
    
snej@8
   398
    Log(@"Generating key pair...");
snej@11
   399
    MYPrivateKey *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: kTestCaseRSAKeySize];
snej@8
   400
    MYPublicKey *publicKey = pair.publicKey;
snej@8
   401
    Log(@"...created { %@ , %@ }.", pair, publicKey);
snej@8
   402
    
snej@0
   403
    @try{
snej@8
   404
        TestUseKeyPair(pair);
snej@14
   405
        TestWrapSessionKey(pair);
snej@3
   406
        
snej@3
   407
        [pair setName: @"Test KeyPair Label"];
snej@3
   408
        CAssertEqual(pair.name, @"Test KeyPair Label");
snej@3
   409
        CAssertEqual(publicKey.name, @"Test KeyPair Label");
snej@3
   410
#if !TARGET_OS_IPHONE
snej@3
   411
        [pair setComment: @"This key-pair was generated automatically by a test case."];
snej@3
   412
        CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
snej@3
   413
        CAssertEqual(publicKey.comment, @"This key-pair was generated automatically by a test case.");
snej@3
   414
#endif
snej@3
   415
        [pair setAlias: @"TestCase@mooseyard.com"];
snej@3
   416
        CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
snej@3
   417
        CAssertEqual(publicKey.alias, @"TestCase@mooseyard.com");
snej@0
   418
        
snej@0
   419
        CAssert([pair removeFromKeychain]);
snej@0
   420
        Log(@"Removed key-pair.");
snej@0
   421
        pair = nil;
snej@0
   422
        
snej@0
   423
    }@finally {
snej@0
   424
        if (pair) {
snej@0
   425
            if ([pair removeFromKeychain])
snej@0
   426
                Log(@"Removed key-pair from keychain.");
snej@0
   427
            else
snej@0
   428
                Warn(@"Unable to remove test key-pair from keychain");
snej@0
   429
        }
snej@0
   430
    }
snej@0
   431
}
snej@0
   432
snej@0
   433
snej@12
   434
#if !TARGET_OS_IPHONE
snej@8
   435
TestCase(MYUseIdentity) {
snej@8
   436
    MYIdentity *me = nil;//[MYIdentity preferredIdentityForName: @"MYCryptoTest"];
snej@8
   437
    if (!me) {
snej@8
   438
        NSArray *idents = [[[MYKeychain allKeychains] enumerateIdentities] allObjects];
snej@8
   439
        SFChooseIdentityPanel *panel = [SFChooseIdentityPanel sharedChooseIdentityPanel];
snej@8
   440
        [panel setAlternateButtonTitle: @"Cancel"];
snej@8
   441
        if ([panel my_runModalForIdentities: idents 
snej@8
   442
                                    message: @"Choose an identity for the MYEncoder test case:"]
snej@8
   443
            != NSOKButton) {
snej@8
   444
            [NSException raise: NSGenericException format: @"User canceled"];
snej@8
   445
        }
snej@8
   446
        me = [panel my_identity];
snej@8
   447
        [me makePreferredIdentityForName: @"MYCryptoTest"];
snej@8
   448
    }
snej@8
   449
    CAssert(me,@"No default identity has been set up in the Keychain");
snej@8
   450
    TestUseKeyPair(me.privateKey);
snej@8
   451
}
snej@12
   452
#endif
snej@8
   453
snej@0
   454
snej@0
   455
#pragma mark -
snej@0
   456
#pragma mark KEYPAIR EXPORT:
snej@0
   457
snej@0
   458
snej@0
   459
static void testKeyPairExportWithPrompt(BOOL withPrompt) {
snej@0
   460
    MYKeychain *keychain = [MYKeychain allKeychains];
snej@0
   461
    Log(@"Generating key pair...");
snej@11
   462
    MYPrivateKey *pair = [keychain generateRSAKeyPairOfSize: kTestCaseRSAKeySize];
snej@0
   463
    CAssert(pair);
snej@0
   464
    CAssert(pair.keyRef);
snej@3
   465
    CAssert(pair.publicKey.keyRef);
snej@0
   466
    Log(@"...created pair.");
snej@0
   467
    
snej@0
   468
    @try{
snej@3
   469
        NSData *pubKeyData = pair.publicKey.keyData;
snej@11
   470
        CAssert(pubKeyData.length >= kTestCaseRSAKeySize/8);
snej@0
   471
        [pair setName: @"Test KeyPair Label"];
snej@0
   472
        CAssertEqual(pair.name, @"Test KeyPair Label");
snej@0
   473
#if !TARGET_OS_IPHONE
snej@0
   474
        [pair setComment: @"This key-pair was generated automatically by a test case."];
snej@0
   475
        CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
snej@0
   476
#endif
snej@0
   477
        [pair setAlias: @"TestCase@mooseyard.com"];
snej@0
   478
        CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
snej@0
   479
        
snej@0
   480
#if !TARGET_OS_IPHONE
snej@0
   481
        Log(@"Exporting key-pair...");
snej@0
   482
        NSString *passphrase = @"passphrase";
snej@0
   483
        NSData *privKeyData;
snej@0
   484
        if (withPrompt)
snej@3
   485
            privKeyData = [pair exportKey];
snej@0
   486
        else
snej@3
   487
            privKeyData = [pair _exportKeyInFormat: kSecFormatWrappedOpenSSL
snej@3
   488
                                          withPEM: YES
snej@3
   489
                                       passphrase: passphrase];
snej@0
   490
        Log(@"Exported data = %@ (%u bytes)", privKeyData,privKeyData.length);
snej@0
   491
        CAssert(privKeyData);
snej@0
   492
        [privKeyData writeToFile: @"ExportedPrivKey" atomically: YES];
snej@0
   493
#endif
snej@0
   494
        
snej@0
   495
        // Check key lookup:
snej@0
   496
        Log(@"Looking up public key of pair in keychain...");
snej@0
   497
        MYSHA1Digest *digest = pair.publicKeyDigest;
snej@0
   498
        MYPublicKey *foundKey = [keychain publicKeyWithDigest: digest];
snej@3
   499
        CAssertEqual(foundKey, pair.publicKey);
snej@3
   500
        CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.publicKey]);
snej@3
   501
        MYPrivateKey *foundPair = [keychain privateKeyWithDigest: digest];
snej@0
   502
        CAssertEqual(foundPair, pair);
snej@3
   503
        CAssert([keychain.enumeratePrivateKeys.allObjects containsObject: pair]);
snej@0
   504
        
snej@0
   505
        Log(@"Removing key-pair from keychain...");
snej@0
   506
        CAssert([pair removeFromKeychain]);
snej@0
   507
        pair = nil;
snej@0
   508
        CAssert([keychain publicKeyWithDigest: digest] == nil);
snej@0
   509
        
snej@0
   510
#if !TARGET_OS_IPHONE
snej@0
   511
        Log(@"Importing key-pair...");
snej@0
   512
        if (withPrompt) {
snej@0
   513
            pair = [keychain importPublicKey: pubKeyData 
snej@0
   514
                                  privateKey: privKeyData];
snej@0
   515
        } else {
snej@3
   516
            pair = [[[MYPrivateKey alloc] _initWithKeyData: privKeyData
snej@3
   517
                                             publicKeyData: pubKeyData
snej@3
   518
                                               forKeychain: keychain.keychainRefOrDefault
snej@3
   519
                                                passphrase: passphrase]
snej@0
   520
                    autorelease];
snej@0
   521
        }
snej@0
   522
        CAssert(pair);
snej@3
   523
        CAssertEqual(pair.publicKey.keyData, pubKeyData);
snej@0
   524
#endif
snej@0
   525
    }@finally {
snej@0
   526
        if (pair) {
snej@0
   527
            if ([pair removeFromKeychain])
snej@0
   528
                Log(@"Removed key-pair from keychain.");
snej@0
   529
            else
snej@0
   530
                Warn(@"Unable to remove test key-pair from keychain");
snej@0
   531
        }
snej@0
   532
    }
snej@0
   533
}
snej@0
   534
snej@0
   535
TestCase(KeyPairExport) {
snej@0
   536
    RequireTestCase(MYKeychain);
snej@12
   537
    RequireTestCase(MYGenerateKeyPair);
snej@0
   538
    testKeyPairExportWithPrompt(NO);
snej@0
   539
}
snej@0
   540
snej@0
   541
TestCase(KeyPairExportWithUI) {
snej@0
   542
    RequireTestCase(KeyPairExport);
snej@0
   543
    testKeyPairExportWithPrompt(YES);
snej@0
   544
}
snej@0
   545
snej@0
   546
snej@0
   547
#endif DEBUG
snej@0
   548