1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/MYCryptoTest.m Sat Apr 04 20:42:03 2009 -0700
1.3 @@ -0,0 +1,295 @@
1.4 +//
1.5 +// MYCryptoTest.m
1.6 +// MYCrypto-iPhone
1.7 +//
1.8 +// Created by Jens Alfke on 4/1/09.
1.9 +// Copyright 2009 Jens Alfke. All rights reserved.
1.10 +//
1.11 +
1.12 +#import "MYKeyPair.h"
1.13 +#import "MYKeychain.h"
1.14 +#import "MYDigest.h"
1.15 +#import "MYCrypto_Private.h"
1.16 +
1.17 +
1.18 +#if DEBUG
1.19 +
1.20 +#pragma mark -
1.21 +#pragma mark KEYCHAIN:
1.22 +
1.23 +
1.24 +TestCase(MYKeychain) {
1.25 + MYKeychain *kc = [MYKeychain defaultKeychain];
1.26 + Log(@"Default keychain = %@", kc);
1.27 + CAssert(kc);
1.28 +#if !USE_IPHONE_API
1.29 + CAssert(kc.path);
1.30 +#endif
1.31 +
1.32 + kc = [MYKeychain allKeychains];
1.33 + Log(@"All-keychains = %@", kc);
1.34 + CAssert(kc);
1.35 + CAssertEq(kc.path,nil);
1.36 +}
1.37 +
1.38 +
1.39 +TestCase(EnumerateKeys) {
1.40 + RequireTestCase(MYKeychain);
1.41 + NSEnumerator *e = [[MYKeychain allKeychains] enumeratePublicKeys];
1.42 + Log(@"Public Key Enumerator = %@", e);
1.43 + CAssert(e);
1.44 + for (MYPublicKey *key in e) {
1.45 + Log(@"Found %@ -- name=%@", key, key.name);
1.46 + }
1.47 +
1.48 + e = [[MYKeychain allKeychains] enumerateKeyPairs];
1.49 + Log(@"Key-Pair Enumerator = %@", e);
1.50 + CAssert(e);
1.51 + for (MYKeyPair *key in e) {
1.52 + Log(@"Found %@ -- name=%@", key, key.name);
1.53 + }
1.54 +
1.55 + e = [[MYKeychain allKeychains] enumerateSymmetricKeys];
1.56 + Log(@"Symmetric Key Enumerator = %@", e);
1.57 + CAssert(e);
1.58 + for (MYSymmetricKey *key in e) {
1.59 + Log(@"Found %@ -- name=%@", key, key.name);
1.60 + }
1.61 +}
1.62 +
1.63 +
1.64 +TestCase(EnumerateCerts) {
1.65 + RequireTestCase(MYKeychain);
1.66 + NSEnumerator *e = [[MYKeychain allKeychains] enumerateCertificates];
1.67 + Log(@"Enumerator = %@", e);
1.68 + CAssert(e);
1.69 + for (MYCertificate *cert in e) {
1.70 + //Log(@"Found %@ -- name=%@, email=%@", cert, cert.commonName, cert.emailAddresses);
1.71 + }
1.72 +}
1.73 +
1.74 +
1.75 +#pragma mark -
1.76 +#pragma mark SYMMETRIC KEYS:
1.77 +
1.78 +
1.79 +TestCase(MYSymmetricKey) {
1.80 + #define kNTests 11
1.81 + static const CCAlgorithm kTestAlgorithms[kNTests] = {
1.82 + kCCAlgorithmAES128, kCCAlgorithmAES128, kCCAlgorithmAES128,
1.83 + kCCAlgorithmDES, kCCAlgorithm3DES,
1.84 + kCCAlgorithmCAST, kCCAlgorithmCAST, kCCAlgorithmCAST,
1.85 + kCCAlgorithmRC4, kCCAlgorithmRC4, kCCAlgorithmRC4};
1.86 +
1.87 + static const unsigned kTestBitSizes[kNTests] = {
1.88 + 128, 192, 256,
1.89 + 64, 3*64,
1.90 + 40, 80, 128,
1.91 + 32, 200, 512*8};
1.92 +
1.93 + for (int i=0; i<kNTests; i++) {
1.94 + NSAutoreleasePool *pool = [NSAutoreleasePool new];
1.95 + Log(@"Test #%2i: algorithm = %3u-bit #%i", i+1, kTestBitSizes[i], (int)kTestAlgorithms[i]);
1.96 + // Generate key:
1.97 + MYSymmetricKey *key = [MYSymmetricKey generateSymmetricKeyOfSize: kTestBitSizes[i]
1.98 + algorithm: kTestAlgorithms[i]];
1.99 + CAssert(key);
1.100 +#if !TARGET_OS_IPHONE
1.101 + CAssert(key.cssmKey != NULL);
1.102 +#endif
1.103 + Log(@"Key data = %@", key.keyData);
1.104 + CAssertEq(key.keyData.length, kTestBitSizes[i]/8);
1.105 +
1.106 + // Encrypt a small amount of text:
1.107 + NSData *cleartext = [@"This is a test. This is only a test." dataUsingEncoding: NSUTF8StringEncoding];
1.108 + NSData *encrypted = [key encryptData: cleartext];
1.109 + Log(@"Encrypted = %u bytes: %@", encrypted.length, encrypted);
1.110 + CAssert(encrypted.length >= cleartext.length);
1.111 + NSData *decrypted = [key decryptData: encrypted];
1.112 + CAssertEqual(decrypted, cleartext);
1.113 +
1.114 + // Encrypt large binary data:
1.115 + cleartext = [NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"];
1.116 + CAssert(cleartext);
1.117 + encrypted = [key encryptData: cleartext];
1.118 + Log(@"Encrypted = %u bytes", encrypted.length);
1.119 + CAssert(encrypted.length >= cleartext.length);
1.120 + decrypted = [key decryptData: encrypted];
1.121 + CAssertEqual(decrypted, cleartext);
1.122 +
1.123 + [pool drain];
1.124 + }
1.125 +}
1.126 +
1.127 +
1.128 +#pragma mark -
1.129 +#pragma mark KEY-PAIRS:
1.130 +
1.131 +
1.132 +TestCase(KeyPair) {
1.133 + RequireTestCase(MYKeychain);
1.134 +
1.135 + Log(@"Generating key pair...");
1.136 + MYKeyPair *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512];
1.137 + CAssert(pair);
1.138 + CAssert(pair.keyRef);
1.139 + CAssert(pair.privateKeyRef);
1.140 + Log(@"...created pair.");
1.141 +
1.142 + @try{
1.143 + [pair setName: @"Test KeyPair Label"];
1.144 + CAssertEqual(pair.name, @"Test KeyPair Label");
1.145 +#if !TARGET_OS_IPHONE
1.146 + [pair setComment: @"This key-pair was generated automatically by a test case."];
1.147 + CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
1.148 +#endif
1.149 + [pair setAlias: @"TestCase@mooseyard.com"];
1.150 + CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
1.151 +
1.152 + NSData *pubKeyData = pair.keyData;
1.153 + Log(@"Public key = %@ (%u bytes)",pubKeyData,pubKeyData.length);
1.154 + CAssert(pubKeyData);
1.155 +
1.156 + MYSHA1Digest *pubKeyDigest = pair.publicKeyDigest;
1.157 + Log(@"Public key digest = %@",pubKeyDigest);
1.158 +
1.159 + Log(@"SHA1 of pub key = %@", pubKeyData.my_SHA1Digest.asData);
1.160 +
1.161 + NSData *data = [@"This is a test. This is only a test!" dataUsingEncoding: NSUTF8StringEncoding];
1.162 + NSData *sig = [pair signData: data];
1.163 + Log(@"Signature = %@ (%u bytes)",sig,sig.length);
1.164 + CAssert(sig);
1.165 + CAssert( [pair verifySignature: sig ofData: data] );
1.166 +
1.167 + // Test creating a standalone public key:
1.168 + MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: pair.keyRef];
1.169 + CAssert( [pub verifySignature: sig ofData: data] );
1.170 + Log(@"Verified signature.");
1.171 +
1.172 + // Test creating a public key from data:
1.173 + Log(@"Reconstituting public key from data...");
1.174 + pub = [[MYPublicKey alloc] initWithKeyData: pubKeyData];
1.175 + CAssert(pub);
1.176 + CAssertEqual(pub.keyData, pubKeyData);
1.177 + CAssertEqual(pub.publicKeyDigest, pubKeyDigest);
1.178 + CAssert( [pub verifySignature: sig ofData: data] );
1.179 + Log(@"Verified signature from reconstituted key.");
1.180 +
1.181 + // Now let's encrypt...
1.182 + NSData *crypted = [pub encryptData: data];
1.183 + Log(@"Encrypted = %@ (%u bytes)",crypted,crypted.length);
1.184 + CAssert(crypted);
1.185 +
1.186 + CAssertEqual([pair decryptData: crypted], data);
1.187 + Log(@"Verified decryption.");
1.188 +
1.189 + CAssert([pair removeFromKeychain]);
1.190 + Log(@"Removed key-pair.");
1.191 + pair = nil;
1.192 +
1.193 + }@finally {
1.194 + if (pair) {
1.195 + if ([pair removeFromKeychain])
1.196 + Log(@"Removed key-pair from keychain.");
1.197 + else
1.198 + Warn(@"Unable to remove test key-pair from keychain");
1.199 + }
1.200 + }
1.201 +}
1.202 +
1.203 +
1.204 +
1.205 +#pragma mark -
1.206 +#pragma mark KEYPAIR EXPORT:
1.207 +
1.208 +
1.209 +static void testKeyPairExportWithPrompt(BOOL withPrompt) {
1.210 + MYKeychain *keychain = [MYKeychain allKeychains];
1.211 + Log(@"Generating key pair...");
1.212 + MYKeyPair *pair = [keychain generateRSAKeyPairOfSize: 512];
1.213 + CAssert(pair);
1.214 + CAssert(pair.keyRef);
1.215 + CAssert(pair.privateKeyRef);
1.216 + Log(@"...created pair.");
1.217 +
1.218 + @try{
1.219 + NSData *pubKeyData = pair.keyData;
1.220 + CAssert(pubKeyData.length >= 512/8);
1.221 + [pair setName: @"Test KeyPair Label"];
1.222 + CAssertEqual(pair.name, @"Test KeyPair Label");
1.223 +#if !TARGET_OS_IPHONE
1.224 + [pair setComment: @"This key-pair was generated automatically by a test case."];
1.225 + CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
1.226 +#endif
1.227 + [pair setAlias: @"TestCase@mooseyard.com"];
1.228 + CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
1.229 +
1.230 +#if !TARGET_OS_IPHONE
1.231 + Log(@"Exporting key-pair...");
1.232 + NSString *passphrase = @"passphrase";
1.233 + NSData *privKeyData;
1.234 + if (withPrompt)
1.235 + privKeyData = [pair exportPrivateKey];
1.236 + else
1.237 + privKeyData = [pair _exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL
1.238 + withPEM: YES
1.239 + passphrase: passphrase];
1.240 + Log(@"Exported data = %@ (%u bytes)", privKeyData,privKeyData.length);
1.241 + CAssert(privKeyData);
1.242 + [privKeyData writeToFile: @"ExportedPrivKey" atomically: YES];
1.243 +#endif
1.244 +
1.245 + // Check key lookup:
1.246 + Log(@"Looking up public key of pair in keychain...");
1.247 + MYSHA1Digest *digest = pair.publicKeyDigest;
1.248 + MYPublicKey *foundKey = [keychain publicKeyWithDigest: digest];
1.249 + CAssertEqual(foundKey, pair.asPublicKey);
1.250 + CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.asPublicKey]);
1.251 + MYKeyPair *foundPair = [keychain keyPairWithDigest: digest];
1.252 + CAssertEqual(foundPair, pair);
1.253 + CAssert([keychain.enumerateKeyPairs.allObjects containsObject: pair]);
1.254 +
1.255 + Log(@"Removing key-pair from keychain...");
1.256 + CAssert([pair removeFromKeychain]);
1.257 + pair = nil;
1.258 + CAssert([keychain publicKeyWithDigest: digest] == nil);
1.259 +
1.260 +#if !TARGET_OS_IPHONE
1.261 + Log(@"Importing key-pair...");
1.262 + if (withPrompt) {
1.263 + pair = [keychain importPublicKey: pubKeyData
1.264 + privateKey: privKeyData];
1.265 + } else {
1.266 + pair = [[[MYKeyPair alloc] _initWithPublicKeyData: pubKeyData
1.267 + privateKeyData: privKeyData
1.268 + forKeychain: keychain.keychainRefOrDefault
1.269 + passphrase: passphrase]
1.270 + autorelease];
1.271 + }
1.272 + CAssert(pair);
1.273 + CAssertEqual(pair.keyData, pubKeyData);
1.274 +#endif
1.275 + }@finally {
1.276 + if (pair) {
1.277 + if ([pair removeFromKeychain])
1.278 + Log(@"Removed key-pair from keychain.");
1.279 + else
1.280 + Warn(@"Unable to remove test key-pair from keychain");
1.281 + }
1.282 + }
1.283 +}
1.284 +
1.285 +TestCase(KeyPairExport) {
1.286 + RequireTestCase(MYKeychain);
1.287 + RequireTestCase(KeyPair);
1.288 + testKeyPairExportWithPrompt(NO);
1.289 +}
1.290 +
1.291 +TestCase(KeyPairExportWithUI) {
1.292 + RequireTestCase(KeyPairExport);
1.293 + testKeyPairExportWithPrompt(YES);
1.294 +}
1.295 +
1.296 +
1.297 +#endif DEBUG
1.298 +