# HG changeset patch # User snej@snej-mbp.mtv.corp.google.com # Date 1239233452 25200 # Node ID 1dfe820d7ebe4e9a5f133cb0ae557707b0fa2ad2 # Parent 8982b8fada63acb8ae5a693df54a8a96a468349f * Replaced MYKeyPair with MYPrivateKey. * Changed config files. diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto-iPhone.xcodeproj/project.pbxproj --- a/MYCrypto-iPhone.xcodeproj/project.pbxproj Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCrypto-iPhone.xcodeproj/project.pbxproj Wed Apr 08 16:30:52 2009 -0700 @@ -11,14 +11,12 @@ 1D60589B0D05DD56006BFB54 /* MYCrypto_iPhone_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* MYCrypto_iPhone_main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 273391A30F81E5E9009414D9 /* MYKeyPair-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */; }; - 273391A50F81E606009414D9 /* MYPublicKey-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */; }; 273391CD0F81EC70009414D9 /* MYCertificate-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273391CC0F81EC70009414D9 /* MYCertificate-iPhone.m */; }; 273392120F8283B8009414D9 /* MYKeychain-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 273392110F8283B8009414D9 /* MYKeychain-iPhone.m */; }; + 2748607F0F8D5E0600FE617B /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 2748607E0F8D5E0600FE617B /* MYPrivateKey.m */; }; 276FB13F0F84090900CB326E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 276FB13E0F84090900CB326E /* Security.framework */; }; 276FB16E0F84152B00CB326E /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB16D0F84152B00CB326E /* MYCryptoTest.m */; }; 276FB3190F856AA700CB326E /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB3180F856AA700CB326E /* MYPublicKey.m */; }; - 276FB3390F856AC300CB326E /* MYKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB3380F856AC300CB326E /* MYKeyPair.m */; }; 276FB33B0F856ACB00CB326E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB33A0F856ACB00CB326E /* MYKeychain.m */; }; 276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB34A0F856CA400CB326E /* MYCertificate.m */; }; 27A430120F87C6C10063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E823110F81D56E0019BE60 /* MYKey.m */; }; @@ -45,14 +43,13 @@ 1D3623250D0F684500981E51 /* MYCrypto_iPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCrypto_iPhoneAppDelegate.m; sourceTree = ""; }; 1D6058910D05DD3D006BFB54 /* MYCrypto-iPhone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MYCrypto-iPhone.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYKeyPair-iPhone.m"; sourceTree = ""; }; - 273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYPublicKey-iPhone.m"; sourceTree = ""; }; 273391CC0F81EC70009414D9 /* MYCertificate-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYCertificate-iPhone.m"; sourceTree = ""; }; 273392110F8283B8009414D9 /* MYKeychain-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYKeychain-iPhone.m"; sourceTree = ""; }; + 2748607D0F8D5DF200FE617B /* MYPrivateKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPrivateKey.h; sourceTree = ""; }; + 2748607E0F8D5E0600FE617B /* MYPrivateKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPrivateKey.m; sourceTree = ""; }; 276FB13E0F84090900CB326E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 276FB16D0F84152B00CB326E /* MYCryptoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptoTest.m; sourceTree = ""; }; 276FB3180F856AA700CB326E /* MYPublicKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPublicKey.m; sourceTree = ""; }; - 276FB3380F856AC300CB326E /* MYKeyPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeyPair.m; sourceTree = ""; }; 276FB33A0F856ACB00CB326E /* MYKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychain.m; sourceTree = ""; }; 276FB34A0F856CA400CB326E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = ""; }; 27A430130F87C6D50063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = ""; }; @@ -66,7 +63,6 @@ 27E823120F81D56E0019BE60 /* MYKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychain.h; sourceTree = ""; }; 27E823140F81D56E0019BE60 /* MYKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychainItem.h; sourceTree = ""; }; 27E823150F81D56E0019BE60 /* MYKeychainItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychainItem.m; sourceTree = ""; }; - 27E823160F81D56E0019BE60 /* MYKeyPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeyPair.h; sourceTree = ""; }; 27E823180F81D56E0019BE60 /* MYPublicKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPublicKey.h; sourceTree = ""; }; 27E8231A0F81D56E0019BE60 /* MYCrypto_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCrypto_Private.h; sourceTree = ""; }; 27E8231B0F81D56E0019BE60 /* MYDigest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYDigest.h; sourceTree = ""; }; @@ -143,12 +139,10 @@ 273392110F8283B8009414D9 /* MYKeychain-iPhone.m */, 27E823140F81D56E0019BE60 /* MYKeychainItem.h */, 27E823150F81D56E0019BE60 /* MYKeychainItem.m */, - 27E823160F81D56E0019BE60 /* MYKeyPair.h */, - 276FB3380F856AC300CB326E /* MYKeyPair.m */, - 273391A20F81E5E9009414D9 /* MYKeyPair-iPhone.m */, + 2748607D0F8D5DF200FE617B /* MYPrivateKey.h */, + 2748607E0F8D5E0600FE617B /* MYPrivateKey.m */, 27E823180F81D56E0019BE60 /* MYPublicKey.h */, 276FB3180F856AA700CB326E /* MYPublicKey.m */, - 273391A40F81E606009414D9 /* MYPublicKey-iPhone.m */, 27A430150F87C6DB0063D362 /* MYSymmetricKey.h */, 27A430130F87C6D50063D362 /* MYSymmetricKey.m */, 27E8231B0F81D56E0019BE60 /* MYDigest.h */, @@ -268,18 +262,16 @@ 27E823390F81D5760019BE60 /* Logging.m in Sources */, 27E8233A0F81D5760019BE60 /* Test.m in Sources */, 27E8233B0F81D5760019BE60 /* MYErrorUtils.m in Sources */, - 273391A30F81E5E9009414D9 /* MYKeyPair-iPhone.m in Sources */, - 273391A50F81E606009414D9 /* MYPublicKey-iPhone.m in Sources */, 273391CD0F81EC70009414D9 /* MYCertificate-iPhone.m in Sources */, 273392120F8283B8009414D9 /* MYKeychain-iPhone.m in Sources */, 276FB16E0F84152B00CB326E /* MYCryptoTest.m in Sources */, 276FB3190F856AA700CB326E /* MYPublicKey.m in Sources */, - 276FB3390F856AC300CB326E /* MYKeyPair.m in Sources */, 276FB33B0F856ACB00CB326E /* MYKeychain.m in Sources */, 276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */, 27A430120F87C6C10063D362 /* MYKey.m in Sources */, 27A430140F87C6D50063D362 /* MYSymmetricKey.m in Sources */, 27FE453F0F87CC8500A86D63 /* MYKey-iPhone.m in Sources */, + 2748607F0F8D5E0600FE617B /* MYPrivateKey.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto.xcconfig --- a/MYCrypto.xcconfig Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCrypto.xcconfig Wed Apr 08 16:30:52 2009 -0700 @@ -6,6 +6,4 @@ // Copyright 2009 Jens Alfke. All rights reserved. // -#include "../MYUtilities/MYUtilities.xcconfig" - GCC_PREFIX_HEADER = ../MYUtilities/MYUtilities_Prefix.pch diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto.xcodeproj/project.pbxproj --- a/MYCrypto.xcodeproj/project.pbxproj Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCrypto.xcodeproj/project.pbxproj Wed Apr 08 16:30:52 2009 -0700 @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 270B879F0F8C565000C56781 /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 270B879E0F8C565000C56781 /* MYPrivateKey.m */; }; 27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */; }; 27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E822A10F81C5660019BE60 /* MYKey.m */; }; 27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42D410F858ED80063D362 /* MYSymmetricKey.m */; }; @@ -14,7 +15,6 @@ 27CFF4C20F7E8535000B418E /* MYCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B40F7E8535000B418E /* MYCryptor.m */; }; 27CFF4C30F7E8535000B418E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B60F7E8535000B418E /* MYKeychain.m */; }; 27CFF4C40F7E8535000B418E /* MYKeychainItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B80F7E8535000B418E /* MYKeychainItem.m */; }; - 27CFF4C60F7E8535000B418E /* MYKeyPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4BB0F7E8535000B418E /* MYKeyPair.m */; }; 27CFF4C70F7E8535000B418E /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4BD0F7E8535000B418E /* MYPublicKey.m */; }; 27CFF4C80F7E8535000B418E /* MYDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4C00F7E8535000B418E /* MYDigest.m */; }; 27CFF4D50F7E8726000B418E /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4CE0F7E8726000B418E /* CollectionUtils.m */; }; @@ -42,6 +42,9 @@ /* Begin PBXFileReference section */ 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 270B879D0F8C565000C56781 /* MYPrivateKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPrivateKey.h; sourceTree = ""; }; + 270B879E0F8C565000C56781 /* MYPrivateKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPrivateKey.m; sourceTree = ""; }; + 2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYCrypto_Release.xcconfig; sourceTree = ""; }; 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptoTest.m; sourceTree = ""; }; 27A42D400F858ED80063D362 /* MYSymmetricKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYSymmetricKey.h; sourceTree = ""; }; 27A42D410F858ED80063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = ""; }; @@ -56,8 +59,6 @@ 27CFF4B60F7E8535000B418E /* MYKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychain.m; sourceTree = ""; }; 27CFF4B70F7E8535000B418E /* MYKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychainItem.h; sourceTree = ""; }; 27CFF4B80F7E8535000B418E /* MYKeychainItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychainItem.m; sourceTree = ""; }; - 27CFF4BA0F7E8535000B418E /* MYKeyPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeyPair.h; sourceTree = ""; }; - 27CFF4BB0F7E8535000B418E /* MYKeyPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeyPair.m; sourceTree = ""; }; 27CFF4BC0F7E8535000B418E /* MYPublicKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPublicKey.h; sourceTree = ""; }; 27CFF4BD0F7E8535000B418E /* MYPublicKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPublicKey.m; sourceTree = ""; }; 27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCrypto_Private.h; sourceTree = ""; }; @@ -103,6 +104,7 @@ isa = PBXGroup; children = ( 08FB7795FE84155DC02AAC07 /* Source */, + 270B881C0F8D055A00C56781 /* Internal */, 27CFF4CC0F7E86E8000B418E /* MYUtilities */, C6859EA2029092E104C91782 /* Documentation */, 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, @@ -128,20 +130,15 @@ 27CFF4B60F7E8535000B418E /* MYKeychain.m */, 27CFF4B70F7E8535000B418E /* MYKeychainItem.h */, 27CFF4B80F7E8535000B418E /* MYKeychainItem.m */, - 27CFF4BA0F7E8535000B418E /* MYKeyPair.h */, - 27CFF4BB0F7E8535000B418E /* MYKeyPair.m */, 27CFF4BC0F7E8535000B418E /* MYPublicKey.h */, 27CFF4BD0F7E8535000B418E /* MYPublicKey.m */, + 270B879D0F8C565000C56781 /* MYPrivateKey.h */, + 270B879E0F8C565000C56781 /* MYPrivateKey.m */, 27A42D400F858ED80063D362 /* MYSymmetricKey.h */, 27A42D410F858ED80063D362 /* MYSymmetricKey.m */, 27AAD97B0F892A0D0064DD7C /* MYCryptoConfig.h */, - 27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */, - 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */, - 27CFF5210F7E94DF000B418E /* MYCrypto_main.m */, 27A42ECC0F8689D30063D362 /* MYCertGen.h */, 27A42ECD0F8689D30063D362 /* MYCertGen.m */, - 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */, - 27CFF5400F7E9653000B418E /* MYCrypto_Debug.xcconfig */, 27EAF0390F8B2D700091AF95 /* README.textile */, ); name = Source; @@ -163,6 +160,19 @@ name = Products; sourceTree = ""; }; + 270B881C0F8D055A00C56781 /* Internal */ = { + isa = PBXGroup; + children = ( + 27CFF4BE0F7E8535000B418E /* MYCrypto_Private.h */, + 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */, + 27CFF5210F7E94DF000B418E /* MYCrypto_main.m */, + 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */, + 27CFF5400F7E9653000B418E /* MYCrypto_Debug.xcconfig */, + 2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */, + ); + name = Internal; + sourceTree = ""; + }; 27CFF4CC0F7E86E8000B418E /* MYUtilities */ = { isa = PBXGroup; children = ( @@ -198,6 +208,7 @@ 8DD76F990486AA7600D96B5E /* Sources */, 8DD76F9B0486AA7600D96B5E /* Frameworks */, 8DD76F9E0486AA7600D96B5E /* CopyFiles */, + 27EAF0C60F8BD4ED0091AF95 /* ShellScript */, ); buildRules = ( ); @@ -226,6 +237,23 @@ }; /* End PBXProject section */ +/* Begin PBXShellScriptBuildPhase section */ + 27EAF0C60F8BD4ED0091AF95 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/csh; + shellScript = "doxygen\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 8DD76F990486AA7600D96B5E /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -235,7 +263,6 @@ 27CFF4C20F7E8535000B418E /* MYCryptor.m in Sources */, 27CFF4C30F7E8535000B418E /* MYKeychain.m in Sources */, 27CFF4C40F7E8535000B418E /* MYKeychainItem.m in Sources */, - 27CFF4C60F7E8535000B418E /* MYKeyPair.m in Sources */, 27CFF4C70F7E8535000B418E /* MYPublicKey.m in Sources */, 27CFF4C80F7E8535000B418E /* MYDigest.m in Sources */, 27CFF4D50F7E8726000B418E /* CollectionUtils.m in Sources */, @@ -247,6 +274,7 @@ 27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */, 27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */, 27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */, + 270B879F0F8C565000C56781 /* MYPrivateKey.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -264,6 +292,7 @@ }; 1DEB927608733DD40010E9CD /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */; buildSettings = { INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = MYCrypto; @@ -279,7 +308,7 @@ }; 1DEB927A08733DD40010E9CD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 27CFF5120F7E9212000B418E /* MYCrypto.xcconfig */; + baseConfigurationReference = 2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */; buildSettings = { }; name = Release; diff -r 8982b8fada63 -r 1dfe820d7ebe MYCryptoTest.m --- a/MYCryptoTest.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCryptoTest.m Wed Apr 08 16:30:52 2009 -0700 @@ -6,7 +6,8 @@ // Copyright 2009 Jens Alfke. All rights reserved. // -#import "MYKeyPair.h" +#import "MYPublicKey.h" +#import "MYPrivateKey.h" #import "MYKeychain.h" #import "MYDigest.h" #import "MYCrypto_Private.h" @@ -44,10 +45,10 @@ Log(@"Found %@ -- name=%@", key, key.name); } - e = [[MYKeychain allKeychains] enumerateKeyPairs]; + e = [[MYKeychain allKeychains] enumeratePrivateKeys]; Log(@"Key-Pair Enumerator = %@", e); CAssert(e); - for (MYKeyPair *key in e) { + for (MYPrivateKey *key in e) { Log(@"Found %@ -- name=%@", key, key.name); } @@ -153,32 +154,25 @@ #pragma mark KEY-PAIRS: -TestCase(KeyPair) { +TestCase(MYPrivateKey) { RequireTestCase(MYKeychain); Log(@"Generating key pair..."); - MYKeyPair *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512]; + MYPrivateKey *pair = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512]; + Log(@"...created { %@ , %@ }.", pair, pair.publicKey); CAssert(pair); CAssert(pair.keyRef); - CAssert(pair.privateKeyRef); - Log(@"...created pair."); + MYPublicKey *publicKey = pair.publicKey; + CAssert(publicKey.keyRef); @try{ - [pair setName: @"Test KeyPair Label"]; - CAssertEqual(pair.name, @"Test KeyPair Label"); -#if !TARGET_OS_IPHONE - [pair setComment: @"This key-pair was generated automatically by a test case."]; - CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case."); -#endif - [pair setAlias: @"TestCase@mooseyard.com"]; - CAssertEqual(pair.alias, @"TestCase@mooseyard.com"); - - NSData *pubKeyData = pair.keyData; + NSData *pubKeyData = publicKey.keyData; Log(@"Public key = %@ (%u bytes)",pubKeyData,pubKeyData.length); CAssert(pubKeyData); - MYSHA1Digest *pubKeyDigest = pair.publicKeyDigest; + MYSHA1Digest *pubKeyDigest = publicKey.publicKeyDigest; Log(@"Public key digest = %@",pubKeyDigest); + CAssertEqual(pair.publicKeyDigest, pubKeyDigest); Log(@"SHA1 of pub key = %@", pubKeyData.my_SHA1Digest.asData); @@ -186,10 +180,22 @@ NSData *sig = [pair signData: data]; Log(@"Signature = %@ (%u bytes)",sig,sig.length); CAssert(sig); - CAssert( [pair verifySignature: sig ofData: data] ); + CAssert( [publicKey verifySignature: sig ofData: data] ); + + [pair setName: @"Test KeyPair Label"]; + CAssertEqual(pair.name, @"Test KeyPair Label"); + CAssertEqual(publicKey.name, @"Test KeyPair Label"); +#if !TARGET_OS_IPHONE + [pair setComment: @"This key-pair was generated automatically by a test case."]; + CAssertEqual(pair.comment, @"This key-pair was generated automatically by a test case."); + CAssertEqual(publicKey.comment, @"This key-pair was generated automatically by a test case."); +#endif + [pair setAlias: @"TestCase@mooseyard.com"]; + CAssertEqual(pair.alias, @"TestCase@mooseyard.com"); + CAssertEqual(publicKey.alias, @"TestCase@mooseyard.com"); // Test creating a standalone public key: - MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: pair.keyRef]; + MYPublicKey *pub = [[MYPublicKey alloc] initWithKeyRef: publicKey.keyRef]; CAssert( [pub verifySignature: sig ofData: data] ); Log(@"Verified signature."); @@ -233,14 +239,14 @@ static void testKeyPairExportWithPrompt(BOOL withPrompt) { MYKeychain *keychain = [MYKeychain allKeychains]; Log(@"Generating key pair..."); - MYKeyPair *pair = [keychain generateRSAKeyPairOfSize: 512]; + MYPrivateKey *pair = [keychain generateRSAKeyPairOfSize: 512]; CAssert(pair); CAssert(pair.keyRef); - CAssert(pair.privateKeyRef); + CAssert(pair.publicKey.keyRef); Log(@"...created pair."); @try{ - NSData *pubKeyData = pair.keyData; + NSData *pubKeyData = pair.publicKey.keyData; CAssert(pubKeyData.length >= 512/8); [pair setName: @"Test KeyPair Label"]; CAssertEqual(pair.name, @"Test KeyPair Label"); @@ -256,11 +262,11 @@ NSString *passphrase = @"passphrase"; NSData *privKeyData; if (withPrompt) - privKeyData = [pair exportPrivateKey]; + privKeyData = [pair exportKey]; else - privKeyData = [pair _exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL - withPEM: YES - passphrase: passphrase]; + privKeyData = [pair _exportKeyInFormat: kSecFormatWrappedOpenSSL + withPEM: YES + passphrase: passphrase]; Log(@"Exported data = %@ (%u bytes)", privKeyData,privKeyData.length); CAssert(privKeyData); [privKeyData writeToFile: @"ExportedPrivKey" atomically: YES]; @@ -270,11 +276,11 @@ Log(@"Looking up public key of pair in keychain..."); MYSHA1Digest *digest = pair.publicKeyDigest; MYPublicKey *foundKey = [keychain publicKeyWithDigest: digest]; - CAssertEqual(foundKey, pair.asPublicKey); - CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.asPublicKey]); - MYKeyPair *foundPair = [keychain keyPairWithDigest: digest]; + CAssertEqual(foundKey, pair.publicKey); + CAssert([keychain.enumeratePublicKeys.allObjects containsObject: pair.publicKey]); + MYPrivateKey *foundPair = [keychain privateKeyWithDigest: digest]; CAssertEqual(foundPair, pair); - CAssert([keychain.enumerateKeyPairs.allObjects containsObject: pair]); + CAssert([keychain.enumeratePrivateKeys.allObjects containsObject: pair]); Log(@"Removing key-pair from keychain..."); CAssert([pair removeFromKeychain]); @@ -287,14 +293,14 @@ pair = [keychain importPublicKey: pubKeyData privateKey: privKeyData]; } else { - pair = [[[MYKeyPair alloc] _initWithPublicKeyData: pubKeyData - privateKeyData: privKeyData - forKeychain: keychain.keychainRefOrDefault - passphrase: passphrase] + pair = [[[MYPrivateKey alloc] _initWithKeyData: privKeyData + publicKeyData: pubKeyData + forKeychain: keychain.keychainRefOrDefault + passphrase: passphrase] autorelease]; } CAssert(pair); - CAssertEqual(pair.keyData, pubKeyData); + CAssertEqual(pair.publicKey.keyData, pubKeyData); #endif }@finally { if (pair) { @@ -308,7 +314,7 @@ TestCase(KeyPairExport) { RequireTestCase(MYKeychain); - RequireTestCase(KeyPair); + RequireTestCase(MYPrivateKey); testKeyPairExportWithPrompt(NO); } diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto_Debug.xcconfig --- a/MYCrypto_Debug.xcconfig Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCrypto_Debug.xcconfig Wed Apr 08 16:30:52 2009 -0700 @@ -6,6 +6,7 @@ // Copyright 2009 Jens Alfke. All rights reserved. // +#include "../MYUtilities/MYUtilities_Debug.xcconfig" #include "MYCrypto.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto_Private.h --- a/MYCrypto_Private.h Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCrypto_Private.h Wed Apr 08 16:30:52 2009 -0700 @@ -10,7 +10,8 @@ #import "MYKeychain.h" #import "MYKey.h" #import "MYSymmetricKey.h" -#import "MYKeyPair.h" +#import "MYPublicKey.h" +#import "MYPrivateKey.h" #import "MYCertificate.h" #import "Test.h" #import @@ -52,9 +53,13 @@ - (id) _initWithKeyData: (NSData*)data forKeychain: (SecKeychainRef)keychain; @property (readonly) SecExternalItemType keyType; +@property (readonly) MYSHA1Digest* _keyDigest; +- (NSData*) _crypt: (NSData *)data operation: (BOOL) op; // YES to encrypt, NO to decrypt #if !MYCRYPTO_USE_IPHONE_API @property (readonly) const CSSM_KEY* cssmKey; - (NSData*) exportKeyInFormat: (SecExternalFormat)format withPEM: (BOOL)withPEM; +- (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm; +- (CSSM_CC_HANDLE) _createPassThroughContext; #endif @property (readonly) NSArray* _itemList; @end @@ -68,27 +73,26 @@ @interface MYPublicKey (Private) -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key; - (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr; @end -@interface MYKeyPair (Private) -+ (MYKeyPair*) _generateRSAKeyPairOfSize: (unsigned)keySize - inKeychain: (MYKeychain*)keychain; -- (id) _initWithPublicKeyData: (NSData*)pubKeyData - privateKeyData: (NSData*)privKeyData - forKeychain: (SecKeychainRef)keychain - alertTitle: (NSString*)title - alertPrompt: (NSString*)prompt; -- (id) _initWithPublicKeyData: (NSData*)pubKeyData - privateKeyData: (NSData*)privKeyData - forKeychain: (SecKeychainRef)keychain - passphrase: (NSString*)passphrase; +@interface MYPrivateKey (Private) ++ (MYPrivateKey*) _generateRSAKeyPairOfSize: (unsigned)keySize + inKeychain: (MYKeychain*)keychain; +- (id) _initWithKeyData: (NSData*)privKeyData + publicKeyData: (NSData*)pubKeyData + forKeychain: (SecKeychainRef)keychain + alertTitle: (NSString*)title + alertPrompt: (NSString*)prompt; +- (id) _initWithKeyData: (NSData*)privKeyData + publicKeyData: (NSData*)pubKeyData + forKeychain: (SecKeychainRef)keychain + passphrase: (NSString*)passphrase; #if !TARGET_OS_IPHONE -- (NSData*) _exportPrivateKeyInFormat: (SecExternalFormat)format - withPEM: (BOOL)withPEM - passphrase: (NSString*)passphrase; +- (NSData*) _exportKeyInFormat: (SecExternalFormat)format + withPEM: (BOOL)withPEM + passphrase: (NSString*)passphrase; #endif @end @@ -102,8 +106,6 @@ #endif -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op); - #undef check BOOL check(OSStatus err, NSString *what); @@ -114,5 +116,4 @@ SecExternalItemType type, SecKeychainRef keychain, SecKeyImportExportParameters *params /*non-null*/); -CSSM_CC_HANDLE cssmCreateSignatureContext(SecKeyRef key); #endif diff -r 8982b8fada63 -r 1dfe820d7ebe MYCrypto_Release.xcconfig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYCrypto_Release.xcconfig Wed Apr 08 16:30:52 2009 -0700 @@ -0,0 +1,10 @@ +// +// MYCrypto_Release.xcconfig +// MYCrypto +// +// Created by Jens Alfke on 4/8/09. +// Copyright 2009 Jens Alfke. All rights reserved. +// + +#include "../MYUtilities/MYUtilities_Release.xcconfig" +#include "MYCrypto.xcconfig" diff -r 8982b8fada63 -r 1dfe820d7ebe MYCryptor.m --- a/MYCryptor.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCryptor.m Wed Apr 08 16:30:52 2009 -0700 @@ -57,11 +57,14 @@ fromPassphrase: (NSString*)passphrase salt: (id)salt { + // This follows algorithm PBKDF1 from PKCS#5 v2.0, with Hash=SHA-256 and c=13. Assert(passphrase); Assert(salt); passphrase = $sprintf(@"MYCrypto|%@|%@", passphrase, salt); size_t lengthInBytes = (lengthInBits + 7)/8; MYDigest *digest = [[passphrase dataUsingEncoding: NSUTF8StringEncoding] my_SHA256Digest]; + for (int i=0; i<12; i++) + digest = digest.asData.my_SHA256Digest; if (lengthInBytes <= digest.length) return [digest.asData subdataWithRange: NSMakeRange(0,lengthInBytes)]; else @@ -126,7 +129,7 @@ - (BOOL) _outputBytes: (const void*)bytes length: (size_t)length { if (_outputStream) { - NSInteger written = [_outputStream write: bytes maxLength: length]; + size_t written = [_outputStream write: bytes maxLength: length]; if (written < 0) { self.error = _outputStream.streamError; if (_error) diff -r 8982b8fada63 -r 1dfe820d7ebe MYDigest.h --- a/MYDigest.h Tue Apr 07 10:56:58 2009 -0700 +++ b/MYDigest.h Wed Apr 08 16:30:52 2009 -0700 @@ -84,6 +84,7 @@ /** Create a MYSHA1Digest object given an existing raw SHA-1 digest. */ + (MYSHA1Digest*) digestFromRawSHA1Digest: (const RawSHA1Digest*)rawDigest; +/** The SHA-1 digest as a C struct */ @property (readonly) const RawSHA1Digest* rawSHA1Digest; @end @@ -104,6 +105,7 @@ /** Create a MYSHA256Digest object given an existing raw SHA-1 digest. */ + (MYSHA256Digest*) digestFromRawSHA256Digest: (const RawSHA256Digest*)rawDigest; +/** The SHA-256 digest as a C struct */ @property (readonly) const RawSHA256Digest* rawSHA256Digest; @end diff -r 8982b8fada63 -r 1dfe820d7ebe MYDigest.m --- a/MYDigest.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYDigest.m Wed Apr 08 16:30:52 2009 -0700 @@ -90,7 +90,7 @@ if( !cStr || strlen(cStr)!=2*length ) return nil; uint8_t digest[length]; - for( int i=0; iData) { + digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data + length: keyDigest->Length] autorelease]; + } + } else { + SecKeyRef keyRef = self.keyRef; + // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to + // be ones that are either expired or don't have a matching public key at all (?) + Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')", + keyRef, + self.name, + self.comment); + NSData *digestData = [[self class] _getAttribute: kSecKeyLabel + ofItem: (SecKeychainItemRef)keyRef]; + if (digestData) { + digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData]; + if (!digest) + Warn(@"Digest property of key %p was invalid SHA-1: %@", keyRef,digestData); + } + } + CSSM_DeleteContext(context); + } + return digest; +} + + +/** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */ +- (NSData*) _crypt: (NSData*)data operation: (BOOL)operation { + CAssert(data); + const CSSM_ACCESS_CREDENTIALS *credentials; + credentials = [self cssmCredentialsForOperation: (operation ?CSSM_ACL_AUTHORIZATION_ENCRYPT + :CSSM_ACL_AUTHORIZATION_DECRYPT) + type: kSecCredentialTypeDefault + error: nil]; + if (!credentials) + return nil; + + CSSM_CC_HANDLE ccHandle; + if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(self.cssmCSPHandle, + CSSM_ALGID_RSA, + credentials, + self.cssmKey, + CSSM_PADDING_PKCS1, + &ccHandle), + @"CSSM_CSP_CreateAsymmetricContext")) + return nil; + + CSSM_DATA original = {data.length, (void*)data.bytes}; + CSSM_DATA result = {}; + size_t outputLength; + BOOL ok; + if (operation) + ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result), + @"CSSM_EncryptData"); + else + ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result), + @"CSSM_DecryptData"); + CSSM_DeleteContext(ccHandle); + return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil; +} + + +- (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm { + const CSSM_ACCESS_CREDENTIALS *credentials; + credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_SIGN + type: kSecCredentialTypeDefault + error: nil]; + if (credentials) { + CSSM_CC_HANDLE ccHandle = 0; + if (checkcssm(CSSM_CSP_CreateSignatureContext(self.cssmCSPHandle, + algorithm, + credentials, + self.cssmKey, + &ccHandle), + @"CSSM_CSP_CreateSignatureContext") ) + return ccHandle; + } + return 0; +} + +- (CSSM_CC_HANDLE) _createPassThroughContext +{ + CSSM_CC_HANDLE ccHandle = 0; + if (checkcssm(CSSM_CSP_CreatePassThroughContext(self.cssmCSPHandle, self.cssmKey, &ccHandle), + @"CSSM_CSP_CreatePassThroughContext") ) + return ccHandle; + else + return 0; +} + + +@end + #endif MYCRYPTO_USE_IPHONE_API diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeyPair.h --- a/MYKeyPair.h Tue Apr 07 10:56:58 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -// -// KeyPair.h -// MYCrypto -// -// Created by Jens Alfke on 3/21/09. -// Copyright 2009 Jens Alfke. All rights reserved. -// - -#import "MYPublicKey.h" - - -/** A key-pair consisting of a public and a private key. - Can be used for signing and decrypting, as well as the inherited encrypting/verifying. - Instances are generated by MYKeychain objects. */ -@interface MYKeyPair : MYPublicKey -{ - @private - SecKeyRef _privateKey; -} - -/** Decrypts data that was encrypted using the public key. - See the description of -[MYPublicKey encryptData:] for warnings and caveats. - This method is usually used only to decrypt a symmetric session key, which then decrypts the - rest of the data. */ -- (NSData*) decryptData: (NSData*)data; - -/** Generates a signature of data, using the private key. - (What's actually signed using RSA is the SHA-256 digest of the data.) - The resulting signature can be verified using the matching MYPublicKey's - verifySignature:ofData: method. */ -- (NSData*) signData: (NSData*)data; - - -/** @name Mac-Only - * Functionality not available on iPhone. - */ -//@{ -#if !TARGET_OS_IPHONE - -/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred - to another computer. Since the key is sensitive, it must be exported in encrypted form - using a user-chosen passphrase. This method will display a standard alert panel, run by - the Security agent, that prompts the user to enter a new passphrase for encrypting the key. - The same passphrase must be re-entered when importing the key from the data blob. - (This is a convenient shorthand for the full exportPrivateKeyInFormat... method. - It uses OpenSSL format, wrapped with PEM, and a default title and prompt for the alert.) */ -- (NSData*) exportPrivateKey; - -/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred - to another computer. Since the key is sensitive, it must be exported in encrypted form - using a user-chosen passphrase. This method will display a standard alert panel, run by - the Security agent, that prompts the user to enter a new passphrase for encrypting the key. - The same passphrase must be re-entered when importing the key from the data blob. - @param format The data format: kSecFormatOpenSSL, kSecFormatSSH, kSecFormatBSAFE or kSecFormatSSHv2. - @param withPEM YES if the data should be encoded in PEM format, which converts into short lines - of printable ASCII characters, suitable for sending in email. - @param alertTitle An optional title for the alert panel. (Currently ignored by the OS?) - @param prompt An optional prompt message to display in the alert panel. */ -- (NSData*) exportPrivateKeyInFormat: (SecExternalFormat)format - withPEM: (BOOL)withPEM - alertTitle: (NSString*)alertTitle - alertPrompt: (NSString*)prompt; - -#endif -//@} - - -/** @name Expert - * Advanced functionality. - */ -//@{ - -/** Creates a MYKeyPair object from existing Keychain key references. */ -- (id) initWithPublicKeyRef: (SecKeyRef)publicKey privateKeyRef: (SecKeyRef)privateKey; - -/** The underlying Keychain key reference for the private key. */ -@property (readonly) SecKeyRef privateKeyRef; - -//@} - -@end diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeyPair.m --- a/MYKeyPair.m Tue Apr 07 10:56:58 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -// -// KeyPair.m -// MYCrypto -// -// Created by Jens Alfke on 3/21/09. -// Copyright 2009 Jens Alfke. All rights reserved. -// - -#import "MYKeyPair.h" -#import "MYCrypto_Private.h" -#import - -#if !MYCRYPTO_USE_IPHONE_API - - -#pragma mark - - -@implementation MYKeyPair - - -+ (MYKeyPair*) _generateRSAKeyPairOfSize: (unsigned)keySize - inKeychain: (MYKeychain*)keychain { - Assert( keySize == 512 || keySize == 1024 || keySize == 2048, @"Unsupported key size %u", keySize ); - SecKeyRef pubKey=NULL, privKey=NULL; - OSStatus err; - err = SecKeyCreatePair(keychain.keychainRefOrDefault, - CSSM_ALGID_RSA, - keySize, - 0LL, - CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY, // public key - CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT, - CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN, // private key - CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_PERMANENT, - NULL, // SecAccessRef - &pubKey, &privKey); - if (!check(err, @"SecKeyCreatePair")) { - return nil; - } else - return [[[self alloc] initWithPublicKeyRef: pubKey privateKeyRef: privKey] autorelease]; -} - - -- (id) initWithPublicKeyRef: (SecKeyRef)publicKey privateKeyRef: (SecKeyRef)privateKey { - self = [super initWithKeyRef: publicKey]; - if (self) { - NSParameterAssert(privateKey); - _privateKey = (SecKeyRef) CFRetain(privateKey); - } - return self; -} - -- (id) _initWithPublicKeyData: (NSData*)pubKeyData - privateKey: (SecKeyRef)privateKey - forKeychain: (SecKeychainRef)keychain { - if (!privateKey) { - [self release]; - return nil; - } - self = [self _initWithKeyData: pubKeyData forKeychain: keychain]; - if (self) { - _privateKey = privateKey; - } else { - SecKeychainItemDelete((SecKeychainItemRef)privateKey); - CFRelease(privateKey); - } - return self; -} - - -// The public API for this is in MYKeychain. -- (id) _initWithPublicKeyData: (NSData*)pubKeyData - privateKeyData: (NSData*)privKeyData - forKeychain: (SecKeychainRef)keychain - alertTitle: (NSString*)title - alertPrompt: (NSString*)prompt -{ - // Try to import the private key first, since the user might cancel the passphrase alert. - SecKeyImportExportParameters params = { - .flags = kSecKeySecurePassphrase, - .alertTitle = (CFStringRef) title, - .alertPrompt = (CFStringRef) prompt - }; - SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,¶ms); - return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain]; -} - -// This method is for testing, so unit-tests don't require user intervention. -// It's deliberately not made public, to discourage clients from trying to manage the passphrases -// themselves (this is less secure than letting the Security agent do it.) -- (id) _initWithPublicKeyData: (NSData*)pubKeyData - privateKeyData: (NSData*)privKeyData - forKeychain: (SecKeychainRef)keychain - passphrase: (NSString*)passphrase -{ - SecKeyImportExportParameters params = { - .passphrase = (CFStringRef) passphrase, - }; - SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,¶ms); - return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain]; -} - - -- (void) dealloc -{ - if (_privateKey) CFRelease(_privateKey); - [super dealloc]; -} - -- (void) finalize -{ - if (_privateKey) CFRelease(_privateKey); - [super finalize]; -} - - -- (NSUInteger)hash { - // Ensure that a KeyPair doesn't hash the same as its corresponding PublicKey: - return super.hash ^ 0xFFFFFFFF; -} - - -- (MYPublicKey*) asPublicKey { - return [[[MYPublicKey alloc] initWithKeyRef: self.keyRef] autorelease]; -} - - -- (NSData*) exportPrivateKeyInFormat: (SecExternalFormat)format - withPEM: (BOOL)withPEM - alertTitle: (NSString*)title - alertPrompt: (NSString*)prompt -{ - SecKeyImportExportParameters params = { - .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, - .flags = kSecKeySecurePassphrase, - .alertTitle = (CFStringRef)title, - .alertPrompt = (CFStringRef)prompt - }; - CFDataRef data = NULL; - if (check(SecKeychainItemExport(_privateKey, //$array((id)_publicKey,(id)_privateKey), - format, (withPEM ?kSecItemPemArmour :0), - ¶ms, &data), - @"SecKeychainItemExport")) - return [(id)CFMakeCollectable(data) autorelease]; - else - return nil; -} - -- (NSData*) exportPrivateKey { - return [self exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL withPEM: YES - alertTitle: @"Export Private Key" - alertPrompt: @"Enter a passphrase to protect the private-key file.\n" - "You will need to re-enter the passphrase later when importing the key from this file, " - "so keep it in a safe place."]; - //FIX: Should make these messages localizable. -} - - -- (NSData*) _exportPrivateKeyInFormat: (SecExternalFormat)format - withPEM: (BOOL)withPEM - passphrase: (NSString*)passphrase -{ - SecKeyImportExportParameters params = { - .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, - .passphrase = (CFStringRef)passphrase - }; - CFDataRef data = NULL; - if (check(SecKeychainItemExport(_privateKey, - format, (withPEM ?kSecItemPemArmour :0), - ¶ms, &data), - @"SecKeychainItemExport")) - return [(id)CFMakeCollectable(data) autorelease]; - else - return nil; -} - -- (BOOL) removeFromKeychain { - return check(SecKeychainItemDelete((SecKeychainItemRef)_privateKey), @"delete private key") - && [super removeFromKeychain]; -} - - -- (SecKeyRef) privateKeyRef { - return _privateKey; -} - - -- (NSData*) decryptData: (NSData*)data { - return _crypt(_privateKey,data,kCCDecrypt); -} - - -- (NSData*) signData: (NSData*)data { - Assert(data); - uint8_t digest[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256(data.bytes,data.length, digest); - - NSData *signature = nil; - CSSM_CC_HANDLE ccHandle = cssmCreateSignatureContext(_privateKey); - if (!ccHandle) return nil; - CSSM_DATA original = {data.length, (void*)data.bytes}; - CSSM_DATA result = {0,NULL}; - if (checkcssm(CSSM_SignData(ccHandle, &original, 1, CSSM_ALGID_NONE, &result), @"CSSM_SignData")) - signature = [NSData dataWithBytesNoCopy: result.Data length: result.Length - freeWhenDone: YES]; - CSSM_DeleteContext(ccHandle); - return signature; -} - - -- (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr { - return [super setValue: valueStr ofAttribute: attr] - && [[self class] _setAttribute: attr - ofItem: (SecKeychainItemRef)_privateKey - stringValue: valueStr]; -} - - -@end - - -#endif !MYCRYPTO_USE_IPHONE_API - - - - -/* - Copyright (c) 2009, Jens Alfke . All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions - and the following disclaimer in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI- - BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeychain-iPhone.m --- a/MYKeychain-iPhone.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYKeychain-iPhone.m Wed Apr 08 16:30:52 2009 -0700 @@ -74,7 +74,7 @@ } -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest { +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest { return [MYKeyEnumerator firstItemWithQuery: $mdict({(id)kSecClass, (id)kSecClassKey}, {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate}, @@ -82,7 +82,7 @@ {(id)kSecReturnRef, $true})]; } -- (NSEnumerator*) enumerateKeyPairs { +- (NSEnumerator*) enumeratePrivateKeys { NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey}, {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate}, {(id)kSecMatchLimit, (id)kSecMatchLimitAll}, @@ -156,8 +156,8 @@ algorithm: algorithm inKeychain: self]; } -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize { - return [MYKeyPair _generateRSAKeyPairOfSize: keySize inKeychain: self]; +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize { + return [MYPrivateKey _generateRSAKeyPairOfSize: keySize inKeychain: self]; } @@ -211,19 +211,7 @@ while (next==nil && _index < CFArrayGetCount(_results)) { CFTypeRef found = CFArrayGetValueAtIndex(_results, _index++); if (_itemClass == kSecAttrKeyClassPrivate) { - MYSHA1Digest *digest = [MYPublicKey _digestOfKey: (SecKeyRef)found]; - if (digest) { - MYPublicKey *publicKey = [[MYKeychain defaultKeychain] publicKeyWithDigest: digest]; - if (publicKey) - next = [[[MYKeyPair alloc] initWithPublicKeyRef: publicKey.keyRef - privateKeyRef: (SecKeyRef)found] - autorelease]; - else { - // The matching public key won't turn up if it's embedded in a certificate; - // I'd have to search for certs if I wanted to look that up. Skip it for now. - //Warn(@"Couldn't find matching public key for private key!"); - } - } + next = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found]; } else if (_itemClass == kSecAttrKeyClassPublic) { next = [[[MYPublicKey alloc] initWithKeyRef: (SecKeyRef)found] autorelease]; } else if (_itemClass == kSecAttrKeyClassSymmetric) { diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeychain.h --- a/MYKeychain.h Tue Apr 07 10:56:58 2009 -0700 +++ b/MYKeychain.h Wed Apr 08 16:30:52 2009 -0700 @@ -8,7 +8,7 @@ #import #import "MYCryptoConfig.h" -@class MYSymmetricKey, MYPublicKey, MYKeyPair, MYCertificate, MYSHA1Digest; +@class MYSymmetricKey, MYPublicKey, MYPrivateKey, MYCertificate, MYSHA1Digest; /** A Keychain, a secure database of cryptographic keys. @@ -77,16 +77,16 @@ to break, but operate more slowly and generate larger signatures. 2048 is a good default choice. You could use 1024 if the data and signatures won't need to stay secure for years; or you could use 4096 if you're extremely paranoid. */ -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize; +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize; /** Looks up an existing key-pair whose public key has the given digest. Returns nil if there is no such key-pair in the keychain. (This method does not look for public keys embedded in certificates, only 'bare' keys.) */ -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest; +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest; /** Enumerates all key-pairs in the keychain. (This method does not find keys embedded in certificates, only 'bare' keys.) */ -- (NSEnumerator*) enumerateKeyPairs; +- (NSEnumerator*) enumeratePrivateKeys; #pragma mark - @@ -109,14 +109,14 @@ of both the public and private keys. Since the private key data is wrapped (encrypted), the Security agent will prompt the user to enter the passphrase. */ -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData privateKey: (NSData*)privKeyData; /** Imports a key-pair into the keychain, given the external representations of both the public and private keys. Since the private key data is wrapped (encrypted), the Security agent will prompt the user to enter the passphrase. You can specify the title and prompt message for this alert panel. */ -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData privateKey: (NSData*)privKeyData alertTitle: (NSString*)title alertPrompt: (NSString*)prompt; diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeychain.m --- a/MYKeychain.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYKeychain.m Wed Apr 08 16:30:52 2009 -0700 @@ -229,11 +229,11 @@ } -- (MYKeyPair*) keyPairWithDigest: (MYSHA1Digest*)pubKeyDigest { - return (MYKeyPair*) [self itemOfClass: kSecPrivateKeyItemClass withDigest: pubKeyDigest]; +- (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest { + return (MYPrivateKey*) [self itemOfClass: kSecPrivateKeyItemClass withDigest: pubKeyDigest]; } -- (NSEnumerator*) enumerateKeyPairs { +- (NSEnumerator*) enumeratePrivateKeys { return [[[MYKeyEnumerator alloc] initWithKeychain: self itemClass: kSecPrivateKeyItemClass attributes: NULL count: 0] autorelease]; @@ -275,19 +275,19 @@ autorelease]; } -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData privateKey: (NSData*)privKeyData alertTitle: (NSString*)title alertPrompt: (NSString*)prompt { - return [[[MYKeyPair alloc] _initWithPublicKeyData: pubKeyData - privateKeyData: privKeyData - forKeychain: self.keychainRefOrDefault - alertTitle: (NSString*)title - alertPrompt: (NSString*)prompt] + return [[[MYPrivateKey alloc] _initWithKeyData: privKeyData + publicKeyData: pubKeyData + forKeychain: self.keychainRefOrDefault + alertTitle: (NSString*)title + alertPrompt: (NSString*)prompt] autorelease]; } -- (MYKeyPair*) importPublicKey: (NSData*)pubKeyData +- (MYPrivateKey*) importPublicKey: (NSData*)pubKeyData privateKey: (NSData*)privKeyData { return [self importPublicKey: pubKeyData privateKey: privKeyData @@ -326,8 +326,8 @@ algorithm: algorithm inKeychain: self]; } -- (MYKeyPair*) generateRSAKeyPairOfSize: (unsigned)keySize { - return [MYKeyPair _generateRSAKeyPairOfSize: keySize inKeychain: self]; +- (MYPrivateKey*) generateRSAKeyPairOfSize: (unsigned)keySize { + return [MYPrivateKey _generateRSAKeyPairOfSize: keySize inKeychain: self]; } @@ -398,19 +398,7 @@ switch (_itemClass) { case kSecPrivateKeyItemClass: { - MYSHA1Digest *digest = [MYPublicKey _digestOfKey: (SecKeyRef)found]; - if (digest) { - MYPublicKey *publicKey = [_keychain publicKeyWithDigest: digest]; - if (publicKey) - key = [[[MYKeyPair alloc] initWithPublicKeyRef: publicKey.keyRef - privateKeyRef: (SecKeyRef)found] - autorelease]; - else { - // The matching public key won't turn up if it's embedded in a certificate; - // I'd have to search for certs if I wanted to look that up. Skip it for now. - //Warn(@"Couldn't find matching public key for private key! digest=%@",digest); - } - } + key = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found]; break; } case kSecCertificateItemClass: diff -r 8982b8fada63 -r 1dfe820d7ebe MYKeychainItem.m --- a/MYKeychainItem.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYKeychainItem.m Wed Apr 08 16:30:52 2009 -0700 @@ -50,10 +50,8 @@ } - (BOOL) isEqual: (id)obj { - // Require the objects to be of the same class, so that a MYPublicKey will not be equal to a - // MYKeyPair with the same public key. - return (obj == self) || - ([obj class] == [self class] && CFEqual(_itemRef, [obj keychainItemRef])); + return (obj == self) || + ([obj isKindOfClass: [MYKeychainItem class]] && CFEqual(_itemRef, [obj keychainItemRef])); } - (NSUInteger) hash { diff -r 8982b8fada63 -r 1dfe820d7ebe MYPrivateKey.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYPrivateKey.h Wed Apr 08 16:30:52 2009 -0700 @@ -0,0 +1,77 @@ +// +// MYPrivateKey.h +// MYCrypto +// +// Created by Jens Alfke on 4/7/09. +// Copyright 2009 Jens Alfke. All rights reserved. +// + +#import "MYKey.h" +@class MYPublicKey, MYSHA1Digest; + + +/** A private key, used for signing and decrypting data. + Always paired with a matching public key in a "key-pair". + MYPublicKeys are instantiated by MYKeychain: either by generating a new key-pair, by + looking up a key-pair by its attributes, or by importing a key-pair from data. */ +@interface MYPrivateKey : MYKey +{ + @private + MYPublicKey *_publicKey; +} + +/** The matching public key. Always non-nil. */ +@property (readonly) MYPublicKey *publicKey; + +/** The public key's SHA-1 digest. + This is a convenient short (20-byte) identifier for the key pair. You can store it in your + application data, and then later look up either key using MYKeychain methods. */ +@property (readonly) MYSHA1Digest *publicKeyDigest; + + +/** Decrypts data that was encrypted using the public key. + See the description of -[MYPublicKey encryptData:] for warnings and caveats. + This method is usually used only to decrypt a symmetric session key, which then decrypts the + rest of the data. */ +- (NSData*) decryptData: (NSData*)data; + +/** Generates a signature of data. + (What's actually signed using RSA is the SHA-256 digest of the data.) + The resulting signature can be verified using the matching MYPublicKey's + verifySignature:ofData: method. */ +- (NSData*) signData: (NSData*)data; + + +/** @name Mac-Only + * Functionality not available on iPhone. + */ +//@{ +#if !TARGET_OS_IPHONE + +/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred + to another computer. Since the key is sensitive, it must be exported in encrypted form + using a user-chosen passphrase. This method will display a standard alert panel, run by + the Security agent, that prompts the user to enter a new passphrase for encrypting the key. + The same passphrase must be re-entered when importing the key from the data blob. + (This is a convenient shorthand for the full exportPrivateKeyInFormat... method. + It uses OpenSSL format, wrapped with PEM, and a default title and prompt for the alert.) */ +- (NSData*) exportKey; + +/** Exports the private key as a data blob, so that it can be stored as a backup, or transferred + to another computer. Since the key is sensitive, it must be exported in encrypted form + using a user-chosen passphrase. This method will display a standard alert panel, run by + the Security agent, that prompts the user to enter a new passphrase for encrypting the key. + The same passphrase must be re-entered when importing the key from the data blob. + @param format The data format: kSecFormatOpenSSL, kSecFormatSSH, kSecFormatBSAFE or kSecFormatSSHv2. + @param withPEM YES if the data should be encoded in PEM format, which converts into short lines + of printable ASCII characters, suitable for sending in email. + @param alertTitle An optional title for the alert panel. (Currently ignored by the OS?) + @param prompt An optional prompt message to display in the alert panel. */ +- (NSData*) exportKeyInFormat: (SecExternalFormat)format + withPEM: (BOOL)withPEM + alertTitle: (NSString*)alertTitle + alertPrompt: (NSString*)prompt; +#endif +//@} + +@end diff -r 8982b8fada63 -r 1dfe820d7ebe MYPrivateKey.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYPrivateKey.m Wed Apr 08 16:30:52 2009 -0700 @@ -0,0 +1,293 @@ +// +// MYPrivateKey.m +// MYCrypto +// +// Created by Jens Alfke on 4/7/09. +// Copyright 2009 Jens Alfke. All rights reserved. +// + +#import "MYPrivateKey.h" +#import "MYCrypto_Private.h" +#import "MYDigest.h" +#import + + +@implementation MYPrivateKey + + +- (id) initWithKeyRef: (SecKeyRef)privateKey +{ + self = [super initWithKeyRef: privateKey]; + if (self) { + // No public key given, so look it up: + MYSHA1Digest *digest = self._keyDigest; + if (digest) + _publicKey = [[self.keychain publicKeyWithDigest: digest] retain]; + if (!_publicKey) { + // The matching public key won't turn up if it's embedded in a certificate; + // I'd have to search for certs if I wanted to look that up. Skip it for now. + Log(@"MYPrivateKey(%p): Couldn't find matching public key for private key! digest=%@", + self, digest); + [self release]; + return nil; + } + } + return self; +} + + +- (id) _initWithKeyRef: (SecKeyRef)privateKey + publicKey: (MYPublicKey*)publicKey +{ + Assert(publicKey); + self = [super initWithKeyRef: privateKey]; + if (self) { + _publicKey = [publicKey retain]; + } + return self; +} + +- (id) initWithKeyRef: (SecKeyRef)privateKey + publicKeyRef: (SecKeyRef)publicKeyRef +{ + MYPublicKey *publicKey = [[MYPublicKey alloc] initWithKeyRef: publicKeyRef]; + self = [self _initWithKeyRef: privateKey publicKey: publicKey]; + [publicKey release]; + return self; +} + +- (id) _initWithKeyRef: (SecKeyRef)privateKey + publicKeyData: (NSData*)pubKeyData + forKeychain: (SecKeychainRef)keychain +{ + if (!privateKey) { + [self release]; + return nil; + } + MYPublicKey *pubKey = [[MYPublicKey alloc] _initWithKeyData: pubKeyData forKeychain: keychain]; + if (!pubKey) { + [self release]; + return nil; + } + self = [super initWithKeyRef: privateKey]; + if (self) { + _publicKey = pubKey; + } else { + [pubKey removeFromKeychain]; + [pubKey release]; + } + return self; +} + + +#if !TARGET_OS_IPHONE + +// The public API for this is in MYKeychain. +- (id) _initWithKeyData: (NSData*)privKeyData + publicKeyData: (NSData*)pubKeyData + forKeychain: (SecKeychainRef)keychain + alertTitle: (NSString*)title + alertPrompt: (NSString*)prompt +{ + // Try to import the private key first, since the user might cancel the passphrase alert. + SecKeyImportExportParameters params = { + .flags = kSecKeySecurePassphrase, + .alertTitle = (CFStringRef) title, + .alertPrompt = (CFStringRef) prompt + }; + SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,¶ms); + return [self _initWithKeyRef: privateKey publicKeyData: pubKeyData forKeychain: keychain]; +} + +// This method is for testing, so unit-tests don't require user intervention. +// It's deliberately not made public, to discourage clients from trying to manage the passphrases +// themselves (this is less secure than letting the Security agent do it.) +- (id) _initWithKeyData: (NSData*)privKeyData + publicKeyData: (NSData*)pubKeyData + forKeychain: (SecKeychainRef)keychain + passphrase: (NSString*)passphrase +{ + SecKeyImportExportParameters params = { + .passphrase = (CFStringRef) passphrase, + }; + SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,¶ms); + return [self _initWithKeyRef: privateKey publicKeyData: pubKeyData forKeychain: keychain]; +} + +#endif + + +- (void) dealloc +{ + [_publicKey release]; + [super dealloc]; +} + + ++ (MYPrivateKey*) _generateRSAKeyPairOfSize: (unsigned)keySize + inKeychain: (MYKeychain*)keychain +{ + Assert( keySize == 512 || keySize == 1024 || keySize == 2048, @"Unsupported key size %u", keySize ); + SecKeyRef pubKey=NULL, privKey=NULL; + OSStatus err; + +#if MYCRYPTO_USE_IPHONE_API + NSDictionary *pubKeyAttrs = $dict({(id)kSecAttrIsPermanent, $true}); + NSDictionary *privKeyAttrs = $dict({(id)kSecAttrIsPermanent, $true}); + NSDictionary *keyAttrs = $dict( {(id)kSecAttrKeyType, (id)kSecAttrKeyTypeRSA}, + {(id)kSecAttrKeySizeInBits, $object(keySize)}, + {(id)kSecPublicKeyAttrs, pubKeyAttrs}, + {(id)kSecPrivateKeyAttrs, privKeyAttrs} ); + err = SecKeyGeneratePair((CFDictionaryRef)keyAttrs,&pubKey,&privKey); +#else + err = SecKeyCreatePair(keychain.keychainRefOrDefault, + CSSM_ALGID_RSA, + keySize, + 0LL, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY, // public key + CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN, // private key + CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_PERMANENT, + NULL, // SecAccessRef + &pubKey, &privKey); +#endif + if (!check(err, @"SecKeyCreatePair")) { + return nil; + } else + return [[[self alloc] initWithKeyRef: privKey publicKeyRef: pubKey] autorelease]; +} + + +#pragma mark - +#pragma mark ACCESSORS: + + +- (NSString*) description { + return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString); +} + +@synthesize publicKey=_publicKey; + +- (MYSHA1Digest*) publicKeyDigest { + return _publicKey.publicKeyDigest; +} + +- (SecExternalItemType) keyType { +#if MYCRYPTO_USE_IPHONE_API + return kSecAttrKeyClassPublic; +#else + return kSecItemTypePrivateKey; +#endif +} + +- (NSData *) keyData { + [NSException raise: NSGenericException format: @"Can't access keyData of a PrivateKey"]; + return nil; +} + +- (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr { + return [super setValue: valueStr ofAttribute: attr] + && [_publicKey setValue: valueStr ofAttribute: attr]; +} + + +#pragma mark - +#pragma mark OPERATIONS: + + +- (BOOL) removeFromKeychain { + return [super removeFromKeychain] + && [_publicKey removeFromKeychain]; +} + + +- (NSData*) decryptData: (NSData*)data { + return [self _crypt: data operation: NO]; +} + + +- (NSData*) signData: (NSData*)data { + Assert(data); +#if MYCRYPTO_USE_IPHONE_API + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes,data.length, digest); + + size_t sigLen = 1024; + uint8_t sigBuf[sigLen]; + OSStatus err = SecKeyRawSign(self.keyRef, kSecPaddingPKCS1SHA1, + digest,sizeof(digest), //data.bytes, data.length, + sigBuf, &sigLen); + if(err) { + Warn(@"SecKeyRawSign failed: %i",err); + return nil; + } else + return [NSData dataWithBytes: sigBuf length: sigLen]; +#else + NSData *signature = nil; + CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA]; + if (!ccHandle) return nil; + CSSM_DATA original = {data.length, (void*)data.bytes}; + CSSM_DATA result = {0,NULL}; + if (checkcssm(CSSM_SignData(ccHandle, &original, 1, CSSM_ALGID_NONE, &result), @"CSSM_SignData")) + signature = [NSData dataWithBytesNoCopy: result.Data length: result.Length + freeWhenDone: YES]; + CSSM_DeleteContext(ccHandle); + return signature; +#endif +} + + +#if !TARGET_OS_IPHONE + +- (NSData*) exportKeyInFormat: (SecExternalFormat)format + withPEM: (BOOL)withPEM + alertTitle: (NSString*)title + alertPrompt: (NSString*)prompt +{ + SecKeyImportExportParameters params = { + .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, + .flags = kSecKeySecurePassphrase, + .alertTitle = (CFStringRef)title, + .alertPrompt = (CFStringRef)prompt + }; + CFDataRef data = NULL; + if (check(SecKeychainItemExport(self.keyRef, + format, (withPEM ?kSecItemPemArmour :0), + ¶ms, &data), + @"SecKeychainItemExport")) + return [(id)CFMakeCollectable(data) autorelease]; + else + return nil; +} + +- (NSData*) exportKey { + return [self exportKeyInFormat: kSecFormatWrappedOpenSSL withPEM: YES + alertTitle: @"Export Private Key" + alertPrompt: @"Enter a passphrase to protect the private-key file.\n" + "You will need to re-enter the passphrase later when importing the key from this file, " + "so keep it in a safe place."]; + //FIX: Should make these messages localizable. +} + + +- (NSData*) _exportKeyInFormat: (SecExternalFormat)format + withPEM: (BOOL)withPEM + passphrase: (NSString*)passphrase +{ + SecKeyImportExportParameters params = { + .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, + .passphrase = (CFStringRef)passphrase + }; + CFDataRef data = NULL; + if (check(SecKeychainItemExport(self.keyRef, + format, (withPEM ?kSecItemPemArmour :0), + ¶ms, &data), + @"SecKeychainItemExport")) + return [(id)CFMakeCollectable(data) autorelease]; + else + return nil; +} + +#endif TARGET_OS_IPHONE + +@end diff -r 8982b8fada63 -r 1dfe820d7ebe MYPublicKey-iPhone.m --- a/MYPublicKey-iPhone.m Tue Apr 07 10:56:58 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -// -// MYPublicKey-iPhone.m -// MYCrypto-iPhone -// -// Created by Jens Alfke on 3/30/09. -// Copyright 2009 Jens Alfke. All rights reserved. -// - -#import "MYPublicKey.h" -#import "MYCrypto_Private.h" - -#if MYCRYPTO_USE_IPHONE_API - -#import "MYDigest.h" -#import "MYErrorUtils.h" -#import - - -@implementation MYPublicKey - - -- (void) dealloc -{ - [_digest release]; - [super dealloc]; -} - - -- (SecExternalItemType) keyType { - return kSecAttrKeyClassPublic; -} - - -- (MYPublicKey*) asPublicKey { - return self; -} - - -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key { - NSData *digestData = [MYKeychainItem _getAttribute: kSecAttrApplicationLabel ofItem: key]; - if (digestData) - return (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData]; - else { - Warn(@"MYKeyPair: public keyref %p didn't have digest attribute", key); - return nil; - } -} - - -- (MYSHA1Digest*) publicKeyDigest { - return [[self class] _digestOfKey: self.keyRef]; -} - - -- (NSData*) encryptData: (NSData*)data { - return _crypt(self.keyRef,data,kCCEncrypt); -} - - -- (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data { - Assert(data); - Assert(signature); - uint8_t digest[CC_SHA1_DIGEST_LENGTH]; - CC_SHA1(data.bytes,data.length, digest); - OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1, - digest,sizeof(digest), //data.bytes, data.length, - signature.bytes, signature.length); - return err==noErr; -} - - -@end - - - - -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op) { - CAssert(data); - size_t dataLength = data.length; - size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key)); - void *outputBuf = malloc(outputLength); - if (!outputBuf) return nil; - OSStatus err; - if (op==kCCEncrypt) - err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1, - data.bytes, dataLength, - outputBuf, &outputLength); - else - err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1, - data.bytes, dataLength, - outputBuf, &outputLength); - if (err) { - free(outputBuf); - Warn(@"%scrypting failed (%i)", (op==kCCEncrypt ?"En" :"De"), err); - // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h) - return nil; - } else - return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES]; -} - -#endif MYCRYPTO_USE_IPHONE_API diff -r 8982b8fada63 -r 1dfe820d7ebe MYPublicKey.h --- a/MYPublicKey.h Tue Apr 07 10:56:58 2009 -0700 +++ b/MYPublicKey.h Wed Apr 08 16:30:52 2009 -0700 @@ -15,8 +15,8 @@ /** A public key, which can be used for encrypting data and verifying signatures. - MYPublicKeys are created as part of generating a MYKeyPair, - or by being imported into a MYKeychain. */ + MYPublicKeys are created as part of generating a key-pair, + or by being imported from data into a MYKeychain. */ @interface MYPublicKey : MYKey { @private @@ -26,11 +26,6 @@ /** The public key's SHA-1 digest. This is a convenient short (20-byte) identifier for the key. */ @property (readonly) MYSHA1Digest *publicKeyDigest; -/** Returns the receiver as a MYPublicKey. - If the receiver already is a MYPublicKey, this just returns self. - If it's a MYKeyPair, it returns a new MYPublicKey containing just the public key. */ -@property (readonly) MYPublicKey *asPublicKey; - /** Encrypts a short piece of data using this key, returning the raw encrypted result. An RSA key can encrypt only blocks smaller than its own key size; this method will fail and return nil if the data is too long. diff -r 8982b8fada63 -r 1dfe820d7ebe MYPublicKey.m --- a/MYPublicKey.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYPublicKey.m Wed Apr 08 16:30:52 2009 -0700 @@ -8,17 +8,11 @@ #import "MYPublicKey.h" #import "MYCrypto_Private.h" - -#if !MYCRYPTO_USE_IPHONE_API - #import "MYDigest.h" #import "MYErrorUtils.h" #import -static CSSM_CC_HANDLE cssmCreatePassThroughContext(SecKeyRef key); - - #pragma mark - @implementation MYPublicKey @@ -30,8 +24,13 @@ } - (SecExternalItemType) keyType { +#if MYCRYPTO_USE_IPHONE_API + return kSecAttrKeyClassPublic; +#else return kSecItemTypePublicKey; +#endif } + - (NSUInteger)hash { return self.publicKeyDigest.hash; } @@ -40,64 +39,38 @@ return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString); } -- (MYPublicKey*) asPublicKey { - return self; -} - - -+ (MYSHA1Digest*) _digestOfKey: (SecKeyRef)key { - Assert(key); - MYSHA1Digest *digest = nil; - CSSM_DATA *keyDigest = NULL; - CSSM_CC_HANDLE context = cssmCreatePassThroughContext(key); - if (context) { - if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest), - @"CSSM_CSP_PassThrough")) { - if (keyDigest && keyDigest->Data) { - digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data - length: keyDigest->Length] autorelease]; - } - } else { - // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to - // be ones that are either expired or don't have a matching public key at all (?) - Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')", key, - [self _getStringAttribute: kSecKeyPrintName ofItem: (SecKeychainItemRef)key], - [self _getStringAttribute: kSecKeyApplicationTag ofItem: (SecKeychainItemRef)key]); - NSData *digestData = [self _getAttribute: kSecKeyLabel ofItem: (SecKeychainItemRef)key]; - if (digestData) { - digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData]; - if (!digest) - Warn(@"Digest property of key %p was invalid SHA-1: %@", key,digestData); - } - } - CSSM_DeleteContext(context); - } - return digest; -} - - (MYSHA1Digest*) publicKeyDigest { if (!_digest) - _digest = [[[self class] _digestOfKey: self.keyRef] retain]; + _digest = [[self _keyDigest] retain]; return _digest; } +#if !MYCRYPTO_USE_IPHONE_API - (NSData*) keyData { return [self exportKeyInFormat: kSecFormatOpenSSL withPEM: NO]; } +#endif - (NSData*) encryptData: (NSData*)data { - return _crypt(self.keyRef,data,kCCEncrypt); + return [self _crypt: data operation: YES]; } - (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data { Assert(data); Assert(signature); - uint8_t digest[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256(data.bytes,data.length, digest); - CSSM_CC_HANDLE ccHandle = cssmCreateSignatureContext(self.keyRef); +#if MYCRYPTO_USE_IPHONE_API + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes,data.length, digest); + OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1, + digest,sizeof(digest), //data.bytes, data.length, + signature.bytes, signature.length); + return err==noErr; + +#else + CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA]; if (!ccHandle) return NO; CSSM_DATA original = {data.length, (void*)data.bytes}; CSSM_DATA sig = {signature.length, (void*)signature.bytes}; @@ -108,6 +81,7 @@ if (cssmErr != CSSMERR_CSP_VERIFY_FAILED) Warn(@"CSSM error verifying signature: %u", MYErrorName(MYCSSMErrorDomain,cssmErr)); return NO; +#endif } @@ -115,80 +89,6 @@ - -#pragma mark - -#pragma mark UTILITY FUNCTIONS: - - -NSData* _crypt(SecKeyRef key, NSData *data, CCOperation op) { - CAssert(data); - const CSSM_KEY* cssmKey; - const CSSM_ACCESS_CREDENTIALS *credentials; - CSSM_CSP_HANDLE cspHandle; - CSSM_CC_HANDLE ccHandle; - if (!check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey") - || !check(SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeWithUI, - &credentials), @"GetCredentials") - || !check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle") - - || !checkcssm(CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA, - credentials, cssmKey, - CSSM_PADDING_PKCS1, &ccHandle), - @"CSSM_CSP_CreateAsymmetricContext")) - return nil; - - CSSM_DATA original = {data.length, (void*)data.bytes}; - CSSM_DATA result = {}; - size_t outputLength; - BOOL ok; - if (op==kCCEncrypt) - ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result), - @"CSSM_EncryptData"); - else - ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result), - @"CSSM_DecryptData"); - CSSM_DeleteContext(ccHandle); - return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil; -} - - -CSSM_CC_HANDLE cssmCreateSignatureContext(SecKeyRef key) -{ - const CSSM_KEY* cssmKey; - const CSSM_ACCESS_CREDENTIALS *credentials; - CSSM_CSP_HANDLE cspHandle; - CSSM_CC_HANDLE ccHandle; - if (check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey") - && check(SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeWithUI, - &credentials), @"GetCredentials") - && check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle") - && checkcssm(CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_SHA1WithRSA, - credentials, - cssmKey, &ccHandle), - @"CSSM_CSP_CreateSignatureContext") ) - return ccHandle; - else - return 0; -} - -static CSSM_CC_HANDLE cssmCreatePassThroughContext(SecKeyRef key) -{ - const CSSM_KEY* cssmKey; - CSSM_CSP_HANDLE cspHandle; - CSSM_CC_HANDLE ccHandle; - if (check(SecKeyGetCSSMKey(key, &cssmKey), @"GetCSSMKey") - && check(SecKeyGetCSPHandle(key, &cspHandle), @"GetCSPHandle") - && checkcssm(CSSM_CSP_CreatePassThroughContext(cspHandle, cssmKey, &ccHandle), - @"CSSM_CSP_CreatePassThroughContext") ) - return ccHandle; - else - return 0; -} - -#endif !MYCRYPTO_USE_IPHONE_API - - - /* Copyright (c) 2009, Jens Alfke . All rights reserved. diff -r 8982b8fada63 -r 1dfe820d7ebe README.textile --- a/README.textile Tue Apr 07 10:56:58 2009 -0700 +++ b/README.textile Wed Apr 08 16:30:52 2009 -0700 @@ -24,7 +24,7 @@ * Mac OS X 10.5 or later _[has been tested on 10.5.6]_ * iPhone OS 2.0 or later _[not yet tested; see Limitations section below]_ * iPhone Simulator, for iPhone OS 2.0 or later -* The MYUtilities library, which is used by MYCrypto. +* The "MYUtilities":http://mooseyard.com/hg/hgwebdir.cgi/MYUtilities library, which is used by MYCrypto. * _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. h3. Current Limitations @@ -55,7 +55,7 @@ ** "MYKey":Documentation/html/interfaceMYKey.html *** "*MYSymmetricKey*":Documentation/html/interfaceMYSymmetricKey.html *** "*MYPublicKey*":Documentation/html/interfaceMYPublicKey.html -**** "*MYKeyPair*":Documentation/html/interfaceMYKeyPair.html +*** "*MYPrivateKey*":Documentation/html/interfaceMYPrivateKey.html *** "*MYCertificate*":Documentation/html/interfaceMYCertificate.html * "MYDigest":Documentation/html/interfaceMYDigest.html ** "*MYSHA1Digest*":Documentation/html/interfaceMYSHA1Digest.html @@ -72,4 +72,5 @@ * "??Common Security: CDSA and CSSM, Version 2??":http://www.opengroup.org/publications/catalog/c914.htm (The Open Group) * "??Practical Cryptography??":http://www.schneier.com/book-practical.html (Ferguson and Schneier) +* "??Handbook of Applied Cryptography":http://www.cacr.math.uwaterloo.ca/hac/ (Menezes, van Oorschot, Vanstone) -- free download! * "??The Devil's InfoSec Dictionary??":http://www.csoonline.com/article/220527/The_Devil_s_Infosec_Dictionary (CSO Online) \ No newline at end of file