Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first commit

  • Loading branch information...
commit a78ac884e46006b40bc702b65fa111039b881eca 0 parents
@samrobbins samrobbins authored
5 .gitignore
@@ -0,0 +1,5 @@
+.DS_Store
+build
+*.xcuserstate
+*.xcuserdatad
+
0  README.md
No changes.
7 SecureUDID-Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'SecureUDID' target in the 'SecureUDID' project
+//
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+#endif
46 SecureUDID.h
@@ -0,0 +1,46 @@
+//
+// SecureUDID.h
+// SecureUDID
+//
+// Created by Crashlytics Team on 3/22/12.
+// Copyright (c) 2012 Crashlytics, Inc. All rights reserved.
+// http://www.crashlytics.com
+// info@crashlytics.com
+//
+
+/*
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface SecureUDID : NSObject
+
+/*
+ Returns a unique id for the device, sandboxed to the domain and salt provided.
+
+ Example usage:
+ #import "SecureUDID.h"
+
+ NSString *udid = [SecureUDID UDIDForDomain:@"com.example.myapp" salt:@"superSecretCodeHere!@##%#$#%$^"];
+
+ */
++ (NSString *)UDIDForDomain:(NSString *)domain salt:(NSString *)salt;
+
+@end
217 SecureUDID.m
@@ -0,0 +1,217 @@
+//
+// SecureUDID.m
+// SecureUDID
+//
+// Created by Crashlytics Team on 3/22/12.
+// Copyright (c) 2012 Crashlytics, Inc. All rights reserved.
+// http://www.crashlytics.com
+// info@crashlytics.com
+//
+
+/*
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#import "SecureUDID.h"
+#import <UIKit/UIKit.h>
+#import <CommonCrypto/CommonCryptor.h>
+#import <CommonCrypto/CommonKeyDerivation.h>
+#import <CommonCrypto/CommonDigest.h>
+
+#define SECURE_UDID_MAX_PASTEBOARD_ENTRIES (100)
+
+NSString *const SUTypeDataDictionary = @"public.secureudid";
+NSString *const SUTimeStampKey = @"SUTimeStampKey";
+NSString *const SUOwnerKey = @"SUOwnerKey";
+NSString *const SUPastboardFileFormat = @"org.secureudid-%d";
+
+NSData * cryptorToData(CCOperation operation, NSData *value, NSData *key);
+NSString * cryptorToString(CCOperation operation, NSData *value, NSData *key);
+NSString * pasteboardNameForNumber(NSInteger number);
+UIPasteboard * pasteboardForEncryptedDomain(NSData *encryptedDomain);
+
+@implementation SecureUDID
+
++ (NSString *)UDIDForDomain:(NSString *)domain salt:(NSString *)salt {
+ NSData *domainAndSalt = [[NSString stringWithFormat:@"%@%@", domain, salt] dataUsingEncoding:NSUTF8StringEncoding];
+
+ uint8_t digest[kCCKeySizeAES128] = {0};
+ CC_SHA1(domainAndSalt.bytes, domainAndSalt.length, digest);
+
+ NSData *key = [NSData dataWithBytes:digest length:kCCKeySizeAES128];
+
+ NSData *encryptedDomain = cryptorToData(kCCEncrypt, [domain dataUsingEncoding:NSUTF8StringEncoding], key);
+
+ UIPasteboard *pasteboard = pasteboardForEncryptedDomain(encryptedDomain);
+
+ NSMutableDictionary *secureUDIDDictionary = nil;
+
+ id pasteboardData = [pasteboard dataForPasteboardType:SUTypeDataDictionary];
+
+ if (pasteboardData) {
+ pasteboardData = [NSKeyedUnarchiver unarchiveObjectWithData:pasteboardData];
+ secureUDIDDictionary = [NSMutableDictionary dictionaryWithDictionary:pasteboardData];
+ } else {
+ secureUDIDDictionary = [NSMutableDictionary dictionaryWithCapacity:1];
+ }
+
+ NSData *valueFromPastboard = [secureUDIDDictionary objectForKey:encryptedDomain];
+
+ if (valueFromPastboard) {
+ return cryptorToString(kCCDecrypt, valueFromPastboard, key);
+ }
+
+ CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
+ CFStringRef uuidStr = CFUUIDCreateString(kCFAllocatorDefault, uuid);
+ CFRelease(uuid);
+
+ NSData *data = cryptorToData(kCCEncrypt, [(NSString *)uuidStr dataUsingEncoding:NSUTF8StringEncoding], key);
+
+ [secureUDIDDictionary setObject:data forKey:encryptedDomain];
+ [secureUDIDDictionary setObject:[NSDate date] forKey:SUTimeStampKey];
+ [secureUDIDDictionary setObject:encryptedDomain forKey:SUOwnerKey];
+
+ [pasteboard setData:[NSKeyedArchiver archivedDataWithRootObject:secureUDIDDictionary] forPasteboardType:SUTypeDataDictionary];
+
+ return [(NSString *)uuidStr autorelease];
+}
+
+/*
+ Applies the operation (encrypt or decrypt) to the NSData value with the provided NSData key returns the vaule as NSData.
+ */
+NSData * cryptorToData(CCOperation operation, NSData *value, NSData *key) {
+ NSMutableData *output = [NSMutableData dataWithLength:value.length + kCCBlockSizeAES128];
+
+ size_t numBytes = 0;
+ CCCryptorStatus cryptStatus = CCCrypt(operation,
+ kCCAlgorithmAES128,
+ kCCOptionPKCS7Padding,
+ [key bytes],
+ kCCKeySizeAES128,
+ NULL,
+ value.bytes,
+ value.length,
+ output.mutableBytes,
+ output.length,
+ &numBytes);
+
+ if (cryptStatus == kCCSuccess) {
+ return [[[NSData alloc] initWithBytes:output.bytes length:numBytes] autorelease];
+ }
+
+ return nil;
+}
+
+/*
+ Applies the operation (encrypt or decrypt) to the NSData value with the provided NSData key returns the vaule as an NSString.
+ */
+NSString * cryptorToString(CCOperation operation, NSData *value, NSData *key) {
+ return [[[NSString alloc] initWithData:cryptorToData(operation, value, key) encoding:NSUTF8StringEncoding] autorelease];
+}
+
+/*
+ Returns an NSString formatted with the supplied number.
+ */
+NSString * pasteboardNameForNumber(NSInteger number) {
+ return [NSString stringWithFormat:SUPastboardFileFormat, number];
+}
+
+/*
+ Returns a pasteboard for the encrypted domain. If a pasteboard for the domain is not found a new one is created.
+ */
+UIPasteboard * pasteboardForEncryptedDomain(NSData *encryptedDomain) {
+ UIPasteboard* usablePasteboard;
+ NSInteger lowestUnusedIndex;
+ NSInteger ownerIndex;
+ NSDate* mostRecentDate;
+ NSMutableDictionary* mostRecentDictionary;
+
+ usablePasteboard = nil;
+ lowestUnusedIndex = INTMAX_MAX;
+ mostRecentDate = [NSDate distantPast];
+ mostRecentDictionary = nil;
+ ownerIndex = -1;
+
+ // first, check for matching pasteboards
+ for (NSInteger i = 0; i < SECURE_UDID_MAX_PASTEBOARD_ENTRIES; ++i) {
+ UIPasteboard* pasteboard;
+ NSDate* modifiedDate;
+ NSDictionary* dictionary;
+ NSData* pasteboardData;
+
+ pasteboard = [UIPasteboard pasteboardWithName:pasteboardNameForNumber(i) create:NO];
+ if (!pasteboard) {
+ if (lowestUnusedIndex == -1) {
+ lowestUnusedIndex = i;
+ }
+
+ continue;
+ }
+
+ // ok, found a pasteboard, check for our value
+ pasteboardData = [pasteboard valueForPasteboardType:SUTypeDataDictionary];
+ if (!pasteboardData) {
+ // corrupted slot
+ if (lowestUnusedIndex == -1) {
+ lowestUnusedIndex = i;
+ }
+
+ continue;
+ }
+
+ dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:pasteboardData];
+ modifiedDate = [dictionary valueForKey:SUTimeStampKey];
+
+ if ([modifiedDate compare:mostRecentDate] == NSOrderedDescending) {
+ mostRecentDate = modifiedDate;
+ mostRecentDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary];
+ usablePasteboard = pasteboard;
+ }
+
+ if ([[dictionary objectForKey:SUOwnerKey] isEqual:encryptedDomain]) {
+ ownerIndex = i;
+ }
+ }
+
+ if (ownerIndex == -1) {
+
+ // if this is nil, we haven't found anything on this device
+ if (!mostRecentDictionary) {
+ mostRecentDictionary = [NSMutableDictionary dictionary];
+ }
+
+ [mostRecentDictionary setObject:encryptedDomain forKey:SUOwnerKey];
+ [mostRecentDictionary setObject:[NSDate date] forKey:SUTimeStampKey];
+
+ if ((lowestUnusedIndex < 0) || (lowestUnusedIndex >= SECURE_UDID_MAX_PASTEBOARD_ENTRIES)) {
+ return nil;
+ }
+
+ usablePasteboard = [UIPasteboard pasteboardWithName:pasteboardNameForNumber(lowestUnusedIndex) create:YES];
+ usablePasteboard.persistent = YES;
+
+ [usablePasteboard setData:[NSKeyedArchiver archivedDataWithRootObject:mostRecentDictionary] forPasteboardType:SUTypeDataDictionary];
+ }
+
+ assert(usablePasteboard);
+
+ return usablePasteboard;
+}
+
+@end
303 SecureUDID.xcodeproj/project.pbxproj
@@ -0,0 +1,303 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 221B739C1520A6E1005015FE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 221B73991520A6CD005015FE /* UIKit.framework */; };
+ 221DD6AB152161240023C82A /* SecureUDID.m in Sources */ = {isa = PBXBuildFile; fileRef = 22EB0AF61520A5D5008DB8C8 /* SecureUDID.m */; };
+ 22EB0AFF1520A5D5008DB8C8 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22EB0AFE1520A5D5008DB8C8 /* SenTestingKit.framework */; };
+ 22EB0B021520A5D5008DB8C8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22EB0AF01520A5D5008DB8C8 /* Foundation.framework */; };
+ 22EB0B0B1520A5D5008DB8C8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 22EB0B091520A5D5008DB8C8 /* InfoPlist.strings */; };
+ 22EB0B0E1520A5D5008DB8C8 /* SecureUDIDTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 22EB0B0D1520A5D5008DB8C8 /* SecureUDIDTests.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 221B73991520A6CD005015FE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 22EB0AF01520A5D5008DB8C8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 22EB0AF41520A5D5008DB8C8 /* SecureUDID-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SecureUDID-Prefix.pch"; sourceTree = SOURCE_ROOT; };
+ 22EB0AF51520A5D5008DB8C8 /* SecureUDID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecureUDID.h; sourceTree = SOURCE_ROOT; };
+ 22EB0AF61520A5D5008DB8C8 /* SecureUDID.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecureUDID.m; sourceTree = SOURCE_ROOT; };
+ 22EB0AFD1520A5D5008DB8C8 /* SecureUDIDTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureUDIDTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22EB0AFE1520A5D5008DB8C8 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
+ 22EB0B081520A5D5008DB8C8 /* SecureUDIDTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SecureUDIDTests-Info.plist"; sourceTree = "<group>"; };
+ 22EB0B0A1520A5D5008DB8C8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 22EB0B0D1520A5D5008DB8C8 /* SecureUDIDTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SecureUDIDTests.m; path = SecureUDIDTests/SecureUDIDTests.m; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 22EB0AF91520A5D5008DB8C8 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 221B739C1520A6E1005015FE /* UIKit.framework in Frameworks */,
+ 22EB0AFF1520A5D5008DB8C8 /* SenTestingKit.framework in Frameworks */,
+ 22EB0B021520A5D5008DB8C8 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 22EB0AE21520A5D5008DB8C8 = {
+ isa = PBXGroup;
+ children = (
+ 22EB0AF21520A5D5008DB8C8 /* SecureUDID */,
+ 22EB0B061520A5D5008DB8C8 /* SecureUDIDTests */,
+ 22EB0AEF1520A5D5008DB8C8 /* Frameworks */,
+ 22EB0AEE1520A5D5008DB8C8 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 22EB0AEE1520A5D5008DB8C8 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 22EB0AFD1520A5D5008DB8C8 /* SecureUDIDTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 22EB0AEF1520A5D5008DB8C8 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 221B73991520A6CD005015FE /* UIKit.framework */,
+ 22EB0AF01520A5D5008DB8C8 /* Foundation.framework */,
+ 22EB0AFE1520A5D5008DB8C8 /* SenTestingKit.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 22EB0AF21520A5D5008DB8C8 /* SecureUDID */ = {
+ isa = PBXGroup;
+ children = (
+ 22EB0AF51520A5D5008DB8C8 /* SecureUDID.h */,
+ 22EB0AF61520A5D5008DB8C8 /* SecureUDID.m */,
+ 22EB0AF31520A5D5008DB8C8 /* Supporting Files */,
+ );
+ path = SecureUDID;
+ sourceTree = "<group>";
+ };
+ 22EB0AF31520A5D5008DB8C8 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 22EB0AF41520A5D5008DB8C8 /* SecureUDID-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 22EB0B061520A5D5008DB8C8 /* SecureUDIDTests */ = {
+ isa = PBXGroup;
+ children = (
+ 22EB0B0D1520A5D5008DB8C8 /* SecureUDIDTests.m */,
+ 22EB0B071520A5D5008DB8C8 /* Supporting Files */,
+ );
+ path = SecureUDIDTests;
+ sourceTree = "<group>";
+ };
+ 22EB0B071520A5D5008DB8C8 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 22EB0B081520A5D5008DB8C8 /* SecureUDIDTests-Info.plist */,
+ 22EB0B091520A5D5008DB8C8 /* InfoPlist.strings */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 22EB0AFC1520A5D5008DB8C8 /* SecureUDIDTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 22EB0B141520A5D5008DB8C8 /* Build configuration list for PBXNativeTarget "SecureUDIDTests" */;
+ buildPhases = (
+ 22EB0AF81520A5D5008DB8C8 /* Sources */,
+ 22EB0AF91520A5D5008DB8C8 /* Frameworks */,
+ 22EB0AFA1520A5D5008DB8C8 /* Resources */,
+ 22EB0AFB1520A5D5008DB8C8 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SecureUDIDTests;
+ productName = SecureUDIDTests;
+ productReference = 22EB0AFD1520A5D5008DB8C8 /* SecureUDIDTests.octest */;
+ productType = "com.apple.product-type.bundle";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 22EB0AE41520A5D5008DB8C8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ ORGANIZATIONNAME = Crashlytics;
+ };
+ buildConfigurationList = 22EB0AE71520A5D5008DB8C8 /* Build configuration list for PBXProject "SecureUDID" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 22EB0AE21520A5D5008DB8C8;
+ productRefGroup = 22EB0AEE1520A5D5008DB8C8 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 22EB0AFC1520A5D5008DB8C8 /* SecureUDIDTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 22EB0AFA1520A5D5008DB8C8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 22EB0B0B1520A5D5008DB8C8 /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 22EB0AFB1520A5D5008DB8C8 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 22EB0AF81520A5D5008DB8C8 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 22EB0B0E1520A5D5008DB8C8 /* SecureUDIDTests.m in Sources */,
+ 221DD6AB152161240023C82A /* SecureUDID.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 22EB0B091520A5D5008DB8C8 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 22EB0B0A1520A5D5008DB8C8 /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 22EB0B0F1520A5D5008DB8C8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 22EB0B101520A5D5008DB8C8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 22EB0B151520A5D5008DB8C8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(DEVELOPER_LIBRARY_DIR)/Frameworks",
+ );
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "SecureUDID-Prefix.pch";
+ INFOPLIST_FILE = "SecureUDIDTests/SecureUDIDTests-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 4.0;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Debug;
+ };
+ 22EB0B161520A5D5008DB8C8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(DEVELOPER_LIBRARY_DIR)/Frameworks",
+ );
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "SecureUDID-Prefix.pch";
+ INFOPLIST_FILE = "SecureUDIDTests/SecureUDIDTests-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 4.0;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 22EB0AE71520A5D5008DB8C8 /* Build configuration list for PBXProject "SecureUDID" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 22EB0B0F1520A5D5008DB8C8 /* Debug */,
+ 22EB0B101520A5D5008DB8C8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 22EB0B141520A5D5008DB8C8 /* Build configuration list for PBXNativeTarget "SecureUDIDTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 22EB0B151520A5D5008DB8C8 /* Debug */,
+ 22EB0B161520A5D5008DB8C8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 22EB0AE41520A5D5008DB8C8 /* Project object */;
+}
7 SecureUDID.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:SecureUDID.xcodeproj">
+ </FileRef>
+</Workspace>
68 SecureUDID.xcodeproj/xcshareddata/xcschemes/SecureUDID.xcscheme
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "22EB0AEC1520A5D5008DB8C8"
+ BuildableName = "libSecureUDID.a"
+ BlueprintName = "SecureUDID"
+ ReferencedContainer = "container:SecureUDID.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "22EB0AFC1520A5D5008DB8C8"
+ BuildableName = "SecureUDIDTests.octest"
+ BlueprintName = "SecureUDIDTests"
+ ReferencedContainer = "container:SecureUDID.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
22 SecureUDIDTests/SecureUDIDTests-Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.secureudid.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
59 SecureUDIDTests/SecureUDIDTests.m
@@ -0,0 +1,59 @@
+//
+// SecureUDIDTests.m
+// SecureUDID
+//
+// Created by Crashlytics Team on 3/22/12.
+// Copyright (c) 2012 Crashlytics, Inc. All rights reserved.
+// http://www.crashlytics.com
+// info@crashlytics.com
+//
+
+/*
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+#import "SecureUDID.h"
+
+@interface SecureUDIDTests : SenTestCase
+
+@end
+
+@implementation SecureUDIDTests
+
+/*
+ Tests the output from the UDIDForDomain:salt: method.
+ */
+- (void)testUDIDForDomain {
+ // Confirm we get a UDID back.
+ NSString *udid = [SecureUDID UDIDForDomain:@"com.example.myapp" salt:@"superSecretCodeHere!@##%#$#%$^"];
+ STAssertNotNil(udid, @"udid should not be nil");
+
+ // Confirm we get the same UDID back.
+ NSString *sameUDID = [SecureUDID UDIDForDomain:@"com.example.myapp" salt:@"superSecretCodeHere!@##%#$#%$^"];
+ STAssertNotNil(sameUDID, @"sameUDID should not be nil");
+ STAssertEqualObjects(udid, sameUDID, @"udid and sameUDID should be equal");
+
+ // Confirm we get a different UDID since we are using a different domain.
+ NSString *newUDID = [SecureUDID UDIDForDomain:@"com.example.myapp.udid" salt:@"superSecretCodeHere!@##%#$#%$^"];
+ STAssertNotNil(newUDID, @"newUDID should not be nil");
+ STAssertFalse([newUDID isEqualToString:udid], @"newUDID and udid should not be equal");
+}
+
+@end
2  SecureUDIDTests/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
Please sign in to comment.
Something went wrong with that request. Please try again.