5 // Created by James Murphy on 12/12/12.
6 // Copyright (c) 2012 James Murphy. All rights reserved.
9 #import "PSUtilities.h"
10 #import <Security/Security.h>
12 @implementation PSUtilities
14 + (void)outputError:(NSString *)message withError:(CFErrorRef)error
16 NSString* output = nil;
19 CFStringRef aCFStr = CFErrorCopyDescription(error);
22 output = [NSString stringWithFormat:@"%@ error: %@", message, aCFStr];
39 + (NSString *)digestAndEncode:(CFDataRef)cfData useSHA1:(BOOL)useSHA1;
41 CFErrorRef cfError = NULL;
42 NSString* result = nil;
43 CFTypeRef digestType = kSecDigestSHA2;
44 CFIndex digestLength = 256;
48 digestType = kSecDigestSHA1;
52 SecTransformRef digestXForm = SecDigestTransformCreate(digestType, digestLength, &cfError);
56 [PSUtilities outputError:@"Could not create the digesting transform." withError:cfError];
60 if (!SecTransformSetAttribute(digestXForm, kSecTransformInputAttributeName, cfData, &cfError))
63 CFRelease(digestXForm);
64 [PSUtilities outputError:@"Could not set the input attribute" withError:cfError];
68 SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &cfError);
72 CFRelease(digestXForm);
73 [PSUtilities outputError:@"Could not create the encoding transform." withError:cfError];
77 SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform();
78 if (NULL == groupXForm)
80 CFRelease(digestXForm);
81 CFRelease(base64Xform);
82 NSLog(@"Could not create the group transform");
86 SecTransformConnectTransforms(digestXForm, kSecTransformOutputAttributeName,
87 base64Xform, kSecTransformInputAttributeName,
88 groupXForm, &cfError);
89 CFRelease(digestXForm);
90 CFRelease(base64Xform);
94 [PSUtilities outputError:@"Could not connect the transforms" withError:cfError];
98 CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &cfError);
99 CFRelease(groupXForm);
102 [PSUtilities outputError:@"Could not execute the transform." withError:cfError];
105 const void* pPtr = (const void*)CFDataGetBytePtr(cfResult);
106 NSUInteger len = (NSUInteger)CFDataGetLength(cfResult);
108 NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len];
109 result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding];
115 + (CFDataRef)readFile:(NSString *)file_path
117 CFDataRef result = NULL;
121 NSError* error = nil;
123 if (nil == file_path)
125 NSLog(@"PSUtilities.readFile called with a nil file path");
130 NSFileManager* fileManager = [NSFileManager defaultManager];
132 if (![fileManager fileExistsAtPath:file_path isDirectory:&isDir])
134 NSLog(@"PSUtilities.readFile %@ does not exist", file_path);
140 NSLog(@"PSUtilities.readFile %@ does exist but it is a directory", file_path);
145 NSData* temp_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error];
148 NSLog(@"NSData dataWithContentsOfFile returned error %@", file_path);
152 result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)[temp_data bytes], (CFIndex)[temp_data length]);
159 + (SecCertificateRef)getCertificateFromData:(CFDataRef)data
161 SecCertificateRef result = NULL;
162 SecExternalFormat inputFormat = kSecFormatUnknown;
163 SecExternalItemType itemType = kSecItemTypeUnknown;
164 SecItemImportExportFlags flags = 0;
165 CFArrayRef outItems = NULL;
167 OSStatus err = SecKeychainItemImport(data, NULL, &inputFormat, &itemType, flags,
168 NULL, NULL, &outItems);
169 if (errSecSuccess != err)
171 NSLog(@"Could not import data");
174 if (NULL != outItems)
176 CFIndex num_items = CFArrayGetCount(outItems);
179 CFTypeRef anItem = (CFTypeRef)CFArrayGetValueAtIndex(outItems, 0);
180 if (NULL != anItem && (CFGetTypeID(anItem) == SecCertificateGetTypeID()))
182 result = (SecCertificateRef)anItem;
195 + (CFDataRef)getKeyDataFromCertificate:(SecCertificateRef)cert
197 CFDataRef result = NULL;
204 SecKeyRef aPublicKey = NULL;
205 OSStatus err = SecCertificateCopyPublicKey(cert, &aPublicKey);
206 if (errSecSuccess == err && NULL != aPublicKey)
208 err = SecItemExport(aPublicKey, kSecFormatBSAFE, 0, NULL, &result);
209 if (errSecSuccess != err)
213 CFRelease(aPublicKey);
218 + (SecKeyRef)getPrivateKeyWithName:(NSString *)keyName
220 SecKeyRef result = NULL;
221 NSArray* key_array = [NSArray arrayWithObjects:kSecClass, kSecAttrLabel, kSecReturnRef, nil];
222 NSArray* obj_array = [NSArray arrayWithObjects:kSecClassKey, keyName, kCFBooleanTrue, nil];
223 NSDictionary* query = [NSDictionary dictionaryWithObjects:obj_array forKeys:key_array];
225 OSStatus err = SecItemCopyMatching(CFBridgingRetain(query), (CFTypeRef *)&result);
226 if (errSecSuccess != err)
228 NSLog(@"Unable to find the Private Key");
233 + (NSString *)signAndEncode:(CFDataRef)data usingKey:(SecKeyRef)key useSHA1:(BOOL)useSHA1
235 NSString* result = nil;
236 if (NULL == data || NULL == key)
241 CFTypeRef digestType = kSecDigestHMACSHA2;
242 CFIndex digestLength = 256;
246 digestType = kSecDigestSHA1;
250 CFErrorRef error = NULL;
251 SecTransformRef signXForm = SecSignTransformCreate(key, &error);
254 [PSUtilities outputError:@"Unable to create the signing transform" withError:error];
258 if (!SecTransformSetAttribute(signXForm, kSecTransformInputAttributeName, data, &error))
260 CFRelease(signXForm);
261 [PSUtilities outputError:@"Could not set the input attribute" withError:error];
265 if (!SecTransformSetAttribute(signXForm, kSecDigestTypeAttribute, digestType, &error))
267 CFRelease(signXForm);
268 [PSUtilities outputError:@"Unable to set the digest type attribute" withError:error];
272 CFNumberRef digest_length_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &digestLength);
273 if (!SecTransformSetAttribute(signXForm, kSecDigestLengthAttribute, digest_length_number, &error))
275 CFRelease(signXForm);
276 CFRelease(digest_length_number);
277 [PSUtilities outputError:@"Unable to set the digest length attribute" withError:error];
280 CFRelease(digest_length_number);
282 if (!SecTransformSetAttribute(signXForm, kSecInputIsAttributeName, kSecInputIsPlainText, &error))
284 CFRelease(signXForm);
285 [PSUtilities outputError:@"Unable to set the is plain text attribute" withError:error];
289 SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &error);
292 CFRelease(signXForm);
293 [PSUtilities outputError:@"Could not create the encoding transform." withError:error];
297 SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform();
298 if (NULL == groupXForm)
300 CFRelease(signXForm);
301 CFRelease(base64Xform);
302 NSLog(@"Could not create the group transform");
306 SecTransformConnectTransforms(signXForm, kSecTransformOutputAttributeName,
307 base64Xform, kSecTransformInputAttributeName,
309 CFRelease(signXForm);
310 CFRelease(base64Xform);
313 [PSUtilities outputError:@"Could connect the signing and encoding transforms." withError:error];
317 CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &error);
318 CFRelease(groupXForm);
321 [PSUtilities outputError:@"Could not execute the transform." withError:error];
324 const void* pPtr = (const void*)CFDataGetBytePtr(cfResult);
325 NSUInteger len = (NSUInteger)CFDataGetLength(cfResult);
327 NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len];
328 result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding];