Skip to content

Instantly share code, notes, and snippets.

@mattt
Created May 22, 2014 03:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mattt/fa22a128a10dc80c1e86 to your computer and use it in GitHub Desktop.
Save mattt/fa22a128a10dc80c1e86 to your computer and use it in GitHub Desktop.
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