* Replaced MYKeyPair with MYPrivateKey.
* Changed config files.
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,¶ms);
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,¶ms);
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 - ¶ms, &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 - ¶ms, &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,¶ms);
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,¶ms);
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 + ¶ms, &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 + ¶ms, &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