* Replaced MYKeyPair with MYPrivateKey.
authorsnej@snej-mbp.mtv.corp.google.com
Wed Apr 08 16:30:52 2009 -0700 (2009-04-08)
changeset 31dfe820d7ebe
parent 2 8982b8fada63
child 4 f4709533c816
* Replaced MYKeyPair with MYPrivateKey.
* Changed config files.
MYCrypto-iPhone.xcodeproj/project.pbxproj
MYCrypto.xcconfig
MYCrypto.xcodeproj/project.pbxproj
MYCryptoTest.m
MYCrypto_Debug.xcconfig
MYCrypto_Private.h
MYCrypto_Release.xcconfig
MYCryptor.m
MYDigest.h
MYDigest.m
MYKey-iPhone.m
MYKey.m
MYKeyPair.h
MYKeyPair.m
MYKeychain-iPhone.m
MYKeychain.h
MYKeychain.m
MYKeychainItem.m
MYPrivateKey.h
MYPrivateKey.m
MYPublicKey-iPhone.m
MYPublicKey.h
MYPublicKey.m
README.textile
     1.1 --- a/MYCrypto-iPhone.xcodeproj/project.pbxproj	Tue Apr 07 10:56:58 2009 -0700
     1.2 +++ b/MYCrypto-iPhone.xcodeproj/project.pbxproj	Wed Apr 08 16:30:52 2009 -0700
     1.3 @@ -11,14 +11,12 @@
     1.4  		1D60589B0D05DD56006BFB54 /* MYCrypto_iPhone_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* MYCrypto_iPhone_main.m */; };
     1.5  		1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
     1.6  		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
     1.7 -		273391A30F81E5E9009414D9 /* MYKeyPair-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */; };
     1.8 -		273391A50F81E606009414D9 /* MYPublicKey-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */; };
     1.9  		273391CD0F81EC70009414D9 /* MYCertificate-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391CC0F81EC70009414D9 /* MYCertificate-iPhone.m */; };
    1.10  		273392120F8283B8009414D9 /* MYKeychain-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273392110F8283B8009414D9 /* MYKeychain-iPhone.m */; };
    1.11 +		2748607F0F8D5E0600FE617B /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 2748607E0F8D5E0600FE617B /* MYPrivateKey.m */; };
    1.12  		276FB13F0F84090900CB326E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 276FB13E0F84090900CB326E /* Security.framework */; };
    1.13  		276FB16E0F84152B00CB326E /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB16D0F84152B00CB326E /* MYCryptoTest.m */; };
    1.14  		276FB3190F856AA700CB326E /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB3180F856AA700CB326E /* MYPublicKey.m */; };
    1.15 -		276FB3390F856AC300CB326E /* MYKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB3380F856AC300CB326E /* MYKeyPair.m */; };
    1.16  		276FB33B0F856ACB00CB326E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB33A0F856ACB00CB326E /* MYKeychain.m */; };
    1.17  		276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB34A0F856CA400CB326E /* MYCertificate.m */; };
    1.18  		27A430120F87C6C10063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E823110F81D56E0019BE60 /* MYKey.m */; };
    1.19 @@ -45,14 +43,13 @@
    1.20  		1D3623250D0F684500981E51 /* MYCrypto_iPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCrypto_iPhoneAppDelegate.m; sourceTree = "<group>"; };
    1.21  		1D6058910D05DD3D006BFB54 /* MYCrypto-iPhone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MYCrypto-iPhone.app"; sourceTree = BUILT_PRODUCTS_DIR; };
    1.22  		1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
    1.23 -		273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYKeyPair-iPhone.m"; sourceTree = "<group>"; };
    1.24 -		273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYPublicKey-iPhone.m"; sourceTree = "<group>"; };
    1.25  		273391CC0F81EC70009414D9 /* MYCertificate-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYCertificate-iPhone.m"; sourceTree = "<group>"; };
    1.26  		273392110F8283B8009414D9 /* MYKeychain-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYKeychain-iPhone.m"; sourceTree = "<group>"; };
    1.27 +		2748607D0F8D5DF200FE617B /* MYPrivateKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPrivateKey.h; sourceTree = "<group>"; };
    1.28 +		2748607E0F8D5E0600FE617B /* MYPrivateKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPrivateKey.m; sourceTree = "<group>"; };
    1.29  		276FB13E0F84090900CB326E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
    1.30  		276FB16D0F84152B00CB326E /* MYCryptoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptoTest.m; sourceTree = "<group>"; };
    1.31  		276FB3180F856AA700CB326E /* MYPublicKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPublicKey.m; sourceTree = "<group>"; };
    1.32 -		276FB3380F856AC300CB326E /* MYKeyPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeyPair.m; sourceTree = "<group>"; };
    1.33  		276FB33A0F856ACB00CB326E /* MYKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychain.m; sourceTree = "<group>"; };
    1.34  		276FB34A0F856CA400CB326E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = "<group>"; };
    1.35  		27A430130F87C6D50063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = "<group>"; };
    1.36 @@ -66,7 +63,6 @@
    1.37  		27E823120F81D56E0019BE60 /* MYKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychain.h; sourceTree = "<group>"; };
    1.38  		27E823140F81D56E0019BE60 /* MYKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychainItem.h; sourceTree = "<group>"; };
    1.39  		27E823150F81D56E0019BE60 /* MYKeychainItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychainItem.m; sourceTree = "<group>"; };
    1.40 -		27E823160F81D56E0019BE60 /* MYKeyPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeyPair.h; sourceTree = "<group>"; };
    1.41  		27E823180F81D56E0019BE60 /* MYPublicKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPublicKey.h; sourceTree = "<group>"; };
    1.42  		27E8231A0F81D56E0019BE60 /* MYCrypto_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCrypto_Private.h; sourceTree = "<group>"; };
    1.43  		27E8231B0F81D56E0019BE60 /* MYDigest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYDigest.h; sourceTree = "<group>"; };
    1.44 @@ -143,12 +139,10 @@
    1.45  				273392110F8283B8009414D9 /* MYKeychain-iPhone.m */,
    1.46  				27E823140F81D56E0019BE60 /* MYKeychainItem.h */,
    1.47  				27E823150F81D56E0019BE60 /* MYKeychainItem.m */,
    1.48 -				27E823160F81D56E0019BE60 /* MYKeyPair.h */,
    1.49 -				276FB3380F856AC300CB326E /* MYKeyPair.m */,
    1.50 -				273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */,
    1.51 +				2748607D0F8D5DF200FE617B /* MYPrivateKey.h */,
    1.52 +				2748607E0F8D5E0600FE617B /* MYPrivateKey.m */,
    1.53  				27E823180F81D56E0019BE60 /* MYPublicKey.h */,
    1.54  				276FB3180F856AA700CB326E /* MYPublicKey.m */,
    1.55 -				273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */,
    1.56  				27A430150F87C6DB0063D362 /* MYSymmetricKey.h */,
    1.57  				27A430130F87C6D50063D362 /* MYSymmetricKey.m */,
    1.58  				27E8231B0F81D56E0019BE60 /* MYDigest.h */,
    1.59 @@ -268,18 +262,16 @@
    1.60  				27E823390F81D5760019BE60 /* Logging.m in Sources */,
    1.61  				27E8233A0F81D5760019BE60 /* Test.m in Sources */,
    1.62  				27E8233B0F81D5760019BE60 /* MYErrorUtils.m in Sources */,
    1.63 -				273391A30F81E5E9009414D9 /* MYKeyPair-iPhone.m in Sources */,
    1.64 -				273391A50F81E606009414D9 /* MYPublicKey-iPhone.m in Sources */,
    1.65  				273391CD0F81EC70009414D9 /* MYCertificate-iPhone.m in Sources */,
    1.66  				273392120F8283B8009414D9 /* MYKeychain-iPhone.m in Sources */,
    1.67  				276FB16E0F84152B00CB326E /* MYCryptoTest.m in Sources */,
    1.68  				276FB3190F856AA700CB326E /* MYPublicKey.m in Sources */,
    1.69 -				276FB3390F856AC300CB326E /* MYKeyPair.m in Sources */,
    1.70  				276FB33B0F856ACB00CB326E /* MYKeychain.m in Sources */,
    1.71  				276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */,
    1.72  				27A430120F87C6C10063D362 /* MYKey.m in Sources */,
    1.73  				27A430140F87C6D50063D362 /* MYSymmetricKey.m in Sources */,
    1.74  				27FE453F0F87CC8500A86D63 /* MYKey-iPhone.m in Sources */,
    1.75 +				2748607F0F8D5E0600FE617B /* MYPrivateKey.m in Sources */,
    1.76  			);
    1.77  			runOnlyForDeploymentPostprocessing = 0;
    1.78  		};
     2.1 --- a/MYCrypto.xcconfig	Tue Apr 07 10:56:58 2009 -0700
     2.2 +++ b/MYCrypto.xcconfig	Wed Apr 08 16:30:52 2009 -0700
     2.3 @@ -6,6 +6,4 @@
     2.4  //  Copyright 2009 Jens Alfke. All rights reserved.
     2.5  //
     2.6  
     2.7 -#include "../MYUtilities/MYUtilities.xcconfig"
     2.8 -
     2.9  GCC_PREFIX_HEADER = ../MYUtilities/MYUtilities_Prefix.pch
     3.1 --- a/MYCrypto.xcodeproj/project.pbxproj	Tue Apr 07 10:56:58 2009 -0700
     3.2 +++ b/MYCrypto.xcodeproj/project.pbxproj	Wed Apr 08 16:30:52 2009 -0700
     3.3 @@ -7,6 +7,7 @@
     3.4  	objects = {
     3.5  
     3.6  /* Begin PBXBuildFile section */
     3.7 +		270B879F0F8C565000C56781 /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 270B879E0F8C565000C56781 /* MYPrivateKey.m */; };
     3.8  		27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */; };
     3.9  		27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E822A10F81C5660019BE60 /* MYKey.m */; };
    3.10  		27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42D410F858ED80063D362 /* MYSymmetricKey.m */; };
    3.11 @@ -14,7 +15,6 @@
    3.12  		27CFF4C20F7E8535000B418E /* MYCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B40F7E8535000B418E /* MYCryptor.m */; };
    3.13  		27CFF4C30F7E8535000B418E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B60F7E8535000B418E /* MYKeychain.m */; };
    3.14  		27CFF4C40F7E8535000B418E /* MYKeychainItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B80F7E8535000B418E /* MYKeychainItem.m */; };
    3.15 -		27CFF4C60F7E8535000B418E /* MYKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4BB0F7E8535000B418E /* MYKeyPair.m */; };
    3.16  		27CFF4C70F7E8535000B418E /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4BD0F7E8535000B418E /* MYPublicKey.m */; };
    3.17  		27CFF4C80F7E8535000B418E /* MYDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4C00F7E8535000B418E /* MYDigest.m */; };
    3.18  		27CFF4D50F7E8726000B418E /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4CE0F7E8726000B418E /* CollectionUtils.m */; };
    3.19 @@ -42,6 +42,9 @@
    3.20  
    3.21  /* Begin PBXFileReference section */
    3.22  		08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
    3.23 +		270B879D0F8C565000C56781 /* MYPrivateKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPrivateKey.h; sourceTree = "<group>"; };
    3.24 +		270B879E0F8C565000C56781 /* MYPrivateKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPrivateKey.m; sourceTree = "<group>"; };
    3.25 +		2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYCrypto_Release.xcconfig; sourceTree = "<group>"; };
    3.26  		27A42CBE0F8578B40063D362 /* MYCryptoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptoTest.m; sourceTree = "<group>"; };
    3.27  		27A42D400F858ED80063D362 /* MYSymmetricKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYSymmetricKey.h; sourceTree = "<group>"; };
    3.28  		27A42D410F858ED80063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = "<group>"; };
    3.29 @@ -56,8 +59,6 @@
    3.30  		27CFF4B60F7E8535000B418E /* MYKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychain.m; sourceTree = "<group>"; };
    3.31  		27CFF4B70F7E8535000B418E /* MYKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychainItem.h; sourceTree = "<group>"; };
    3.32  		27CFF4B80F7E8535000B418E /* MYKeychainItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychainItem.m; sourceTree = "<group>"; };
    3.33 -		27CFF4BA0F7E8535000B418E /* MYKeyPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeyPair.h; sourceTree = "<group>"; };
    3.34 -		27CFF4BB0F7E8535000B418E /* MYKeyPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeyPair.m; sourceTree = "<group>"; };
    3.35  		27CFF4BC0F7E8535000B418E /* MYPublicKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPublicKey.h; sourceTree = "<group>"; };
    3.36  		27CFF4BD0F7E8535000B418E /* MYPublicKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPublicKey.m; sourceTree = "<group>"; };
    3.37  		27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCrypto_Private.h; sourceTree = "<group>"; };
    3.38 @@ -103,6 +104,7 @@
    3.39  			isa = PBXGroup;
    3.40  			children = (
    3.41  				08FB7795FE84155DC02AAC07 /* Source */,
    3.42 +				270B881C0F8D055A00C56781 /* Internal */,
    3.43  				27CFF4CC0F7E86E8000B418E /* MYUtilities */,
    3.44  				C6859EA2029092E104C91782 /* Documentation */,
    3.45  				08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
    3.46 @@ -128,20 +130,15 @@
    3.47  				27CFF4B60F7E8535000B418E /* MYKeychain.m */,
    3.48  				27CFF4B70F7E8535000B418E /* MYKeychainItem.h */,
    3.49  				27CFF4B80F7E8535000B418E /* MYKeychainItem.m */,
    3.50 -				27CFF4BA0F7E8535000B418E /* MYKeyPair.h */,
    3.51 -				27CFF4BB0F7E8535000B418E /* MYKeyPair.m */,
    3.52  				27CFF4BC0F7E8535000B418E /* MYPublicKey.h */,
    3.53  				27CFF4BD0F7E8535000B418E /* MYPublicKey.m */,
    3.54 +				270B879D0F8C565000C56781 /* MYPrivateKey.h */,
    3.55 +				270B879E0F8C565000C56781 /* MYPrivateKey.m */,
    3.56  				27A42D400F858ED80063D362 /* MYSymmetricKey.h */,
    3.57  				27A42D410F858ED80063D362 /* MYSymmetricKey.m */,
    3.58  				27AAD97B0F892A0D0064DD7C /* MYCryptoConfig.h */,
    3.59 -				27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */,
    3.60 -				27A42CBE0F8578B40063D362 /* MYCryptoTest.m */,
    3.61 -				27CFF5210F7E94DF000B418E /* MYCrypto_main.m */,
    3.62  				27A42ECC0F8689D30063D362 /* MYCertGen.h */,
    3.63  				27A42ECD0F8689D30063D362 /* MYCertGen.m */,
    3.64 -				27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */,
    3.65 -				27CFF5400F7E9653000B418E /* MYCrypto_Debug.xcconfig */,
    3.66  				27EAF0390F8B2D700091AF95 /* README.textile */,
    3.67  			);
    3.68  			name = Source;
    3.69 @@ -163,6 +160,19 @@
    3.70  			name = Products;
    3.71  			sourceTree = "<group>";
    3.72  		};
    3.73 +		270B881C0F8D055A00C56781 /* Internal */ = {
    3.74 +			isa = PBXGroup;
    3.75 +			children = (
    3.76 +				27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */,
    3.77 +				27A42CBE0F8578B40063D362 /* MYCryptoTest.m */,
    3.78 +				27CFF5210F7E94DF000B418E /* MYCrypto_main.m */,
    3.79 +				27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */,
    3.80 +				27CFF5400F7E9653000B418E /* MYCrypto_Debug.xcconfig */,
    3.81 +				2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */,
    3.82 +			);
    3.83 +			name = Internal;
    3.84 +			sourceTree = "<group>";
    3.85 +		};
    3.86  		27CFF4CC0F7E86E8000B418E /* MYUtilities */ = {
    3.87  			isa = PBXGroup;
    3.88  			children = (
    3.89 @@ -198,6 +208,7 @@
    3.90  				8DD76F990486AA7600D96B5E /* Sources */,
    3.91  				8DD76F9B0486AA7600D96B5E /* Frameworks */,
    3.92  				8DD76F9E0486AA7600D96B5E /* CopyFiles */,
    3.93 +				27EAF0C60F8BD4ED0091AF95 /* ShellScript */,
    3.94  			);
    3.95  			buildRules = (
    3.96  			);
    3.97 @@ -226,6 +237,23 @@
    3.98  		};
    3.99  /* End PBXProject section */
   3.100  
   3.101 +/* Begin PBXShellScriptBuildPhase section */
   3.102 +		27EAF0C60F8BD4ED0091AF95 /* ShellScript */ = {
   3.103 +			isa = PBXShellScriptBuildPhase;
   3.104 +			buildActionMask = 2147483647;
   3.105 +			files = (
   3.106 +			);
   3.107 +			inputPaths = (
   3.108 +			);
   3.109 +			outputPaths = (
   3.110 +			);
   3.111 +			runOnlyForDeploymentPostprocessing = 0;
   3.112 +			shellPath = /bin/csh;
   3.113 +			shellScript = "doxygen\n";
   3.114 +			showEnvVarsInLog = 0;
   3.115 +		};
   3.116 +/* End PBXShellScriptBuildPhase section */
   3.117 +
   3.118  /* Begin PBXSourcesBuildPhase section */
   3.119  		8DD76F990486AA7600D96B5E /* Sources */ = {
   3.120  			isa = PBXSourcesBuildPhase;
   3.121 @@ -235,7 +263,6 @@
   3.122  				27CFF4C20F7E8535000B418E /* MYCryptor.m in Sources */,
   3.123  				27CFF4C30F7E8535000B418E /* MYKeychain.m in Sources */,
   3.124  				27CFF4C40F7E8535000B418E /* MYKeychainItem.m in Sources */,
   3.125 -				27CFF4C60F7E8535000B418E /* MYKeyPair.m in Sources */,
   3.126  				27CFF4C70F7E8535000B418E /* MYPublicKey.m in Sources */,
   3.127  				27CFF4C80F7E8535000B418E /* MYDigest.m in Sources */,
   3.128  				27CFF4D50F7E8726000B418E /* CollectionUtils.m in Sources */,
   3.129 @@ -247,6 +274,7 @@
   3.130  				27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */,
   3.131  				27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */,
   3.132  				27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */,
   3.133 +				270B879F0F8C565000C56781 /* MYPrivateKey.m in Sources */,
   3.134  			);
   3.135  			runOnlyForDeploymentPostprocessing = 0;
   3.136  		};
   3.137 @@ -264,6 +292,7 @@
   3.138  		};
   3.139  		1DEB927608733DD40010E9CD /* Release */ = {
   3.140  			isa = XCBuildConfiguration;
   3.141 +			baseConfigurationReference = 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */;
   3.142  			buildSettings = {
   3.143  				INSTALL_PATH = /usr/local/bin;
   3.144  				PRODUCT_NAME = MYCrypto;
   3.145 @@ -279,7 +308,7 @@
   3.146  		};
   3.147  		1DEB927A08733DD40010E9CD /* Release */ = {
   3.148  			isa = XCBuildConfiguration;
   3.149 -			baseConfigurationReference = 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */;
   3.150 +			baseConfigurationReference = 2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */;
   3.151  			buildSettings = {
   3.152  			};
   3.153  			name = Release;
     4.1 --- a/MYCryptoTest.m	Tue Apr 07 10:56:58 2009 -0700
     4.2 +++ b/MYCryptoTest.m	Wed Apr 08 16:30:52 2009 -0700
     4.3 @@ -6,7 +6,8 @@
     4.4  //  Copyright 2009 Jens Alfke. All rights reserved.
     4.5  //
     4.6  
     4.7 -#import "MYKeyPair.h"
     4.8 +#import "MYPublicKey.h"
     4.9 +#import "MYPrivateKey.h"
    4.10  #import "MYKeychain.h"
    4.11  #import "MYDigest.h"
    4.12  #import "MYCrypto_Private.h"
    4.13 @@ -44,10 +45,10 @@
    4.14          Log(@"Found %@ -- name=%@", key, key.name);
    4.15      }
    4.16      
    4.17 -    e = [[MYKeychain allKeychains] enumerateKeyPairs];
    4.18 +    e = [[MYKeychain allKeychains] enumeratePrivateKeys];
    4.19      Log(@"Key-Pair Enumerator = %@", e);
    4.20      CAssert(e);
    4.21 -    for (MYKeyPair *key in e) {
    4.22 +    for (MYPrivateKey *key in e) {
    4.23          Log(@"Found %@ -- name=%@", key, key.name);
    4.24      }
    4.25      
    4.26 @@ -153,32 +154,25 @@
    4.27  #pragma mark KEY-PAIRS:
    4.28  
    4.29  
    4.30 -TestCase(KeyPair) {
    4.31 +TestCase(MYPrivateKey) {
    4.32      RequireTestCase(MYKeychain);
    4.33      
    4.34      Log(@"Generating key pair...");
    4.35 -    MYKeyPair *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512];
    4.36 +    MYPrivateKey *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512];
    4.37 +    Log(@"...created { %@ , %@ }.", pair, pair.publicKey);
    4.38      CAssert(pair);
    4.39      CAssert(pair.keyRef);
    4.40 -    CAssert(pair.privateKeyRef);
    4.41 -    Log(@"...created pair.");
    4.42 +    MYPublicKey *publicKey = pair.publicKey;
    4.43 +    CAssert(publicKey.keyRef);
    4.44      
    4.45      @try{
    4.46 -        [pair setName: @"Test KeyPair Label"];
    4.47 -        CAssertEqual(pair.name, @"Test KeyPair Label");
    4.48 -#if !TARGET_OS_IPHONE
    4.49 -        [pair setComment: @"This key-pair was generated automatically by a test case."];
    4.50 -        CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
    4.51 -#endif
    4.52 -        [pair setAlias: @"TestCase@mooseyard.com"];
    4.53 -        CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
    4.54 -        
    4.55 -        NSData *pubKeyData = pair.keyData;
    4.56 +        NSData *pubKeyData = publicKey.keyData;
    4.57          Log(@"Public key = %@ (%u bytes)",pubKeyData,pubKeyData.length);
    4.58          CAssert(pubKeyData);
    4.59          
    4.60 -        MYSHA1Digest *pubKeyDigest = pair.publicKeyDigest;
    4.61 +        MYSHA1Digest *pubKeyDigest = publicKey.publicKeyDigest;
    4.62          Log(@"Public key digest = %@",pubKeyDigest);
    4.63 +        CAssertEqual(pair.publicKeyDigest, pubKeyDigest);
    4.64          
    4.65          Log(@"SHA1 of pub key = %@", pubKeyData.my_SHA1Digest.asData);
    4.66          
    4.67 @@ -186,10 +180,22 @@
    4.68          NSData *sig = [pair signData: data];
    4.69          Log(@"Signature = %@ (%u bytes)",sig,sig.length);
    4.70          CAssert(sig);
    4.71 -        CAssert( [pair verifySignature: sig ofData: data] );
    4.72 +        CAssert( [publicKey verifySignature: sig ofData: data] );
    4.73 +        
    4.74 +        [pair setName: @"Test KeyPair Label"];
    4.75 +        CAssertEqual(pair.name, @"Test KeyPair Label");
    4.76 +        CAssertEqual(publicKey.name, @"Test KeyPair Label");
    4.77 +#if !TARGET_OS_IPHONE
    4.78 +        [pair setComment: @"This key-pair was generated automatically by a test case."];
    4.79 +        CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case.");
    4.80 +        CAssertEqual(publicKey.comment, @"This key-pair was generated automatically by a test case.");
    4.81 +#endif
    4.82 +        [pair setAlias: @"TestCase@mooseyard.com"];
    4.83 +        CAssertEqual(pair.alias, @"TestCase@mooseyard.com");
    4.84 +        CAssertEqual(publicKey.alias, @"TestCase@mooseyard.com");
    4.85          
    4.86          // Test creating a standalone public key:
    4.87 -        MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: pair.keyRef];
    4.88 +        MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: publicKey.keyRef];
    4.89          CAssert( [pub verifySignature: sig ofData: data] );
    4.90          Log(@"Verified signature.");
    4.91  
    4.92 @@ -233,14 +239,14 @@
    4.93  static void testKeyPairExportWithPrompt(BOOL withPrompt) {
    4.94      MYKeychain *keychain = [MYKeychain allKeychains];
    4.95      Log(@"Generating key pair...");
    4.96 -    MYKeyPair *pair = [keychain generateRSAKeyPairOfSize: 512];
    4.97 +    MYPrivateKey *pair = [keychain generateRSAKeyPairOfSize: 512];
    4.98      CAssert(pair);
    4.99      CAssert(pair.keyRef);
   4.100 -    CAssert(pair.privateKeyRef);
   4.101 +    CAssert(pair.publicKey.keyRef);
   4.102      Log(@"...created pair.");
   4.103      
   4.104      @try{
   4.105 -        NSData *pubKeyData = pair.keyData;
   4.106 +        NSData *pubKeyData = pair.publicKey.keyData;
   4.107          CAssert(pubKeyData.length >= 512/8);
   4.108          [pair setName: @"Test KeyPair Label"];
   4.109          CAssertEqual(pair.name, @"Test KeyPair Label");
   4.110 @@ -256,11 +262,11 @@
   4.111          NSString *passphrase = @"passphrase";
   4.112          NSData *privKeyData;
   4.113          if (withPrompt)
   4.114 -            privKeyData = [pair exportPrivateKey];
   4.115 +            privKeyData = [pair exportKey];
   4.116          else
   4.117 -            privKeyData = [pair _exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL
   4.118 -                                                  withPEM: YES
   4.119 -                                               passphrase: passphrase];
   4.120 +            privKeyData = [pair _exportKeyInFormat: kSecFormatWrappedOpenSSL
   4.121 +                                          withPEM: YES
   4.122 +                                       passphrase: passphrase];
   4.123          Log(@"Exported data = %@ (%u bytes)", privKeyData,privKeyData.length);
   4.124          CAssert(privKeyData);
   4.125          [privKeyData writeToFile: @"ExportedPrivKey" atomically: YES];
   4.126 @@ -270,11 +276,11 @@
   4.127          Log(@"Looking up public key of pair in keychain...");
   4.128          MYSHA1Digest *digest = pair.publicKeyDigest;
   4.129          MYPublicKey *foundKey = [keychain publicKeyWithDigest: digest];
   4.130 -        CAssertEqual(foundKey, pair.asPublicKey);
   4.131 -        CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.asPublicKey]);
   4.132 -        MYKeyPair *foundPair = [keychain keyPairWithDigest: digest];
   4.133 +        CAssertEqual(foundKey, pair.publicKey);
   4.134 +        CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.publicKey]);
   4.135 +        MYPrivateKey *foundPair = [keychain privateKeyWithDigest: digest];
   4.136          CAssertEqual(foundPair, pair);
   4.137 -        CAssert([keychain.enumerateKeyPairs.allObjects containsObject: pair]);
   4.138 +        CAssert([keychain.enumeratePrivateKeys.allObjects containsObject: pair]);
   4.139          
   4.140          Log(@"Removing key-pair from keychain...");
   4.141          CAssert([pair removeFromKeychain]);
   4.142 @@ -287,14 +293,14 @@
   4.143              pair = [keychain importPublicKey: pubKeyData 
   4.144                                    privateKey: privKeyData];
   4.145          } else {
   4.146 -            pair = [[[MYKeyPair alloc] _initWithPublicKeyData: pubKeyData
   4.147 -                                               privateKeyData: privKeyData
   4.148 -                                                  forKeychain: keychain.keychainRefOrDefault
   4.149 -                                                   passphrase: passphrase]
   4.150 +            pair = [[[MYPrivateKey alloc] _initWithKeyData: privKeyData
   4.151 +                                             publicKeyData: pubKeyData
   4.152 +                                               forKeychain: keychain.keychainRefOrDefault
   4.153 +                                                passphrase: passphrase]
   4.154                      autorelease];
   4.155          }
   4.156          CAssert(pair);
   4.157 -        CAssertEqual(pair.keyData, pubKeyData);
   4.158 +        CAssertEqual(pair.publicKey.keyData, pubKeyData);
   4.159  #endif
   4.160      }@finally {
   4.161          if (pair) {
   4.162 @@ -308,7 +314,7 @@
   4.163  
   4.164  TestCase(KeyPairExport) {
   4.165      RequireTestCase(MYKeychain);
   4.166 -    RequireTestCase(KeyPair);
   4.167 +    RequireTestCase(MYPrivateKey);
   4.168      testKeyPairExportWithPrompt(NO);
   4.169  }
   4.170  
     5.1 --- a/MYCrypto_Debug.xcconfig	Tue Apr 07 10:56:58 2009 -0700
     5.2 +++ b/MYCrypto_Debug.xcconfig	Wed Apr 08 16:30:52 2009 -0700
     5.3 @@ -6,6 +6,7 @@
     5.4  //  Copyright 2009 Jens Alfke. All rights reserved.
     5.5  //
     5.6  
     5.7 +#include "../MYUtilities/MYUtilities_Debug.xcconfig"
     5.8  #include "MYCrypto.xcconfig"
     5.9  
    5.10  GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1
     6.1 --- a/MYCrypto_Private.h	Tue Apr 07 10:56:58 2009 -0700
     6.2 +++ b/MYCrypto_Private.h	Wed Apr 08 16:30:52 2009 -0700
     6.3 @@ -10,7 +10,8 @@
     6.4  #import "MYKeychain.h"
     6.5  #import "MYKey.h"
     6.6  #import "MYSymmetricKey.h"
     6.7 -#import "MYKeyPair.h"
     6.8 +#import "MYPublicKey.h"
     6.9 +#import "MYPrivateKey.h"
    6.10  #import "MYCertificate.h"
    6.11  #import "Test.h"
    6.12  #import <Security/Security.h>
    6.13 @@ -52,9 +53,13 @@
    6.14  - (id) _initWithKeyData: (NSData*)data
    6.15              forKeychain: (SecKeychainRef)keychain;
    6.16  @property (readonly) SecExternalItemType keyType;
    6.17 +@property (readonly) MYSHA1Digest* _keyDigest;
    6.18 +- (NSData*) _crypt: (NSData *)data operation: (BOOL) op;    // YES to encrypt, NO to decrypt
    6.19  #if !MYCRYPTO_USE_IPHONE_API
    6.20  @property (readonly) const CSSM_KEY* cssmKey;
    6.21  - (NSData*) exportKeyInFormat: (SecExternalFormat)format withPEM: (BOOL)withPEM;
    6.22 +- (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm;
    6.23 +- (CSSM_CC_HANDLE) _createPassThroughContext;
    6.24  #endif
    6.25  @property (readonly) NSArray* _itemList;
    6.26  @end
    6.27 @@ -68,27 +73,26 @@
    6.28  
    6.29  
    6.30  @interface MYPublicKey (Private)
    6.31 -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key;
    6.32  - (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr;
    6.33  @end
    6.34  
    6.35  
    6.36 -@interface MYKeyPair (Private)
    6.37 -+ (MYKeyPair*) _generateRSAKeyPairOfSize: (unsigned)keySize
    6.38 -                            inKeychain: (MYKeychain*)keychain;
    6.39 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
    6.40 -               privateKeyData: (NSData*)privKeyData
    6.41 -                  forKeychain: (SecKeychainRef)keychain
    6.42 -                   alertTitle: (NSString*)title
    6.43 -                  alertPrompt: (NSString*)prompt;
    6.44 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
    6.45 -               privateKeyData: (NSData*)privKeyData
    6.46 -                  forKeychain: (SecKeychainRef)keychain 
    6.47 -                   passphrase: (NSString*)passphrase;
    6.48 +@interface MYPrivateKey (Private)
    6.49 ++ (MYPrivateKey*) _generateRSAKeyPairOfSize: (unsigned)keySize
    6.50 +                                 inKeychain: (MYKeychain*)keychain;
    6.51 +- (id) _initWithKeyData: (NSData*)privKeyData 
    6.52 +          publicKeyData: (NSData*)pubKeyData
    6.53 +            forKeychain: (SecKeychainRef)keychain 
    6.54 +             alertTitle: (NSString*)title
    6.55 +            alertPrompt: (NSString*)prompt;
    6.56 +- (id) _initWithKeyData: (NSData*)privKeyData 
    6.57 +          publicKeyData: (NSData*)pubKeyData
    6.58 +            forKeychain: (SecKeychainRef)keychain 
    6.59 +             passphrase: (NSString*)passphrase;
    6.60  #if !TARGET_OS_IPHONE
    6.61 -- (NSData*) _exportPrivateKeyInFormat: (SecExternalFormat)format
    6.62 -                              withPEM: (BOOL)withPEM
    6.63 -                           passphrase: (NSString*)passphrase;
    6.64 +- (NSData*) _exportKeyInFormat: (SecExternalFormat)format
    6.65 +                       withPEM: (BOOL)withPEM
    6.66 +                    passphrase: (NSString*)passphrase;
    6.67  #endif
    6.68  @end
    6.69  
    6.70 @@ -102,8 +106,6 @@
    6.71  #endif
    6.72  
    6.73  
    6.74 -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op);
    6.75 -
    6.76  #undef check
    6.77  BOOL check(OSStatus err, NSString *what);
    6.78  
    6.79 @@ -114,5 +116,4 @@
    6.80                      SecExternalItemType type,
    6.81                      SecKeychainRef keychain,
    6.82                      SecKeyImportExportParameters *params /*non-null*/);
    6.83 -CSSM_CC_HANDLE cssmCreateSignatureContext(SecKeyRef key);
    6.84  #endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/MYCrypto_Release.xcconfig	Wed Apr 08 16:30:52 2009 -0700
     7.3 @@ -0,0 +1,10 @@
     7.4 +//
     7.5 +//  MYCrypto_Release.xcconfig
     7.6 +//  MYCrypto
     7.7 +//
     7.8 +//  Created by Jens Alfke on 4/8/09.
     7.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
    7.10 +//
    7.11 +
    7.12 +#include "../MYUtilities/MYUtilities_Release.xcconfig"
    7.13 +#include "MYCrypto.xcconfig"
     8.1 --- a/MYCryptor.m	Tue Apr 07 10:56:58 2009 -0700
     8.2 +++ b/MYCryptor.m	Wed Apr 08 16:30:52 2009 -0700
     8.3 @@ -57,11 +57,14 @@
     8.4           fromPassphrase: (NSString*)passphrase
     8.5                     salt: (id)salt
     8.6  {
     8.7 +    // This follows algorithm PBKDF1 from PKCS#5 v2.0, with Hash=SHA-256 and c=13.
     8.8      Assert(passphrase);
     8.9      Assert(salt);
    8.10      passphrase = $sprintf(@"MYCrypto|%@|%@", passphrase, salt);
    8.11      size_t lengthInBytes = (lengthInBits + 7)/8;
    8.12      MYDigest *digest = [[passphrase dataUsingEncoding: NSUTF8StringEncoding] my_SHA256Digest];
    8.13 +    for (int i=0; i<12; i++)
    8.14 +        digest = digest.asData.my_SHA256Digest;
    8.15      if (lengthInBytes <= digest.length)
    8.16          return [digest.asData subdataWithRange: NSMakeRange(0,lengthInBytes)];
    8.17      else
    8.18 @@ -126,7 +129,7 @@
    8.19  
    8.20  - (BOOL) _outputBytes: (const void*)bytes length: (size_t)length {
    8.21      if (_outputStream) {
    8.22 -        NSInteger written = [_outputStream write: bytes maxLength: length];
    8.23 +        size_t written = [_outputStream write: bytes maxLength: length];
    8.24          if (written < 0) {
    8.25              self.error = _outputStream.streamError;
    8.26              if (_error)
     9.1 --- a/MYDigest.h	Tue Apr 07 10:56:58 2009 -0700
     9.2 +++ b/MYDigest.h	Wed Apr 08 16:30:52 2009 -0700
     9.3 @@ -84,6 +84,7 @@
     9.4  /** Create a MYSHA1Digest object given an existing raw SHA-1 digest. */
     9.5  + (MYSHA1Digest*) digestFromRawSHA1Digest: (const RawSHA1Digest*)rawDigest;
     9.6  
     9.7 +/** The SHA-1 digest as a C struct */
     9.8  @property (readonly) const RawSHA1Digest* rawSHA1Digest;
     9.9  
    9.10  @end
    9.11 @@ -104,6 +105,7 @@
    9.12  /** Create a MYSHA256Digest object given an existing raw SHA-1 digest. */
    9.13  + (MYSHA256Digest*) digestFromRawSHA256Digest: (const RawSHA256Digest*)rawDigest;
    9.14  
    9.15 +/** The SHA-256 digest as a C struct */
    9.16  @property (readonly) const RawSHA256Digest* rawSHA256Digest;
    9.17  
    9.18  @end
    10.1 --- a/MYDigest.m	Tue Apr 07 10:56:58 2009 -0700
    10.2 +++ b/MYDigest.m	Wed Apr 08 16:30:52 2009 -0700
    10.3 @@ -90,7 +90,7 @@
    10.4      if( !cStr || strlen(cStr)!=2*length )
    10.5          return nil;
    10.6      uint8_t digest[length];
    10.7 -    for( int i=0; i<length; i++ ) {
    10.8 +    for( size_t i=0; i<length; i++ ) {
    10.9          if( sscanf(cStr, "%2hhx", &digest[i]) != 1 )
   10.10              return nil;
   10.11          cStr += 2;
   10.12 @@ -158,7 +158,7 @@
   10.13      size_t length = self.length;
   10.14      char out[2*length+1];
   10.15      char *dst = &out[0];
   10.16 -    for( int i=0; i<length; i+=1 )
   10.17 +    for( size_t i=0; i<length; i+=1 )
   10.18          dst += sprintf(dst,"%02X", bytes[i]);
   10.19      return [[[NSString alloc] initWithBytes: out length: 2*length encoding: NSASCIIStringEncoding]
   10.20              autorelease];
    11.1 --- a/MYKey-iPhone.m	Tue Apr 07 10:56:58 2009 -0700
    11.2 +++ b/MYKey-iPhone.m	Wed Apr 08 16:30:52 2009 -0700
    11.3 @@ -109,6 +109,35 @@
    11.4  }
    11.5  
    11.6  
    11.7 +
    11.8 +
    11.9 +/** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
   11.10 +- (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
   11.11 +    CAssert(data);
   11.12 +    size_t dataLength = data.length;
   11.13 +    SecKeyRef key = self.keyRef;
   11.14 +    size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key));
   11.15 +    void *outputBuf = malloc(outputLength);
   11.16 +    if (!outputBuf) return nil;
   11.17 +    OSStatus err;
   11.18 +    if (operation)
   11.19 +        err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1, 
   11.20 +                            data.bytes, dataLength,
   11.21 +                            outputBuf, &outputLength);
   11.22 +    else
   11.23 +        err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1, 
   11.24 +                            data.bytes, dataLength,
   11.25 +                            outputBuf, &outputLength);
   11.26 +    if (err) {
   11.27 +        free(outputBuf);
   11.28 +        Warn(@"%scrypting failed (%i)", (operation ?"En" :"De"), err);
   11.29 +        // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h)
   11.30 +        return nil;
   11.31 +    } else
   11.32 +        return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES];
   11.33 +}
   11.34 +
   11.35 +
   11.36  @end
   11.37  
   11.38  
    12.1 --- a/MYKey.m	Tue Apr 07 10:56:58 2009 -0700
    12.2 +++ b/MYKey.m	Wed Apr 08 16:30:52 2009 -0700
    12.3 @@ -115,11 +115,6 @@
    12.4  }
    12.5  
    12.6  
    12.7 -@end
    12.8 -
    12.9 -
   12.10 -
   12.11 -
   12.12  #pragma mark -
   12.13  #pragma mark UTILITY FUNCTIONS:
   12.14  
   12.15 @@ -152,9 +147,109 @@
   12.16      SecKeyRef key = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(items,0));
   12.17      CFRelease(items);
   12.18      return key; // caller must CFRelease
   12.19 -}    
   12.20 +}
   12.21  
   12.22  
   12.23 +- (MYSHA1Digest*) _keyDigest {
   12.24 +    MYSHA1Digest *digest = nil;
   12.25 +    CSSM_DATA *keyDigest = NULL;
   12.26 +    CSSM_CC_HANDLE context = [self _createPassThroughContext];
   12.27 +    if (context) {
   12.28 +        if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest),
   12.29 +                      @"CSSM_CSP_PassThrough")) {
   12.30 +            if (keyDigest && keyDigest->Data) {
   12.31 +                digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data
   12.32 +                                                           length: keyDigest->Length] autorelease];
   12.33 +            }
   12.34 +        } else {
   12.35 +            SecKeyRef keyRef = self.keyRef;
   12.36 +            // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to
   12.37 +            // be ones that are either expired or don't have a matching public key at all (?)
   12.38 +            Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')", 
   12.39 +                 keyRef,
   12.40 +                 self.name,
   12.41 +                 self.comment);
   12.42 +            NSData *digestData = [[self class] _getAttribute: kSecKeyLabel 
   12.43 +                                                      ofItem: (SecKeychainItemRef)keyRef];
   12.44 +            if (digestData) {
   12.45 +                digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
   12.46 +                if (!digest)
   12.47 +                    Warn(@"Digest property of key %p was invalid SHA-1: %@", keyRef,digestData);
   12.48 +            }
   12.49 +        }
   12.50 +        CSSM_DeleteContext(context);
   12.51 +    }
   12.52 +    return digest;
   12.53 +}
   12.54 +
   12.55 +
   12.56 +/** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
   12.57 +- (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
   12.58 +    CAssert(data);
   12.59 +    const CSSM_ACCESS_CREDENTIALS *credentials;
   12.60 +    credentials = [self cssmCredentialsForOperation: (operation ?CSSM_ACL_AUTHORIZATION_ENCRYPT 
   12.61 +                                                                :CSSM_ACL_AUTHORIZATION_DECRYPT) 
   12.62 +                                               type: kSecCredentialTypeDefault
   12.63 +                                              error: nil];
   12.64 +    if (!credentials)
   12.65 +        return nil;
   12.66 +    
   12.67 +    CSSM_CC_HANDLE ccHandle;
   12.68 +    if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(self.cssmCSPHandle,
   12.69 +                                                    CSSM_ALGID_RSA,
   12.70 +                                                    credentials,
   12.71 +                                                    self.cssmKey,
   12.72 +                                                    CSSM_PADDING_PKCS1,
   12.73 +                                                    &ccHandle),
   12.74 +                   @"CSSM_CSP_CreateAsymmetricContext"))
   12.75 +        return nil;
   12.76 +    
   12.77 +    CSSM_DATA original = {data.length, (void*)data.bytes};
   12.78 +    CSSM_DATA result = {};
   12.79 +    size_t outputLength;
   12.80 +    BOOL ok;
   12.81 +    if (operation)
   12.82 +        ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
   12.83 +                       @"CSSM_EncryptData");
   12.84 +    else
   12.85 +        ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
   12.86 +                       @"CSSM_DecryptData");
   12.87 +    CSSM_DeleteContext(ccHandle);
   12.88 +    return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil;
   12.89 +}
   12.90 +
   12.91 +
   12.92 +- (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm {
   12.93 +    const CSSM_ACCESS_CREDENTIALS *credentials;
   12.94 +    credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_SIGN 
   12.95 +                                               type: kSecCredentialTypeDefault
   12.96 +                                              error: nil];
   12.97 +    if (credentials) {
   12.98 +        CSSM_CC_HANDLE ccHandle = 0;
   12.99 +        if (checkcssm(CSSM_CSP_CreateSignatureContext(self.cssmCSPHandle, 
  12.100 +                                                      algorithm, 
  12.101 +                                                      credentials,
  12.102 +                                                      self.cssmKey,
  12.103 +                                                      &ccHandle),
  12.104 +                             @"CSSM_CSP_CreateSignatureContext") )
  12.105 +            return ccHandle;
  12.106 +    }
  12.107 +    return 0;
  12.108 +}
  12.109 +
  12.110 +- (CSSM_CC_HANDLE) _createPassThroughContext
  12.111 +{
  12.112 +    CSSM_CC_HANDLE ccHandle = 0;
  12.113 +    if (checkcssm(CSSM_CSP_CreatePassThroughContext(self.cssmCSPHandle, self.cssmKey, &ccHandle), 
  12.114 +                          @"CSSM_CSP_CreatePassThroughContext") )
  12.115 +        return ccHandle;
  12.116 +    else
  12.117 +        return 0;
  12.118 +}
  12.119 +
  12.120 +
  12.121 +@end
  12.122 +
  12.123  #endif MYCRYPTO_USE_IPHONE_API
  12.124  
  12.125  
    13.1 --- a/MYKeyPair.h	Tue Apr 07 10:56:58 2009 -0700
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,81 +0,0 @@
    13.4 -//
    13.5 -//  KeyPair.h
    13.6 -//  MYCrypto
    13.7 -//
    13.8 -//  Created by Jens Alfke on 3/21/09.
    13.9 -//  Copyright 2009 Jens Alfke. All rights reserved.
   13.10 -//
   13.11 -
   13.12 -#import "MYPublicKey.h"
   13.13 -
   13.14 -
   13.15 -/** A key-pair consisting of a public and a private key.
   13.16 -    Can be used for signing and decrypting, as well as the inherited encrypting/verifying.
   13.17 -    Instances are generated by MYKeychain objects. */
   13.18 -@interface MYKeyPair : MYPublicKey <MYDecryption>
   13.19 -{
   13.20 -    @private
   13.21 -    SecKeyRef _privateKey;
   13.22 -}
   13.23 -
   13.24 -/** Decrypts data that was encrypted using the public key.
   13.25 -    See the description of -[MYPublicKey encryptData:] for warnings and caveats.
   13.26 -    This method is usually used only to decrypt a symmetric session key, which then decrypts the
   13.27 -    rest of the data. */
   13.28 -- (NSData*) decryptData: (NSData*)data;
   13.29 -
   13.30 -/** Generates a signature of data, using the private key.
   13.31 -    (What's actually signed using RSA is the SHA-256 digest of the data.)
   13.32 -    The resulting signature can be verified using the matching MYPublicKey's
   13.33 -    verifySignature:ofData: method. */
   13.34 -- (NSData*) signData: (NSData*)data;
   13.35 -
   13.36 -
   13.37 -/** @name Mac-Only
   13.38 - *  Functionality not available on iPhone. 
   13.39 - */
   13.40 -//@{
   13.41 -#if !TARGET_OS_IPHONE
   13.42 -
   13.43 -/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred
   13.44 -    to another computer. Since the key is sensitive, it must be exported in encrypted form
   13.45 -    using a user-chosen passphrase. This method will display a standard alert panel, run by
   13.46 -    the Security agent, that prompts the user to enter a new passphrase for encrypting the key.
   13.47 -    The same passphrase must be re-entered when importing the key from the data blob.
   13.48 -    (This is a convenient shorthand for the full exportPrivateKeyInFormat... method.
   13.49 -    It uses OpenSSL format, wrapped with PEM, and a default title and prompt for the alert.) */
   13.50 -- (NSData*) exportPrivateKey;
   13.51 -
   13.52 -/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred
   13.53 -    to another computer. Since the key is sensitive, it must be exported in encrypted form
   13.54 -    using a user-chosen passphrase. This method will display a standard alert panel, run by
   13.55 -    the Security agent, that prompts the user to enter a new passphrase for encrypting the key.
   13.56 -    The same passphrase must be re-entered when importing the key from the data blob.
   13.57 -    @param format  The data format: kSecFormatOpenSSL, kSecFormatSSH, kSecFormatBSAFE or kSecFormatSSHv2.
   13.58 -    @param withPEM  YES if the data should be encoded in PEM format, which converts into short lines
   13.59 -        of printable ASCII characters, suitable for sending in email.
   13.60 -    @param alertTitle  An optional title for the alert panel. (Currently ignored by the OS?)
   13.61 -    @param prompt  An optional prompt message to display in the alert panel. */
   13.62 -- (NSData*) exportPrivateKeyInFormat: (SecExternalFormat)format
   13.63 -                             withPEM: (BOOL)withPEM
   13.64 -                          alertTitle: (NSString*)alertTitle
   13.65 -                         alertPrompt: (NSString*)prompt;
   13.66 -
   13.67 -#endif
   13.68 -//@}
   13.69 -
   13.70 -
   13.71 -/** @name Expert
   13.72 - *  Advanced functionality.
   13.73 - */
   13.74 -//@{
   13.75 -
   13.76 -/** Creates a MYKeyPair object from existing Keychain key references. */
   13.77 -- (id) initWithPublicKeyRef: (SecKeyRef)publicKey privateKeyRef: (SecKeyRef)privateKey;
   13.78 -
   13.79 -/** The underlying Keychain key reference for the private key. */
   13.80 -@property (readonly) SecKeyRef privateKeyRef;
   13.81 -
   13.82 -//@}
   13.83 -
   13.84 -@end
    14.1 --- a/MYKeyPair.m	Tue Apr 07 10:56:58 2009 -0700
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,246 +0,0 @@
    14.4 -//
    14.5 -//  KeyPair.m
    14.6 -//  MYCrypto
    14.7 -//
    14.8 -//  Created by Jens Alfke on 3/21/09.
    14.9 -//  Copyright 2009 Jens Alfke. All rights reserved.
   14.10 -//
   14.11 -
   14.12 -#import "MYKeyPair.h"
   14.13 -#import "MYCrypto_Private.h"
   14.14 -#import <CommonCrypto/CommonDigest.h>
   14.15 -
   14.16 -#if !MYCRYPTO_USE_IPHONE_API
   14.17 -
   14.18 -
   14.19 -#pragma mark -
   14.20 -
   14.21 -@implementation MYKeyPair
   14.22 -
   14.23 -
   14.24 -+ (MYKeyPair*) _generateRSAKeyPairOfSize: (unsigned)keySize
   14.25 -                            inKeychain: (MYKeychain*)keychain {
   14.26 -    Assert( keySize == 512 || keySize == 1024 || keySize == 2048, @"Unsupported key size %u", keySize );
   14.27 -    SecKeyRef pubKey=NULL, privKey=NULL;
   14.28 -    OSStatus err;
   14.29 -    err = SecKeyCreatePair(keychain.keychainRefOrDefault,
   14.30 -                           CSSM_ALGID_RSA, 
   14.31 -                           keySize,
   14.32 -                           0LL,
   14.33 -                           CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY,        // public key
   14.34 -                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
   14.35 -                           CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN,          // private key
   14.36 -                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_PERMANENT,
   14.37 -                           NULL, // SecAccessRef
   14.38 -                           &pubKey, &privKey);
   14.39 -    if (!check(err, @"SecKeyCreatePair")) {
   14.40 -        return nil;
   14.41 -    } else
   14.42 -        return [[[self alloc] initWithPublicKeyRef: pubKey privateKeyRef: privKey] autorelease];
   14.43 -}
   14.44 -
   14.45 -
   14.46 -- (id) initWithPublicKeyRef: (SecKeyRef)publicKey privateKeyRef: (SecKeyRef)privateKey {
   14.47 -    self = [super initWithKeyRef: publicKey];
   14.48 -    if (self) {
   14.49 -        NSParameterAssert(privateKey);
   14.50 -        _privateKey = (SecKeyRef) CFRetain(privateKey);
   14.51 -    }
   14.52 -    return self;
   14.53 -}
   14.54 -
   14.55 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData
   14.56 -                   privateKey: (SecKeyRef)privateKey 
   14.57 -                  forKeychain: (SecKeychainRef)keychain {
   14.58 -    if (!privateKey) {
   14.59 -        [self release];
   14.60 -        return nil;
   14.61 -    }
   14.62 -    self = [self _initWithKeyData: pubKeyData forKeychain: keychain];
   14.63 -    if (self) {
   14.64 -        _privateKey = privateKey;
   14.65 -    } else {
   14.66 -        SecKeychainItemDelete((SecKeychainItemRef)privateKey);
   14.67 -        CFRelease(privateKey);
   14.68 -    }
   14.69 -    return self;
   14.70 -}
   14.71 -
   14.72 -
   14.73 -// The public API for this is in MYKeychain.
   14.74 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
   14.75 -               privateKeyData: (NSData*)privKeyData
   14.76 -                  forKeychain: (SecKeychainRef)keychain 
   14.77 -                   alertTitle: (NSString*)title
   14.78 -                  alertPrompt: (NSString*)prompt
   14.79 -{
   14.80 -    // Try to import the private key first, since the user might cancel the passphrase alert.
   14.81 -    SecKeyImportExportParameters params = {
   14.82 -        .flags = kSecKeySecurePassphrase,
   14.83 -        .alertTitle = (CFStringRef) title,
   14.84 -        .alertPrompt = (CFStringRef) prompt
   14.85 -    };
   14.86 -    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
   14.87 -    return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain];
   14.88 -}
   14.89 -
   14.90 -// This method is for testing, so unit-tests don't require user intervention.
   14.91 -// It's deliberately not made public, to discourage clients from trying to manage the passphrases
   14.92 -// themselves (this is less secure than letting the Security agent do it.)
   14.93 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
   14.94 -               privateKeyData: (NSData*)privKeyData
   14.95 -                  forKeychain: (SecKeychainRef)keychain 
   14.96 -                   passphrase: (NSString*)passphrase
   14.97 -{
   14.98 -    SecKeyImportExportParameters params = {
   14.99 -        .passphrase = (CFStringRef) passphrase,
  14.100 -    };
  14.101 -    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
  14.102 -    return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain];
  14.103 -}
  14.104 -
  14.105 -
  14.106 -- (void) dealloc
  14.107 -{
  14.108 -    if (_privateKey) CFRelease(_privateKey);
  14.109 -    [super dealloc];
  14.110 -}
  14.111 -
  14.112 -- (void) finalize
  14.113 -{
  14.114 -    if (_privateKey) CFRelease(_privateKey);
  14.115 -    [super finalize];
  14.116 -}
  14.117 -
  14.118 -
  14.119 -- (NSUInteger)hash {
  14.120 -    // Ensure that a KeyPair doesn't hash the same as its corresponding PublicKey:
  14.121 -    return super.hash ^ 0xFFFFFFFF;
  14.122 -}
  14.123 -
  14.124 -
  14.125 -- (MYPublicKey*) asPublicKey {
  14.126 -    return [[[MYPublicKey alloc] initWithKeyRef: self.keyRef] autorelease];
  14.127 -}
  14.128 -
  14.129 -
  14.130 -- (NSData*) exportPrivateKeyInFormat: (SecExternalFormat)format
  14.131 -                             withPEM: (BOOL)withPEM
  14.132 -                          alertTitle: (NSString*)title
  14.133 -                         alertPrompt: (NSString*)prompt
  14.134 -{
  14.135 -    SecKeyImportExportParameters params = {
  14.136 -        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
  14.137 -        .flags = kSecKeySecurePassphrase,
  14.138 -        .alertTitle = (CFStringRef)title,
  14.139 -        .alertPrompt = (CFStringRef)prompt
  14.140 -    };
  14.141 -    CFDataRef data = NULL;
  14.142 -    if (check(SecKeychainItemExport(_privateKey, //$array((id)_publicKey,(id)_privateKey),
  14.143 -                                    format, (withPEM ?kSecItemPemArmour :0), 
  14.144 -                                    &params, &data),
  14.145 -              @"SecKeychainItemExport"))
  14.146 -        return [(id)CFMakeCollectable(data) autorelease];
  14.147 -    else
  14.148 -        return nil;
  14.149 -}
  14.150 -
  14.151 -- (NSData*) exportPrivateKey {
  14.152 -    return [self exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL withPEM: YES
  14.153 -                               alertTitle: @"Export Private Key"
  14.154 -                              alertPrompt: @"Enter a passphrase to protect the private-key file.\n"
  14.155 -            "You will need to re-enter the passphrase later when importing the key from this file, "
  14.156 -            "so keep it in a safe place."];
  14.157 -    //FIX: Should make these messages localizable.
  14.158 -}
  14.159 -
  14.160 -
  14.161 -- (NSData*) _exportPrivateKeyInFormat: (SecExternalFormat)format
  14.162 -                              withPEM: (BOOL)withPEM
  14.163 -                           passphrase: (NSString*)passphrase
  14.164 -{
  14.165 -    SecKeyImportExportParameters params = {
  14.166 -        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
  14.167 -        .passphrase = (CFStringRef)passphrase
  14.168 -    };
  14.169 -    CFDataRef data = NULL;
  14.170 -    if (check(SecKeychainItemExport(_privateKey,
  14.171 -                                    format, (withPEM ?kSecItemPemArmour :0), 
  14.172 -                                    &params, &data),
  14.173 -              @"SecKeychainItemExport"))
  14.174 -        return [(id)CFMakeCollectable(data) autorelease];
  14.175 -    else
  14.176 -        return nil;
  14.177 -}
  14.178 -
  14.179 -- (BOOL) removeFromKeychain {
  14.180 -    return check(SecKeychainItemDelete((SecKeychainItemRef)_privateKey), @"delete private key")
  14.181 -        && [super removeFromKeychain];
  14.182 -}
  14.183 -
  14.184 -
  14.185 -- (SecKeyRef) privateKeyRef {
  14.186 -    return _privateKey;
  14.187 -}
  14.188 -
  14.189 -
  14.190 -- (NSData*) decryptData: (NSData*)data {
  14.191 -    return _crypt(_privateKey,data,kCCDecrypt);
  14.192 -}
  14.193 -    
  14.194 -
  14.195 -- (NSData*) signData: (NSData*)data {
  14.196 -    Assert(data);
  14.197 -    uint8_t digest[CC_SHA256_DIGEST_LENGTH];
  14.198 -    CC_SHA256(data.bytes,data.length, digest);
  14.199 -    
  14.200 -    NSData *signature = nil;
  14.201 -    CSSM_CC_HANDLE ccHandle = cssmCreateSignatureContext(_privateKey);
  14.202 -    if (!ccHandle) return nil;
  14.203 -    CSSM_DATA original = {data.length, (void*)data.bytes};
  14.204 -    CSSM_DATA result = {0,NULL};
  14.205 -    if (checkcssm(CSSM_SignData(ccHandle, &original, 1, CSSM_ALGID_NONE, &result), @"CSSM_SignData"))
  14.206 -        signature = [NSData dataWithBytesNoCopy: result.Data length: result.Length
  14.207 -                                   freeWhenDone: YES];
  14.208 -    CSSM_DeleteContext(ccHandle);
  14.209 -    return signature;
  14.210 -}
  14.211 -
  14.212 -
  14.213 -- (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr {
  14.214 -    return [super setValue: valueStr ofAttribute: attr]
  14.215 -        && [[self class] _setAttribute: attr 
  14.216 -                                ofItem: (SecKeychainItemRef)_privateKey
  14.217 -                           stringValue: valueStr];
  14.218 -}
  14.219 -
  14.220 -
  14.221 -@end
  14.222 -
  14.223 -
  14.224 -#endif !MYCRYPTO_USE_IPHONE_API
  14.225 -
  14.226 -
  14.227 -
  14.228 -
  14.229 -/*
  14.230 - Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
  14.231 - 
  14.232 - Redistribution and use in source and binary forms, with or without modification, are permitted
  14.233 - provided that the following conditions are met:
  14.234 - 
  14.235 - * Redistributions of source code must retain the above copyright notice, this list of conditions
  14.236 - and the following disclaimer.
  14.237 - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  14.238 - and the following disclaimer in the documentation and/or other materials provided with the
  14.239 - distribution.
  14.240 - 
  14.241 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  14.242 - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
  14.243 - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
  14.244 - BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  14.245 - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  14.246 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  14.247 - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
  14.248 - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.249 - */
    15.1 --- a/MYKeychain-iPhone.m	Tue Apr 07 10:56:58 2009 -0700
    15.2 +++ b/MYKeychain-iPhone.m	Wed Apr 08 16:30:52 2009 -0700
    15.3 @@ -74,7 +74,7 @@
    15.4  }
    15.5  
    15.6  
    15.7 -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest {
    15.8 +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest {
    15.9      return [MYKeyEnumerator firstItemWithQuery:
   15.10                  $mdict({(id)kSecClass, (id)kSecClassKey},
   15.11                        {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate},
   15.12 @@ -82,7 +82,7 @@
   15.13                        {(id)kSecReturnRef, $true})];
   15.14  }
   15.15  
   15.16 -- (NSEnumerator*) enumerateKeyPairs {
   15.17 +- (NSEnumerator*) enumeratePrivateKeys {
   15.18      NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey},
   15.19                                  {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate},
   15.20                                  {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
   15.21 @@ -156,8 +156,8 @@
   15.22                                               algorithm: algorithm inKeychain: self];
   15.23  }
   15.24  
   15.25 -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize {
   15.26 -    return [MYKeyPair _generateRSAKeyPairOfSize: keySize inKeychain: self];
   15.27 +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize {
   15.28 +    return [MYPrivateKey _generateRSAKeyPairOfSize: keySize inKeychain: self];
   15.29  }
   15.30  
   15.31  
   15.32 @@ -211,19 +211,7 @@
   15.33      while (next==nil && _index < CFArrayGetCount(_results)) {
   15.34          CFTypeRef found = CFArrayGetValueAtIndex(_results, _index++); 
   15.35          if (_itemClass == kSecAttrKeyClassPrivate) {
   15.36 -            MYSHA1Digest *digest = [MYPublicKey _digestOfKey: (SecKeyRef)found];
   15.37 -            if (digest) {
   15.38 -                MYPublicKey *publicKey = [[MYKeychain defaultKeychain] publicKeyWithDigest: digest];
   15.39 -                if (publicKey)
   15.40 -                    next = [[[MYKeyPair alloc] initWithPublicKeyRef: publicKey.keyRef
   15.41 -                                                     privateKeyRef: (SecKeyRef)found]
   15.42 -                           autorelease];
   15.43 -                else {
   15.44 -                    // The matching public key won't turn up if it's embedded in a certificate;
   15.45 -                    // I'd have to search for certs if I wanted to look that up. Skip it for now.
   15.46 -                    //Warn(@"Couldn't find matching public key for private key!");
   15.47 -                }
   15.48 -            }
   15.49 +            next = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found];
   15.50          } else if (_itemClass == kSecAttrKeyClassPublic) {
   15.51              next = [[[MYPublicKey alloc] initWithKeyRef: (SecKeyRef)found] autorelease];
   15.52          } else if (_itemClass == kSecAttrKeyClassSymmetric) {
    16.1 --- a/MYKeychain.h	Tue Apr 07 10:56:58 2009 -0700
    16.2 +++ b/MYKeychain.h	Wed Apr 08 16:30:52 2009 -0700
    16.3 @@ -8,7 +8,7 @@
    16.4  
    16.5  #import <Foundation/Foundation.h>
    16.6  #import "MYCryptoConfig.h"
    16.7 -@class MYSymmetricKey, MYPublicKey, MYKeyPair, MYCertificate, MYSHA1Digest;
    16.8 +@class MYSymmetricKey, MYPublicKey, MYPrivateKey, MYCertificate, MYSHA1Digest;
    16.9  
   16.10  
   16.11  /** A Keychain, a secure database of cryptographic keys.
   16.12 @@ -77,16 +77,16 @@
   16.13          to break, but operate more slowly and generate larger signatures.
   16.14          2048 is a good default choice. You could use 1024 if the data and signatures won't need
   16.15          to stay secure for years; or you could use 4096 if you're extremely paranoid. */
   16.16 -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize;
   16.17 +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize;
   16.18  
   16.19  /** Looks up an existing key-pair whose public key has the given digest.
   16.20      Returns nil if there is no such key-pair in the keychain.
   16.21      (This method does not look for public keys embedded in certificates, only 'bare' keys.) */
   16.22 -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest;
   16.23 +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest;
   16.24  
   16.25  /** Enumerates all key-pairs in the keychain.
   16.26      (This method does not find keys embedded in certificates, only 'bare' keys.) */
   16.27 -- (NSEnumerator*) enumerateKeyPairs;
   16.28 +- (NSEnumerator*) enumeratePrivateKeys;
   16.29  
   16.30  
   16.31  #pragma mark -
   16.32 @@ -109,14 +109,14 @@
   16.33      of both the public and private keys.
   16.34      Since the private key data is wrapped (encrypted), the Security agent will prompt the user to enter
   16.35      the passphrase. */
   16.36 -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData 
   16.37 +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData 
   16.38                      privateKey: (NSData*)privKeyData;
   16.39  
   16.40  /** Imports a key-pair into the keychain, given the external representations
   16.41      of both the public and private keys.
   16.42      Since the private key data is wrapped (encrypted), the Security agent will prompt the user to enter
   16.43      the passphrase. You can specify the title and prompt message for this alert panel. */
   16.44 -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData 
   16.45 +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData 
   16.46                      privateKey: (NSData*)privKeyData
   16.47                      alertTitle: (NSString*)title
   16.48                     alertPrompt: (NSString*)prompt;
    17.1 --- a/MYKeychain.m	Tue Apr 07 10:56:58 2009 -0700
    17.2 +++ b/MYKeychain.m	Wed Apr 08 16:30:52 2009 -0700
    17.3 @@ -229,11 +229,11 @@
    17.4  }
    17.5  
    17.6  
    17.7 -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest {
    17.8 -    return (MYKeyPair*) [self itemOfClass: kSecPrivateKeyItemClass withDigest: pubKeyDigest];
    17.9 +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest {
   17.10 +    return (MYPrivateKey*) [self itemOfClass: kSecPrivateKeyItemClass withDigest: pubKeyDigest];
   17.11  }
   17.12  
   17.13 -- (NSEnumerator*) enumerateKeyPairs {
   17.14 +- (NSEnumerator*) enumeratePrivateKeys {
   17.15      return [[[MYKeyEnumerator alloc] initWithKeychain: self
   17.16                                              itemClass: kSecPrivateKeyItemClass
   17.17                                             attributes: NULL count: 0] autorelease];
   17.18 @@ -275,19 +275,19 @@
   17.19              autorelease];
   17.20  }
   17.21  
   17.22 -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData 
   17.23 +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData 
   17.24                      privateKey: (NSData*)privKeyData 
   17.25                      alertTitle: (NSString*)title
   17.26                     alertPrompt: (NSString*)prompt {
   17.27 -    return [[[MYKeyPair alloc] _initWithPublicKeyData: pubKeyData
   17.28 -                                       privateKeyData: privKeyData
   17.29 -                                          forKeychain: self.keychainRefOrDefault
   17.30 -                                           alertTitle: (NSString*)title
   17.31 -                                          alertPrompt: (NSString*)prompt]
   17.32 +    return [[[MYPrivateKey alloc] _initWithKeyData: privKeyData
   17.33 +                                     publicKeyData: pubKeyData
   17.34 +                                       forKeychain: self.keychainRefOrDefault
   17.35 +                                        alertTitle: (NSString*)title
   17.36 +                                       alertPrompt: (NSString*)prompt]
   17.37              autorelease];
   17.38  }
   17.39  
   17.40 -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData 
   17.41 +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData 
   17.42                      privateKey: (NSData*)privKeyData 
   17.43  {
   17.44      return [self importPublicKey: pubKeyData privateKey: privKeyData
   17.45 @@ -326,8 +326,8 @@
   17.46                                               algorithm: algorithm inKeychain: self];
   17.47  }
   17.48  
   17.49 -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize {
   17.50 -    return [MYKeyPair _generateRSAKeyPairOfSize: keySize inKeychain: self];
   17.51 +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize {
   17.52 +    return [MYPrivateKey _generateRSAKeyPairOfSize: keySize inKeychain: self];
   17.53  }
   17.54  
   17.55  
   17.56 @@ -398,19 +398,7 @@
   17.57          
   17.58          switch (_itemClass) {
   17.59              case kSecPrivateKeyItemClass: {
   17.60 -                MYSHA1Digest *digest = [MYPublicKey _digestOfKey: (SecKeyRef)found];
   17.61 -                if (digest) {
   17.62 -                    MYPublicKey *publicKey = [_keychain publicKeyWithDigest: digest];
   17.63 -                    if (publicKey)
   17.64 -                        key = [[[MYKeyPair alloc] initWithPublicKeyRef: publicKey.keyRef
   17.65 -                                                         privateKeyRef: (SecKeyRef)found]
   17.66 -                               autorelease];
   17.67 -                    else {
   17.68 -                        // The matching public key won't turn up if it's embedded in a certificate;
   17.69 -                        // I'd have to search for certs if I wanted to look that up. Skip it for now.
   17.70 -                        //Warn(@"Couldn't find matching public key for private key! digest=%@",digest);
   17.71 -                    }
   17.72 -                }
   17.73 +                key = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found];
   17.74                  break;
   17.75              }
   17.76              case kSecCertificateItemClass:
    18.1 --- a/MYKeychainItem.m	Tue Apr 07 10:56:58 2009 -0700
    18.2 +++ b/MYKeychainItem.m	Wed Apr 08 16:30:52 2009 -0700
    18.3 @@ -50,10 +50,8 @@
    18.4  }
    18.5  
    18.6  - (BOOL) isEqual: (id)obj {
    18.7 -    // Require the objects to be of the same class, so that a MYPublicKey will not be equal to a
    18.8 -    // MYKeyPair with the same public key.
    18.9 -    return (obj == self) || 
   18.10 -           ([obj class] == [self class] && CFEqual(_itemRef, [obj keychainItemRef]));
   18.11 +    return (obj == self) ||
   18.12 +           ([obj isKindOfClass: [MYKeychainItem class]] && CFEqual(_itemRef, [obj keychainItemRef]));
   18.13  }
   18.14  
   18.15  - (NSUInteger) hash {
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/MYPrivateKey.h	Wed Apr 08 16:30:52 2009 -0700
    19.3 @@ -0,0 +1,77 @@
    19.4 +//
    19.5 +//  MYPrivateKey.h
    19.6 +//  MYCrypto
    19.7 +//
    19.8 +//  Created by Jens Alfke on 4/7/09.
    19.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
   19.10 +//
   19.11 +
   19.12 +#import "MYKey.h"
   19.13 +@class MYPublicKey, MYSHA1Digest;
   19.14 +
   19.15 +
   19.16 +/** A private key, used for signing and decrypting data.
   19.17 +    Always paired with a matching public key in a "key-pair".
   19.18 +    MYPublicKeys are instantiated by MYKeychain: either by generating a new key-pair, by
   19.19 +    looking up a key-pair by its attributes, or by importing a key-pair from data. */
   19.20 +@interface MYPrivateKey : MYKey <MYDecryption>
   19.21 +{
   19.22 +    @private
   19.23 +    MYPublicKey *_publicKey;
   19.24 +}
   19.25 +
   19.26 +/** The matching public key. Always non-nil. */
   19.27 +@property (readonly) MYPublicKey *publicKey;
   19.28 +
   19.29 +/** The public key's SHA-1 digest. 
   19.30 +    This is a convenient short (20-byte) identifier for the key pair. You can store it in your
   19.31 +    application data, and then later look up either key using MYKeychain methods. */
   19.32 +@property (readonly) MYSHA1Digest *publicKeyDigest;
   19.33 +
   19.34 +
   19.35 +/** Decrypts data that was encrypted using the public key.
   19.36 +    See the description of -[MYPublicKey encryptData:] for warnings and caveats.
   19.37 +    This method is usually used only to decrypt a symmetric session key, which then decrypts the
   19.38 +    rest of the data. */
   19.39 +- (NSData*) decryptData: (NSData*)data;
   19.40 +
   19.41 +/** Generates a signature of data.
   19.42 +    (What's actually signed using RSA is the SHA-256 digest of the data.)
   19.43 +    The resulting signature can be verified using the matching MYPublicKey's
   19.44 +    verifySignature:ofData: method. */
   19.45 +- (NSData*) signData: (NSData*)data;
   19.46 +
   19.47 +
   19.48 +/** @name Mac-Only
   19.49 + *  Functionality not available on iPhone. 
   19.50 + */
   19.51 +//@{
   19.52 +#if !TARGET_OS_IPHONE
   19.53 +
   19.54 +/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred
   19.55 +    to another computer. Since the key is sensitive, it must be exported in encrypted form
   19.56 +    using a user-chosen passphrase. This method will display a standard alert panel, run by
   19.57 +    the Security agent, that prompts the user to enter a new passphrase for encrypting the key.
   19.58 +    The same passphrase must be re-entered when importing the key from the data blob.
   19.59 +    (This is a convenient shorthand for the full exportPrivateKeyInFormat... method.
   19.60 +    It uses OpenSSL format, wrapped with PEM, and a default title and prompt for the alert.) */
   19.61 +- (NSData*) exportKey;
   19.62 +
   19.63 +/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred
   19.64 +    to another computer. Since the key is sensitive, it must be exported in encrypted form
   19.65 +    using a user-chosen passphrase. This method will display a standard alert panel, run by
   19.66 +    the Security agent, that prompts the user to enter a new passphrase for encrypting the key.
   19.67 +    The same passphrase must be re-entered when importing the key from the data blob.
   19.68 +    @param format  The data format: kSecFormatOpenSSL, kSecFormatSSH, kSecFormatBSAFE or kSecFormatSSHv2.
   19.69 +    @param withPEM  YES if the data should be encoded in PEM format, which converts into short lines
   19.70 +        of printable ASCII characters, suitable for sending in email.
   19.71 +    @param alertTitle  An optional title for the alert panel. (Currently ignored by the OS?)
   19.72 +    @param prompt  An optional prompt message to display in the alert panel. */
   19.73 +- (NSData*) exportKeyInFormat: (SecExternalFormat)format
   19.74 +                      withPEM: (BOOL)withPEM
   19.75 +                   alertTitle: (NSString*)alertTitle
   19.76 +                  alertPrompt: (NSString*)prompt;
   19.77 +#endif
   19.78 +//@}
   19.79 +
   19.80 +@end
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/MYPrivateKey.m	Wed Apr 08 16:30:52 2009 -0700
    20.3 @@ -0,0 +1,293 @@
    20.4 +//
    20.5 +//  MYPrivateKey.m
    20.6 +//  MYCrypto
    20.7 +//
    20.8 +//  Created by Jens Alfke on 4/7/09.
    20.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
   20.10 +//
   20.11 +
   20.12 +#import "MYPrivateKey.h"
   20.13 +#import "MYCrypto_Private.h"
   20.14 +#import "MYDigest.h"
   20.15 +#import <CommonCrypto/CommonDigest.h>
   20.16 +
   20.17 +
   20.18 +@implementation MYPrivateKey
   20.19 +
   20.20 +
   20.21 +- (id) initWithKeyRef: (SecKeyRef)privateKey
   20.22 +{
   20.23 +    self = [super initWithKeyRef: privateKey];
   20.24 +    if (self) {
   20.25 +        // No public key given, so look it up:
   20.26 +        MYSHA1Digest *digest = self._keyDigest;
   20.27 +        if (digest)
   20.28 +            _publicKey = [[self.keychain publicKeyWithDigest: digest] retain];
   20.29 +        if (!_publicKey) {
   20.30 +            // The matching public key won't turn up if it's embedded in a certificate;
   20.31 +            // I'd have to search for certs if I wanted to look that up. Skip it for now.
   20.32 +            Log(@"MYPrivateKey(%p): Couldn't find matching public key for private key! digest=%@",
   20.33 +                self, digest);
   20.34 +            [self release];
   20.35 +            return nil;
   20.36 +        }
   20.37 +    }
   20.38 +    return self;
   20.39 +}
   20.40 +
   20.41 +
   20.42 +- (id) _initWithKeyRef: (SecKeyRef)privateKey
   20.43 +             publicKey: (MYPublicKey*)publicKey 
   20.44 +{
   20.45 +    Assert(publicKey);
   20.46 +    self = [super initWithKeyRef: privateKey];
   20.47 +    if (self) {
   20.48 +        _publicKey = [publicKey retain];
   20.49 +    }
   20.50 +    return self;
   20.51 +}
   20.52 +
   20.53 +- (id) initWithKeyRef: (SecKeyRef)privateKey
   20.54 +         publicKeyRef: (SecKeyRef)publicKeyRef
   20.55 +{
   20.56 +    MYPublicKey *publicKey = [[MYPublicKey alloc] initWithKeyRef: publicKeyRef];
   20.57 +    self = [self _initWithKeyRef: privateKey publicKey: publicKey];
   20.58 +    [publicKey release];
   20.59 +    return self;
   20.60 +}
   20.61 +
   20.62 +- (id) _initWithKeyRef: (SecKeyRef)privateKey 
   20.63 +         publicKeyData: (NSData*)pubKeyData
   20.64 +           forKeychain: (SecKeychainRef)keychain 
   20.65 +{
   20.66 +    if (!privateKey) {
   20.67 +        [self release];
   20.68 +        return nil;
   20.69 +    }
   20.70 +    MYPublicKey *pubKey = [[MYPublicKey alloc] _initWithKeyData: pubKeyData forKeychain: keychain];
   20.71 +    if (!pubKey) {
   20.72 +        [self release];
   20.73 +        return nil;
   20.74 +    }
   20.75 +    self = [super initWithKeyRef: privateKey];
   20.76 +    if (self) {
   20.77 +        _publicKey = pubKey;
   20.78 +    } else {
   20.79 +        [pubKey removeFromKeychain];
   20.80 +        [pubKey release];
   20.81 +    }
   20.82 +    return self;
   20.83 +}
   20.84 +
   20.85 +
   20.86 +#if !TARGET_OS_IPHONE
   20.87 +
   20.88 +// The public API for this is in MYKeychain.
   20.89 +- (id) _initWithKeyData: (NSData*)privKeyData 
   20.90 +          publicKeyData: (NSData*)pubKeyData
   20.91 +            forKeychain: (SecKeychainRef)keychain 
   20.92 +             alertTitle: (NSString*)title
   20.93 +            alertPrompt: (NSString*)prompt
   20.94 +{
   20.95 +    // Try to import the private key first, since the user might cancel the passphrase alert.
   20.96 +    SecKeyImportExportParameters params = {
   20.97 +        .flags = kSecKeySecurePassphrase,
   20.98 +        .alertTitle = (CFStringRef) title,
   20.99 +        .alertPrompt = (CFStringRef) prompt
  20.100 +    };
  20.101 +    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
  20.102 +    return [self _initWithKeyRef: privateKey publicKeyData: pubKeyData forKeychain: keychain];
  20.103 +}
  20.104 +
  20.105 +// This method is for testing, so unit-tests don't require user intervention.
  20.106 +// It's deliberately not made public, to discourage clients from trying to manage the passphrases
  20.107 +// themselves (this is less secure than letting the Security agent do it.)
  20.108 +- (id) _initWithKeyData: (NSData*)privKeyData 
  20.109 +          publicKeyData: (NSData*)pubKeyData
  20.110 +            forKeychain: (SecKeychainRef)keychain 
  20.111 +             passphrase: (NSString*)passphrase
  20.112 +{
  20.113 +    SecKeyImportExportParameters params = {
  20.114 +        .passphrase = (CFStringRef) passphrase,
  20.115 +    };
  20.116 +    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
  20.117 +    return [self _initWithKeyRef: privateKey publicKeyData: pubKeyData forKeychain: keychain];
  20.118 +}
  20.119 +
  20.120 +#endif
  20.121 +
  20.122 +
  20.123 +- (void) dealloc
  20.124 +{
  20.125 +    [_publicKey release];
  20.126 +    [super dealloc];
  20.127 +}
  20.128 +
  20.129 +
  20.130 ++ (MYPrivateKey*) _generateRSAKeyPairOfSize: (unsigned)keySize
  20.131 +                                 inKeychain: (MYKeychain*)keychain 
  20.132 +{
  20.133 +    Assert( keySize == 512 || keySize == 1024 || keySize == 2048, @"Unsupported key size %u", keySize );
  20.134 +    SecKeyRef pubKey=NULL, privKey=NULL;
  20.135 +    OSStatus err;
  20.136 +    
  20.137 +#if MYCRYPTO_USE_IPHONE_API
  20.138 +    NSDictionary *pubKeyAttrs = $dict({(id)kSecAttrIsPermanent, $true});
  20.139 +    NSDictionary *privKeyAttrs = $dict({(id)kSecAttrIsPermanent, $true});
  20.140 +    NSDictionary *keyAttrs = $dict( {(id)kSecAttrKeyType, (id)kSecAttrKeyTypeRSA},
  20.141 +                                    {(id)kSecAttrKeySizeInBits, $object(keySize)},
  20.142 +                                    {(id)kSecPublicKeyAttrs, pubKeyAttrs},
  20.143 +                                    {(id)kSecPrivateKeyAttrs, privKeyAttrs} );
  20.144 +    err = SecKeyGeneratePair((CFDictionaryRef)keyAttrs,&pubKey,&privKey);
  20.145 +#else
  20.146 +    err = SecKeyCreatePair(keychain.keychainRefOrDefault,
  20.147 +                           CSSM_ALGID_RSA, 
  20.148 +                           keySize,
  20.149 +                           0LL,
  20.150 +                           CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY,        // public key
  20.151 +                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
  20.152 +                           CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN,          // private key
  20.153 +                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_PERMANENT,
  20.154 +                           NULL, // SecAccessRef
  20.155 +                           &pubKey, &privKey);
  20.156 +#endif
  20.157 +    if (!check(err, @"SecKeyCreatePair")) {
  20.158 +        return nil;
  20.159 +    } else
  20.160 +        return [[[self alloc] initWithKeyRef: privKey publicKeyRef: pubKey] autorelease];
  20.161 +}
  20.162 +
  20.163 +
  20.164 +#pragma mark -
  20.165 +#pragma mark ACCESSORS:
  20.166 +
  20.167 +
  20.168 +- (NSString*) description {
  20.169 +    return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString);
  20.170 +}
  20.171 +
  20.172 +@synthesize publicKey=_publicKey;
  20.173 +
  20.174 +- (MYSHA1Digest*) publicKeyDigest {
  20.175 +    return _publicKey.publicKeyDigest;
  20.176 +}
  20.177 +
  20.178 +- (SecExternalItemType) keyType {
  20.179 +#if MYCRYPTO_USE_IPHONE_API
  20.180 +    return kSecAttrKeyClassPublic;
  20.181 +#else
  20.182 +    return kSecItemTypePrivateKey;
  20.183 +#endif
  20.184 +}
  20.185 +
  20.186 +- (NSData *) keyData {
  20.187 +    [NSException raise: NSGenericException format: @"Can't access keyData of a PrivateKey"];
  20.188 +    return nil;
  20.189 +}
  20.190 +
  20.191 +- (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr {
  20.192 +    return [super setValue: valueStr ofAttribute: attr]
  20.193 +        && [_publicKey setValue: valueStr ofAttribute: attr];
  20.194 +}
  20.195 +
  20.196 +
  20.197 +#pragma mark -
  20.198 +#pragma mark OPERATIONS:
  20.199 +
  20.200 +
  20.201 +- (BOOL) removeFromKeychain {
  20.202 +    return [super removeFromKeychain]
  20.203 +        && [_publicKey removeFromKeychain];
  20.204 +}
  20.205 +
  20.206 +
  20.207 +- (NSData*) decryptData: (NSData*)data {
  20.208 +    return [self _crypt: data operation: NO];
  20.209 +}
  20.210 +
  20.211 +
  20.212 +- (NSData*) signData: (NSData*)data {
  20.213 +    Assert(data);
  20.214 +#if MYCRYPTO_USE_IPHONE_API
  20.215 +    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
  20.216 +    CC_SHA1(data.bytes,data.length, digest);
  20.217 +
  20.218 +    size_t sigLen = 1024;
  20.219 +    uint8_t sigBuf[sigLen];
  20.220 +    OSStatus err = SecKeyRawSign(self.keyRef, kSecPaddingPKCS1SHA1,
  20.221 +                                 digest,sizeof(digest), //data.bytes, data.length,
  20.222 +                                 sigBuf, &sigLen);
  20.223 +    if(err) {
  20.224 +        Warn(@"SecKeyRawSign failed: %i",err);
  20.225 +        return nil;
  20.226 +    } else
  20.227 +        return [NSData dataWithBytes: sigBuf length: sigLen];
  20.228 +#else
  20.229 +    NSData *signature = nil;
  20.230 +    CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA];
  20.231 +    if (!ccHandle) return nil;
  20.232 +    CSSM_DATA original = {data.length, (void*)data.bytes};
  20.233 +    CSSM_DATA result = {0,NULL};
  20.234 +    if (checkcssm(CSSM_SignData(ccHandle, &original, 1, CSSM_ALGID_NONE, &result), @"CSSM_SignData"))
  20.235 +        signature = [NSData dataWithBytesNoCopy: result.Data length: result.Length
  20.236 +                                   freeWhenDone: YES];
  20.237 +    CSSM_DeleteContext(ccHandle);
  20.238 +    return signature;
  20.239 +#endif
  20.240 +}
  20.241 +
  20.242 +
  20.243 +#if !TARGET_OS_IPHONE
  20.244 +
  20.245 +- (NSData*) exportKeyInFormat: (SecExternalFormat)format 
  20.246 +                      withPEM: (BOOL)withPEM
  20.247 +                   alertTitle: (NSString*)title
  20.248 +                  alertPrompt: (NSString*)prompt
  20.249 +{
  20.250 +    SecKeyImportExportParameters params = {
  20.251 +        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
  20.252 +        .flags = kSecKeySecurePassphrase,
  20.253 +        .alertTitle = (CFStringRef)title,
  20.254 +        .alertPrompt = (CFStringRef)prompt
  20.255 +    };
  20.256 +    CFDataRef data = NULL;
  20.257 +    if (check(SecKeychainItemExport(self.keyRef,
  20.258 +                                    format, (withPEM ?kSecItemPemArmour :0), 
  20.259 +                                    &params, &data),
  20.260 +              @"SecKeychainItemExport"))
  20.261 +        return [(id)CFMakeCollectable(data) autorelease];
  20.262 +    else
  20.263 +        return nil;
  20.264 +}
  20.265 +
  20.266 +- (NSData*) exportKey {
  20.267 +    return [self exportKeyInFormat: kSecFormatWrappedOpenSSL withPEM: YES
  20.268 +                        alertTitle: @"Export Private Key"
  20.269 +                       alertPrompt: @"Enter a passphrase to protect the private-key file.\n"
  20.270 +            "You will need to re-enter the passphrase later when importing the key from this file, "
  20.271 +            "so keep it in a safe place."];
  20.272 +    //FIX: Should make these messages localizable.
  20.273 +}
  20.274 +
  20.275 +
  20.276 +- (NSData*) _exportKeyInFormat: (SecExternalFormat)format
  20.277 +                       withPEM: (BOOL)withPEM
  20.278 +                    passphrase: (NSString*)passphrase
  20.279 +{
  20.280 +    SecKeyImportExportParameters params = {
  20.281 +        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
  20.282 +        .passphrase = (CFStringRef)passphrase
  20.283 +    };
  20.284 +    CFDataRef data = NULL;
  20.285 +    if (check(SecKeychainItemExport(self.keyRef,
  20.286 +                                    format, (withPEM ?kSecItemPemArmour :0), 
  20.287 +                                    &params, &data),
  20.288 +              @"SecKeychainItemExport"))
  20.289 +        return [(id)CFMakeCollectable(data) autorelease];
  20.290 +    else
  20.291 +        return nil;
  20.292 +}
  20.293 +
  20.294 +#endif TARGET_OS_IPHONE
  20.295 +
  20.296 +@end
    21.1 --- a/MYPublicKey-iPhone.m	Tue Apr 07 10:56:58 2009 -0700
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,101 +0,0 @@
    21.4 -//
    21.5 -//  MYPublicKey-iPhone.m
    21.6 -//  MYCrypto-iPhone
    21.7 -//
    21.8 -//  Created by Jens Alfke on 3/30/09.
    21.9 -//  Copyright 2009 Jens Alfke. All rights reserved.
   21.10 -//
   21.11 -
   21.12 -#import "MYPublicKey.h"
   21.13 -#import "MYCrypto_Private.h"
   21.14 -
   21.15 -#if MYCRYPTO_USE_IPHONE_API
   21.16 -
   21.17 -#import "MYDigest.h"
   21.18 -#import "MYErrorUtils.h"
   21.19 -#import <CommonCrypto/CommonDigest.h>
   21.20 -
   21.21 -
   21.22 -@implementation MYPublicKey
   21.23 -
   21.24 -
   21.25 -- (void) dealloc
   21.26 -{
   21.27 -    [_digest release];
   21.28 -    [super dealloc];
   21.29 -}
   21.30 -
   21.31 -
   21.32 -- (SecExternalItemType) keyType {
   21.33 -    return kSecAttrKeyClassPublic;
   21.34 -}
   21.35 -
   21.36 -
   21.37 -- (MYPublicKey*) asPublicKey {
   21.38 -    return self;
   21.39 -}
   21.40 -
   21.41 -
   21.42 -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key {
   21.43 -    NSData *digestData = [MYKeychainItem _getAttribute: kSecAttrApplicationLabel ofItem: key];
   21.44 -    if (digestData)
   21.45 -        return (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
   21.46 -    else {
   21.47 -        Warn(@"MYKeyPair: public keyref %p didn't have digest attribute", key);
   21.48 -        return nil;
   21.49 -    }
   21.50 -}
   21.51 -
   21.52 -
   21.53 -- (MYSHA1Digest*) publicKeyDigest {
   21.54 -    return [[self class] _digestOfKey: self.keyRef];
   21.55 -}
   21.56 -
   21.57 -
   21.58 -- (NSData*) encryptData: (NSData*)data {
   21.59 -    return _crypt(self.keyRef,data,kCCEncrypt);
   21.60 -}
   21.61 -
   21.62 -
   21.63 -- (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data {
   21.64 -    Assert(data);
   21.65 -    Assert(signature);
   21.66 -    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
   21.67 -    CC_SHA1(data.bytes,data.length, digest);
   21.68 -    OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1,
   21.69 -                                   digest,sizeof(digest), //data.bytes, data.length,
   21.70 -                                   signature.bytes, signature.length);
   21.71 -    return err==noErr;
   21.72 -}
   21.73 -
   21.74 -
   21.75 -@end
   21.76 -
   21.77 -
   21.78 -
   21.79 -
   21.80 -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op) {
   21.81 -    CAssert(data);
   21.82 -    size_t dataLength = data.length;
   21.83 -    size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key));
   21.84 -    void *outputBuf = malloc(outputLength);
   21.85 -    if (!outputBuf) return nil;
   21.86 -    OSStatus err;
   21.87 -    if (op==kCCEncrypt)
   21.88 -        err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1, 
   21.89 -                            data.bytes, dataLength,
   21.90 -                            outputBuf, &outputLength);
   21.91 -    else
   21.92 -        err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1, 
   21.93 -                            data.bytes, dataLength,
   21.94 -                            outputBuf, &outputLength);
   21.95 -    if (err) {
   21.96 -        free(outputBuf);
   21.97 -        Warn(@"%scrypting failed (%i)", (op==kCCEncrypt ?"En" :"De"), err);
   21.98 -        // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h)
   21.99 -        return nil;
  21.100 -    } else
  21.101 -        return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES];
  21.102 -}
  21.103 -
  21.104 -#endif MYCRYPTO_USE_IPHONE_API
    22.1 --- a/MYPublicKey.h	Tue Apr 07 10:56:58 2009 -0700
    22.2 +++ b/MYPublicKey.h	Wed Apr 08 16:30:52 2009 -0700
    22.3 @@ -15,8 +15,8 @@
    22.4  
    22.5  
    22.6  /** A public key, which can be used for encrypting data and verifying signatures.
    22.7 -    MYPublicKeys are created as part of generating a MYKeyPair, 
    22.8 -    or by being imported into a MYKeychain. */
    22.9 +    MYPublicKeys are created as part of generating a key-pair, 
   22.10 +    or by being imported from data into a MYKeychain. */
   22.11  @interface MYPublicKey : MYKey <MYEncryption>
   22.12  {
   22.13      @private
   22.14 @@ -26,11 +26,6 @@
   22.15  /** The public key's SHA-1 digest. This is a convenient short (20-byte) identifier for the key. */
   22.16  @property (readonly) MYSHA1Digest *publicKeyDigest;
   22.17  
   22.18 -/** Returns the receiver as a MYPublicKey.
   22.19 -    If the receiver already is a MYPublicKey, this just returns self.
   22.20 -    If it's a MYKeyPair, it returns a new MYPublicKey containing just the public key. */
   22.21 -@property (readonly) MYPublicKey *asPublicKey;
   22.22 -
   22.23  /** Encrypts a short piece of data using this key, returning the raw encrypted result.
   22.24      An RSA key can encrypt only blocks smaller than its own key size; this
   22.25      method will fail and return nil if the data is too long.
    23.1 --- a/MYPublicKey.m	Tue Apr 07 10:56:58 2009 -0700
    23.2 +++ b/MYPublicKey.m	Wed Apr 08 16:30:52 2009 -0700
    23.3 @@ -8,17 +8,11 @@
    23.4  
    23.5  #import "MYPublicKey.h"
    23.6  #import "MYCrypto_Private.h"
    23.7 -
    23.8 -#if !MYCRYPTO_USE_IPHONE_API
    23.9 -
   23.10  #import "MYDigest.h"
   23.11  #import "MYErrorUtils.h"
   23.12  #import <CommonCrypto/CommonDigest.h>
   23.13  
   23.14  
   23.15 -static CSSM_CC_HANDLE cssmCreatePassThroughContext(SecKeyRef key);
   23.16 -
   23.17 -
   23.18  #pragma mark -
   23.19  @implementation MYPublicKey
   23.20  
   23.21 @@ -30,8 +24,13 @@
   23.22  }
   23.23  
   23.24  - (SecExternalItemType) keyType {
   23.25 +#if MYCRYPTO_USE_IPHONE_API
   23.26 +    return kSecAttrKeyClassPublic;
   23.27 +#else
   23.28      return kSecItemTypePublicKey;
   23.29 +#endif
   23.30  }
   23.31 +
   23.32  - (NSUInteger)hash {
   23.33      return self.publicKeyDigest.hash;
   23.34  }
   23.35 @@ -40,64 +39,38 @@
   23.36      return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString);
   23.37  }
   23.38  
   23.39 -- (MYPublicKey*) asPublicKey {
   23.40 -    return self;
   23.41 -}
   23.42 -
   23.43 -
   23.44 -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key {
   23.45 -    Assert(key);
   23.46 -    MYSHA1Digest *digest = nil;
   23.47 -    CSSM_DATA *keyDigest = NULL;
   23.48 -    CSSM_CC_HANDLE context = cssmCreatePassThroughContext(key);
   23.49 -    if (context) {
   23.50 -        if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest),
   23.51 -                      @"CSSM_CSP_PassThrough")) {
   23.52 -            if (keyDigest && keyDigest->Data) {
   23.53 -                digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data
   23.54 -                                                           length: keyDigest->Length] autorelease];
   23.55 -            }
   23.56 -        } else {
   23.57 -            // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to
   23.58 -            // be ones that are either expired or don't have a matching public key at all (?)
   23.59 -            Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')", key,
   23.60 -                 [self _getStringAttribute: kSecKeyPrintName ofItem: (SecKeychainItemRef)key],
   23.61 -                 [self _getStringAttribute: kSecKeyApplicationTag ofItem: (SecKeychainItemRef)key]);
   23.62 -            NSData *digestData = [self _getAttribute: kSecKeyLabel ofItem: (SecKeychainItemRef)key];
   23.63 -            if (digestData) {
   23.64 -                digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
   23.65 -                if (!digest)
   23.66 -                    Warn(@"Digest property of key %p was invalid SHA-1: %@", key,digestData);
   23.67 -            }
   23.68 -        }
   23.69 -        CSSM_DeleteContext(context);
   23.70 -    }
   23.71 -    return digest;
   23.72 -}
   23.73 -
   23.74  - (MYSHA1Digest*) publicKeyDigest {
   23.75      if (!_digest)
   23.76 -        _digest = [[[self class] _digestOfKey: self.keyRef] retain];
   23.77 +        _digest = [[self _keyDigest] retain];
   23.78      return _digest;
   23.79  }
   23.80  
   23.81 +#if !MYCRYPTO_USE_IPHONE_API
   23.82  - (NSData*) keyData {
   23.83      return [self exportKeyInFormat: kSecFormatOpenSSL withPEM: NO];
   23.84  }
   23.85 +#endif
   23.86  
   23.87  
   23.88  - (NSData*) encryptData: (NSData*)data {
   23.89 -    return _crypt(self.keyRef,data,kCCEncrypt);
   23.90 +    return [self _crypt: data operation: YES];
   23.91  }
   23.92  
   23.93  
   23.94  - (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data {
   23.95      Assert(data);
   23.96      Assert(signature);
   23.97 -    uint8_t digest[CC_SHA256_DIGEST_LENGTH];
   23.98 -    CC_SHA256(data.bytes,data.length, digest);
   23.99      
  23.100 -    CSSM_CC_HANDLE ccHandle = cssmCreateSignatureContext(self.keyRef);
  23.101 +#if MYCRYPTO_USE_IPHONE_API
  23.102 +    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
  23.103 +    CC_SHA1(data.bytes,data.length, digest);
  23.104 +    OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1,
  23.105 +                                   digest,sizeof(digest), //data.bytes, data.length,
  23.106 +                                   signature.bytes, signature.length);
  23.107 +    return err==noErr;
  23.108 +    
  23.109 +#else
  23.110 +    CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA];
  23.111      if (!ccHandle) return NO;
  23.112      CSSM_DATA original = {data.length, (void*)data.bytes};
  23.113      CSSM_DATA sig = {signature.length, (void*)signature.bytes};
  23.114 @@ -108,6 +81,7 @@
  23.115      if (cssmErr != CSSMERR_CSP_VERIFY_FAILED)
  23.116          Warn(@"CSSM error verifying signature: %u", MYErrorName(MYCSSMErrorDomain,cssmErr));
  23.117      return NO;
  23.118 +#endif
  23.119  }
  23.120  
  23.121  
  23.122 @@ -115,80 +89,6 @@
  23.123  
  23.124  
  23.125  
  23.126 -
  23.127 -#pragma mark -
  23.128 -#pragma mark UTILITY FUNCTIONS:
  23.129 -
  23.130 -
  23.131 -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op) {
  23.132 -    CAssert(data);
  23.133 -    const CSSM_KEY* cssmKey;
  23.134 -    const CSSM_ACCESS_CREDENTIALS *credentials;
  23.135 -    CSSM_CSP_HANDLE cspHandle;
  23.136 -    CSSM_CC_HANDLE ccHandle;
  23.137 -    if (!check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey")
  23.138 -            || !check(SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeWithUI,
  23.139 -                                           &credentials), @"GetCredentials")
  23.140 -            || !check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle")
  23.141 -        
  23.142 -            || !checkcssm(CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA,
  23.143 -                                                               credentials, cssmKey,
  23.144 -                                                               CSSM_PADDING_PKCS1, &ccHandle),
  23.145 -                          @"CSSM_CSP_CreateAsymmetricContext"))
  23.146 -        return nil;
  23.147 -    
  23.148 -    CSSM_DATA original = {data.length, (void*)data.bytes};
  23.149 -    CSSM_DATA result = {};
  23.150 -    size_t outputLength;
  23.151 -    BOOL ok;
  23.152 -    if (op==kCCEncrypt)
  23.153 -        ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
  23.154 -                       @"CSSM_EncryptData");
  23.155 -    else
  23.156 -        ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
  23.157 -                       @"CSSM_DecryptData");
  23.158 -    CSSM_DeleteContext(ccHandle);
  23.159 -    return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil;
  23.160 -}
  23.161 -
  23.162 -
  23.163 -CSSM_CC_HANDLE cssmCreateSignatureContext(SecKeyRef key) 
  23.164 -{
  23.165 -    const CSSM_KEY* cssmKey;
  23.166 -    const CSSM_ACCESS_CREDENTIALS *credentials;
  23.167 -    CSSM_CSP_HANDLE cspHandle;
  23.168 -    CSSM_CC_HANDLE ccHandle;
  23.169 -    if (check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey")
  23.170 -            && check(SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeWithUI,
  23.171 -                               &credentials), @"GetCredentials")
  23.172 -            && check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle")
  23.173 -            && checkcssm(CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_SHA1WithRSA, 
  23.174 -                                                          credentials,
  23.175 -                                                          cssmKey, &ccHandle),
  23.176 -                         @"CSSM_CSP_CreateSignatureContext") )
  23.177 -        return ccHandle;
  23.178 -    else
  23.179 -        return 0;
  23.180 -}
  23.181 -
  23.182 -static CSSM_CC_HANDLE cssmCreatePassThroughContext(SecKeyRef key) 
  23.183 -{
  23.184 -    const CSSM_KEY* cssmKey;
  23.185 -    CSSM_CSP_HANDLE cspHandle;
  23.186 -    CSSM_CC_HANDLE ccHandle;
  23.187 -    if (check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey")
  23.188 -            && check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle")
  23.189 -            && checkcssm(CSSM_CSP_CreatePassThroughContext(cspHandle, cssmKey, &ccHandle), 
  23.190 -                          @"CSSM_CSP_CreatePassThroughContext") )
  23.191 -        return ccHandle;
  23.192 -    else
  23.193 -        return 0;
  23.194 -}
  23.195 -
  23.196 -#endif !MYCRYPTO_USE_IPHONE_API
  23.197 -
  23.198 -
  23.199 -
  23.200  /*
  23.201   Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
  23.202   
    24.1 --- a/README.textile	Tue Apr 07 10:56:58 2009 -0700
    24.2 +++ b/README.textile	Wed Apr 08 16:30:52 2009 -0700
    24.3 @@ -24,7 +24,7 @@
    24.4  * Mac OS X 10.5 or later _[has been tested on 10.5.6]_
    24.5  * iPhone OS 2.0 or later _[not yet tested; see Limitations section below]_
    24.6  * iPhone Simulator, for iPhone OS 2.0 or later
    24.7 -* The MYUtilities library, which is used by MYCrypto.
    24.8 +* The "MYUtilities":http://mooseyard.com/hg/hgwebdir.cgi/MYUtilities library, which is used by MYCrypto.
    24.9  * _Some understanding of security and cryptography on your part!_ Even with convenient APIs, cryptographic operations still require care and knowledge to be used safely. There are already too many "examples":http://en.wikipedia.org/wiki/Wired_Equivalent_Privacy#Flaws of insecure systems that were incorrectly assembled from secure primitives; don't add your app to that list. Please read a good overview like "??Practical Cryptography??":http://www.schneier.com/book-practical.html before attempting anything the least bit fancy.
   24.10  
   24.11  h3. Current Limitations
   24.12 @@ -55,7 +55,7 @@
   24.13  ** "MYKey":Documentation/html/interfaceMYKey.html
   24.14  *** "*MYSymmetricKey*":Documentation/html/interfaceMYSymmetricKey.html
   24.15  *** "*MYPublicKey*":Documentation/html/interfaceMYPublicKey.html
   24.16 -**** "*MYKeyPair*":Documentation/html/interfaceMYKeyPair.html
   24.17 +*** "*MYPrivateKey*":Documentation/html/interfaceMYPrivateKey.html
   24.18  *** "*MYCertificate*":Documentation/html/interfaceMYCertificate.html
   24.19  * "MYDigest":Documentation/html/interfaceMYDigest.html
   24.20  ** "*MYSHA1Digest*":Documentation/html/interfaceMYSHA1Digest.html
   24.21 @@ -72,4 +72,5 @@
   24.22  * "??Common Security: CDSA and CSSM, Version 2??":http://www.opengroup.org/publications/catalog/c914.htm (The Open Group)
   24.23  
   24.24  * "??Practical Cryptography??":http://www.schneier.com/book-practical.html (Ferguson and Schneier)
   24.25 +* "??Handbook of Applied Cryptography":http://www.cacr.math.uwaterloo.ca/hac/ (Menezes, van Oorschot, Vanstone) -- free download!
   24.26  * "??The Devil's InfoSec Dictionary??":http://www.csoonline.com/article/220527/The_Devil_s_Infosec_Dictionary (CSO Online)
   24.27 \ No newline at end of file