Created
May 22, 2014 03:17
-
-
Save mattt/fa22a128a10dc80c1e86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static NSString * const CCErrorDomain = @"com.apple.commoncrypto.error"; | |
static NSString * CCDescriptionForStatus(CCCryptorStatus status) { | |
static NSString * const _CCStatusDescriptions[] = { | |
[-kCCSuccess] = @"Operation completed normally.", | |
[-kCCParamError] = @"Illegal parameter value.", | |
[-kCCBufferTooSmall] = @"Insufficent buffer provided for specified operation.", | |
[-kCCMemoryFailure] = @"Memory allocation failure.", | |
[-kCCAlignmentError] = @"Input size was not aligned properly.", | |
[-kCCDecodeError] = @"Input data did not decode or decrypt properly.", | |
[-kCCUnimplemented] = @"Function not implemented for the current algorithm.", | |
}; | |
return _CCStatusDescriptions[-status]; | |
} | |
static NSData * AES128PBKDFKeyWithPassword(NSString *password, NSData *salt, NSError * __autoreleasing *error) { | |
NSCParameterAssert(password); | |
NSCParameterAssert(salt); | |
NSMutableData *mutableDerivedKey = [NSMutableData dataWithLength:kCCKeySizeAES128]; | |
CCCryptorStatus status = CCKeyDerivationPBKDF(kCCPBKDF2, [password UTF8String], [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding], [salt bytes], [salt length], kCCPRFHmacAlgSHA1, 1024, [mutableDerivedKey mutableBytes], kCCKeySizeAES128); | |
NSData *derivedKey = nil; | |
if (status != kCCSuccess) { | |
if (error) { | |
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: CCDescriptionForStatus(status)}; | |
*error = [[NSError alloc] initWithDomain:CCErrorDomain code:status userInfo:userInfo]; | |
} | |
} else { | |
derivedKey = [NSData dataWithData:mutableDerivedKey]; | |
} | |
return derivedKey; | |
} | |
__attribute__((overloadable)) static NSData * AES128EncryptedDataWithData(NSData *data, NSData *key, NSData * __autoreleasing *initializationVector, NSError * __autoreleasing *error) { | |
NSCParameterAssert([key length] == kCCKeySizeAES128); | |
NSCParameterAssert(initializationVector); | |
uint8_t *initializationVectorBuffer = malloc(kCCBlockSizeAES128); | |
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, initializationVectorBuffer); | |
*initializationVector = [NSData dataWithBytes:initializationVector length:kCCBlockSizeAES128]; | |
size_t size = [data length] + kCCBlockSizeAES128; | |
void *buffer = malloc(size); | |
size_t numberOfBytesEncrypted = 0; | |
CCCryptorStatus status = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [key bytes], [key length], [*initializationVector bytes], [data bytes], [data length], buffer, size, &numberOfBytesEncrypted); | |
NSData *encryptedData = nil; | |
if (status != kCCSuccess) { | |
if (error) { | |
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: CCDescriptionForStatus(status)}; | |
*error = [[NSError alloc] initWithDomain:CCErrorDomain code:status userInfo:userInfo]; | |
} | |
} else { | |
encryptedData = [[NSData alloc] initWithBytes:buffer length:numberOfBytesEncrypted]; | |
} | |
return encryptedData; | |
} | |
__attribute__((overloadable)) static NSData * AES128EncryptedDataWithData(NSData *data, NSString *password, NSData * __autoreleasing *salt, NSData * __autoreleasing *initializationVector, NSError * __autoreleasing *error) { | |
NSCParameterAssert(salt); | |
uint8_t *saltBuffer = malloc(8); | |
SecRandomCopyBytes(kSecRandomDefault, 8, saltBuffer); | |
*salt = [NSData dataWithBytes:saltBuffer length:8]; | |
NSData *key = AES128PBKDFKeyWithPassword(password, *salt, error); | |
return AES128EncryptedDataWithData(data, key, initializationVector, error); | |
} | |
__attribute__((overloadable)) static NSData * AES128DecryptedDataWithData(NSData *data, NSData *key, NSData *initializationVector, NSError * __autoreleasing *error) { | |
size_t size = [data length] + kCCBlockSizeAES128; | |
void *buffer = malloc(size); | |
size_t numberOfBytesDecrypted = 0; | |
CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [key bytes], [key length], [initializationVector bytes], [data bytes], [data length], buffer, size, &numberOfBytesDecrypted); | |
NSData *encryptedData = nil; | |
if (status != kCCSuccess) { | |
if (error) { | |
*error = [[NSError alloc] initWithDomain:nil code:status userInfo:nil]; | |
} | |
} else { | |
encryptedData = [[NSData alloc] initWithBytes:buffer length:numberOfBytesDecrypted]; | |
} | |
return encryptedData; | |
} | |
__attribute__((overloadable)) static NSData * AES128DecryptedDataWithData(NSData *data, NSString *password, NSData *salt, NSData *initializationVector, NSError * __autoreleasing *error) { | |
NSData *key = AES128PBKDFKeyWithPassword(password, salt, error); | |
return AES128DecryptedDataWithData(data, key, initializationVector, error); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment