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@8: #import "MYCrypto+Cocoa.h" snej@0: #import "MYCrypto_Private.h" snej@0: snej@0: snej@0: #if DEBUG snej@0: 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: snej@0: TestCase(EnumerateKeys) { 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) { snej@0: Log(@"Found %@ -- name=%@", key, key.name); snej@0: } snej@0: snej@3: e = [[MYKeychain allKeychains] enumeratePrivateKeys]; snej@0: Log(@"Key-Pair Enumerator = %@", e); snej@0: CAssert(e); snej@3: for (MYPrivateKey *key in e) { snej@0: Log(@"Found %@ -- name=%@", key, key.name); snej@0: } snej@0: snej@0: 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) { snej@0: //Log(@"Found %@ -- name=%@, email=%@", cert, cert.commonName, cert.emailAddresses); 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@2: static void testSymmetricKey( CCAlgorithm algorithm, unsigned sizeInBits ) { snej@2: NSAutoreleasePool *pool = [NSAutoreleasePool new]; snej@2: Log(@"--- Testing %3u-bit #%i", sizeInBits, (int)algorithm); snej@2: // Generate key: snej@2: MYSymmetricKey *key = [MYSymmetricKey generateSymmetricKeyOfSize: sizeInBits snej@2: algorithm: algorithm]; snej@2: Log(@"Created %@", key); snej@2: CAssert(key); snej@2: CAssertEq(key.algorithm, algorithm); snej@2: CAssertEq(key.keySizeInBits, sizeInBits); snej@2: #if !TARGET_OS_IPHONE snej@2: CAssert(key.cssmKey != NULL); snej@2: #endif snej@2: snej@2: NSData *keyData = key.keyData; snej@2: Log(@"Key data = %@", keyData); snej@2: CAssertEq(keyData.length, sizeInBits/8); snej@2: snej@2: // Encrypt a small amount of text: snej@2: NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding]; snej@2: NSData *encrypted = [key encryptData: cleartext]; snej@2: Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted); snej@2: CAssert(encrypted.length >= cleartext.length); snej@2: NSData *decrypted = [key decryptData: encrypted]; snej@2: CAssertEqual(decrypted, cleartext); snej@2: snej@2: // Encrypt large binary data: snej@2: cleartext = [NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"]; snej@2: CAssert(cleartext); snej@2: encrypted = [key encryptData: cleartext]; snej@2: Log(@"Encrypted = %u bytes", encrypted.length); snej@2: CAssert(encrypted.length >= cleartext.length); snej@2: decrypted = [key decryptData: encrypted]; snej@2: CAssertEqual(decrypted, cleartext); snej@2: snej@2: #if !TARGET_OS_IPHONE snej@2: // Try reconstituting the key from its data: snej@2: NSData *exported = [key exportKeyInFormat: kSecFormatWrappedPKCS8 withPEM: NO]; snej@2: Log(@"Exported key: %@", exported); snej@2: // CAssert(exported); snej@2: //FIX: Exporting symmetric keys isn't working. Temporarily making this optional. snej@2: if (exported) { snej@2: CAssert(exported); snej@2: MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithKeyData: exported algorithm: algorithm]; snej@2: Log(@"Reconstituted as %@", key2); snej@2: CAssertEqual(key2,key); snej@2: decrypted = [key2 decryptData: encrypted]; snej@2: CAssertEqual(decrypted, cleartext); snej@2: } else snej@2: Warn(@"Unable to export key in PKCS8"); snej@2: #endif 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@2: for (int i=0; i= 512/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@3: RequireTestCase(MYPrivateKey); 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: