🎯 Recommended Samples
Balanced sample collections from various categories for you to explore
macOS Cryptography Objective-C Samples
macOS Objective-C cryptography examples including hash calculation, symmetric encryption, and Base64 encoding
💻 Base64 Encoding objectivec
🟢 simple
⭐⭐
Encode and decode data to/from Base64 format using Foundation APIs
⏱️ 20 min
🏷️ objectivec, macos, cryptography, encoding
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Base64 Encoding Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic Base64 Encoding/Decoding
@interface Base64Coder : NSObject
+ (NSString *)encodeDataToBase64:(NSData *)data;
+ (NSData *)decodeBase64ToString:(NSString *)base64String;
+ (NSString *)encodeStringToBase64:(NSString *)string;
+ (NSString *)decodeBase64ToString:(NSString *)base64String;
@end
@implementation Base64Coder
+ (NSString *)encodeDataToBase64:(NSData *)data {
NSString *base64String = [data base64EncodedStringWithOptions:0];
NSLog(@"Encoded %lu bytes to Base64", (unsigned long)data.length);
return base64String;
}
+ (NSData *)decodeBase64ToData:(NSString *)base64String {
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
if (data) {
NSLog(@"Decoded Base64 to %lu bytes", (unsigned long)data.length);
} else {
NSLog(@"Failed to decode Base64 string");
}
return data;
}
+ (NSString *)encodeStringToBase64:(NSString *)string {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64 = [self encodeDataToBase64:data];
NSLog(@"'%@' -> %@", string, base64);
return base64;
}
+ (NSString *)decodeBase64ToString:(NSString *)base64String {
NSData *data = [self decodeBase64ToData:base64String];
if (!data) {
return nil;
}
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@ -> '%@'", base64String, string);
return string;
}
@end
// MARK: - 2. URL-Safe Base64
@interface URLSafeBase64Coder : NSObject
+ (NSString *)encodeToURLSafeBase64:(NSData *)data;
+ (NSData *)decodeFromURLSafeBase64:(NSString *)base64String;
@end
@implementation URLSafeBase64Coder
+ (NSString *)encodeToURLSafeBase64:(NSData *)data {
NSString *base64 = [data base64EncodedStringWithOptions:0];
// Replace '+' and '/' with '-' and '_'
NSString *urlSafe = [base64 stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
urlSafe = [urlSafe stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
// Remove trailing '=' padding
while ([urlSafe hasSuffix:@"="]) {
urlSafe = [urlSafe substringToIndex:urlSafe.length - 1];
}
NSLog(@"URL-safe Base64: %@", urlSafe);
return urlSafe;
}
+ (NSData *)decodeFromURLSafeBase64:(NSString *)base64String {
// Replace '-' and '_' with '+' and '/'
NSString *standard = [base64String stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
standard = [standard stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
// Add padding
NSInteger padding = 4 - (standard.length % 4);
if (padding < 4) {
standard = [standard stringByPaddingToLength:standard.length + padding
withString:@"="
startingAtIndex:0];
}
return [[NSData alloc] initWithBase64EncodedString:standard options:0];
}
@end
// MARK: - 3. File Base64 Encoding
@interface FileBase64Coder : NSObject
+ (BOOL)encodeFileToBase64:(NSString *)inputPath
toFile:(NSString *)outputPath
error:(NSError **)error;
+ (BOOL)decodeBase64File:(NSString *)inputPath
toFile:(NSString *)outputPath
error:(NSError **)error;
@end
@implementation FileBase64Coder
+ (BOOL)encodeFileToBase64:(NSString *)inputPath
toFile:(NSString *)outputPath
error:(NSError **)error {
// Read input file
NSData *inputData = [NSData dataWithContentsOfFile:inputPath];
if (!inputData) {
if (error) {
*error = [NSError errorWithDomain:@"Base64Error"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to read input file"}];
}
return NO;
}
// Encode to Base64
NSString *base64String = [inputData base64EncodedStringWithOptions:0];
// Write to output file
BOOL success = [base64String writeToFile:outputPath
atomically:YES
encoding:NSUTF8StringEncoding
error:error];
if (success) {
NSLog(@"File encoded to Base64: %@", outputPath);
}
return success;
}
+ (BOOL)decodeBase64File:(NSString *)inputPath
toFile:(NSString *)outputPath
error:(NSError **)error {
// Read Base64 file
NSString *base64String = [NSString stringWithContentsOfFile:inputPath
encoding:NSUTF8StringEncoding
error:error];
if (!base64String) {
return NO;
}
// Decode Base64
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
if (!decodedData) {
if (error) {
*error = [NSError errorWithDomain:@"Base64Error"
code:2
userInfo:@{NSLocalizedDescriptionKey: @"Failed to decode Base64"}];
}
return NO;
}
// Write to output file
BOOL success = [decodedData writeToFile:outputPath options:NSDataWritingAtomic error:error];
if (success) {
NSLog(@"File decoded from Base64: %@", outputPath);
}
return success;
}
@end
// MARK: - 4. Chunked Base64 Encoding
@interface ChunkedBase64Coder : NSObject
+ (NSArray<NSString *> *)encodeDataToChunkedBase64:(NSData *)data chunkSize:(NSInteger)chunkSize;
+ (NSString *)encodeDataToChunkedBase64String:(NSData *)data chunkSize:(NSInteger)chunkSize;
@end
@implementation ChunkedBase64Coder
+ (NSArray<NSString *> *)encodeDataToChunkedBase64:(NSData *)data chunkSize:(NSInteger)chunkSize {
NSString *base64 = [data base64EncodedStringWithOptions:0];
NSMutableArray *chunks = [NSMutableArray array];
NSInteger index = 0;
while (index < base64.length) {
NSInteger length = MIN(chunkSize, base64.length - index);
NSString *chunk = [base64 substringWithRange:NSMakeRange(index, length)];
[chunks addObject:chunk];
index += length;
}
NSLog(@"Split Base64 into %lu chunks", (unsigned long)chunks.count);
return [chunks copy];
}
+ (NSString *)encodeDataToChunkedBase64String:(NSData *)data chunkSize:(NSInteger)chunkSize {
NSArray *chunks = [self encodeDataToChunkedBase64:data chunkSize:chunkSize];
NSString *result = [chunks componentsJoinedByString:@"\n"];
return result;
}
@end
// MARK: - 5. Base64 with Line Wrapping
@interface LineWrappedBase64Coder : NSObject
+ (NSString *)encodeWithLineWrap:(NSData *)data lineLength:(NSInteger)lineLength;
@end
@implementation LineWrappedBase64Coder
+ (NSString *)encodeWithLineWrap:(NSData *)data lineLength:(NSInteger)lineLength {
NSString *base64 = [data base64EncodedStringWithOptions:0];
NSMutableString *wrapped = [NSMutableString string];
NSInteger index = 0;
while (index < base64.length) {
NSInteger length = MIN(lineLength, base64.length - index);
NSString *line = [base64 substringWithRange:NSMakeRange(index, length)];
[wrapped appendString:line];
[wrapped appendString:@"\n"];
index += length;
}
NSLog(@"Encoded with line wrapping (line length: %ld)", (long)lineLength);
return [wrapped copy];
}
@end
// MARK: - 6. Image to Base64
@interface ImageBase64Coder : NSObject
+ (NSString *)encodeImageToBase64:(NSString *)imagePath;
+ (BOOL)saveBase64Image:(NSString *)base64String
toFile:(NSString *)outputPath
error:(NSError **)error;
@end
@implementation ImageBase64Coder
+ (NSString *)encodeImageToBase64:(NSString *)imagePath {
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
if (!imageData) {
NSLog(@"Failed to read image file");
return nil;
}
NSString *base64 = [imageData base64EncodedStringWithOptions:0];
// Get MIME type from file extension
NSString *extension = [imagePath pathExtension];
NSString *mimeType = [self mimeTypeForExtension:extension];
NSString *dataURI = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, base64];
NSLog(@"Encoded image to Data URI (length: %lu)", (unsigned long)base64.length);
return dataURI;
}
+ (BOOL)saveBase64Image:(NSString *)base64String
toFile:(NSString *)outputPath
error:(NSError **)error {
// Extract Base64 data from Data URI if present
NSString *base64Data = base64String;
NSRange range = [base64String rangeOfString:@"base64,"];
if (range.location != NSNotFound) {
base64Data = [base64String substringFromIndex:range.location + range.length];
}
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64Data options:0];
if (!imageData) {
if (error) {
*error = [NSError errorWithDomain:@"Base64Error"
code:3
userInfo:@{NSLocalizedDescriptionKey: @"Invalid Base64 image data"}];
}
return NO;
}
BOOL success = [imageData writeToFile:outputPath options:NSDataWritingAtomic error:error];
if (success) {
NSLog(@"Saved Base64 image to: %@", outputPath);
}
return success;
}
+ (NSString *)mimeTypeForExtension:(NSString *)extension {
NSDictionary *mimeTypes = @{
@"png": @"image/png",
@"jpg": @"image/jpeg",
@"jpeg": @"image/jpeg",
@"gif": @"image/gif",
@"bmp": @"image/bmp",
@"tiff": @"image/tiff",
@"webp": @"image/webp"
};
return mimeTypes[extension.lowercaseString] ?: @"application/octet-stream";
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Base64 Encoding Examples ===\n");
// 1. Basic encoding/decoding
NSLog(@"--- 1. Basic Encoding/Decoding ---");
NSString *text = @"Hello, Base64!";
NSString *encoded = [Base64Coder encodeStringToBase64:text];
NSString *decoded = [Base64Coder decodeBase64ToString:encoded];
NSLog(@"Original: %@", text);
NSLog(@"Decoded: %@", decoded);
// 2. Data encoding
NSLog(@"\n--- 2. Data Encoding ---");
NSData *data = [@"Binary data" dataUsingEncoding:NSUTF8StringEncoding];
[Base64Coder encodeDataToBase64:data];
[Base64Coder decodeBase64ToData:encoded];
// 3. URL-safe Base64
NSLog(@"\n--- 3. URL-Safe Base64 ---");
NSData *urlData = [@"URL Safe Data!" dataUsingEncoding:NSUTF8StringEncoding];
NSString *urlSafe = [URLSafeBase64Coder encodeToURLSafeBase64:urlData];
NSData *urlDecoded = [URLSafeBase64Coder decodeFromURLSafeBase64:urlSafe];
if (urlDecoded) {
NSString *urlDecodedText = [[NSString alloc] initWithData:urlDecoded encoding:NSUTF8StringEncoding];
NSLog(@"URL-safe decoded: %@", urlDecodedText);
}
// 4. File encoding
NSLog(@"\n--- 4. File Encoding ---");
NSString *testFile = @"/tmp/base64_test.txt";
NSString *encodedFile = @"/tmp/base64_test.b64";
NSString *decodedFile = @"/tmp/base64_decoded.txt";
[@"Content for Base64 encoding" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
NSError *error = nil;
BOOL success = [FileBase64Coder encodeFileToBase64:testFile
toFile:encodedFile
error:&error];
if (success) {
success = [FileBase64Coder decodeBase64File:encodedFile
toFile:decodedFile
error:&error];
if (success) {
NSString *content = [NSString stringWithContentsOfFile:decodedFile
encoding:NSUTF8StringEncoding
error:nil];
NSLog(@"Decoded file content: %@", content);
}
}
// 5. Chunked encoding
NSLog(@"\n--- 5. Chunked Encoding ---");
NSData *largeData = [@"This is a longer piece of text that will be split into multiple chunks" dataUsingEncoding:NSUTF8StringEncoding];
NSArray *chunks = [ChunkedBase64Coder encodeDataToChunkedBase64:largeData chunkSize:20];
NSLog(@"Chunks (%lu):", (unsigned long)chunks.count);
for (NSInteger i = 0; i < chunks.count; i++) {
NSLog(@" Chunk %ld: %@", (long)(i + 1), chunks[i]);
}
// 6. Line wrapping
NSLog(@"\n--- 6. Line Wrapping ---");
NSString *wrapped = [LineWrappedBase64Coder encodeWithLineWrap:largeData lineLength:30];
NSLog(@"Wrapped:\n%@", wrapped);
// Cleanup
[[NSFileManager defaultManager] removeItemAtPath:testFile error:nil];
[[NSFileManager defaultManager] removeItemAtPath:encodedFile error:nil];
[[NSFileManager defaultManager] removeItemAtPath:decodedFile error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== Base64 Encoding Examples Completed ===");
}
return 0;
}
💻 Hash Calculation objectivec
🟡 intermediate
⭐⭐⭐
Calculate MD5 and SHA256 hashes of strings and data using CommonCrypto
⏱️ 25 min
🏷️ objectivec, macos, cryptography, hashing
Prerequisites:
Objective-C basics, Foundation framework, CommonCrypto
// macOS Objective-C Hash Calculation Examples
// Using CommonCrypto framework
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonHMAC.h>
// MARK: - 1. MD5 Hash
@interface MD5Hash : NSObject
+ (NSString *)calculateMD5FromString:(NSString *)string;
+ (NSString *)calculateMD5FromData:(NSData *)data;
+ (NSString *)calculateMD5FromFile:(NSString *)filePath;
@end
@implementation MD5Hash
+ (NSString *)calculateMD5FromString:(NSString *)string {
const char *cStr = [string UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"MD5 hash of '%@': %@", string, output);
return output;
}
+ (NSString *)calculateMD5FromData:(NSData *)data {
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"MD5 hash of data: %@", output);
return output;
}
+ (NSString *)calculateMD5FromFile:(NSString *)filePath {
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
if (!fileData) {
NSLog(@"Failed to read file for MD5 calculation");
return nil;
}
NSString *md5Hash = [self calculateMD5FromData:fileData];
NSLog(@"MD5 hash of file %@: %@", filePath, md5Hash);
return md5Hash;
}
@end
// MARK: - 2. SHA256 Hash
@interface SHA256Hash : NSObject
+ (NSString *)calculateSHA256FromString:(NSString *)string;
+ (NSString *)calculateSHA256FromData:(NSData *)data;
+ (NSString *)calculateSHA256FromFile:(NSString *)filePath;
@end
@implementation SHA256Hash
+ (NSString *)calculateSHA256FromString:(NSString *)string {
const char *cStr = [string UTF8String];
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"SHA256 hash of '%@': %@", string, output);
return output;
}
+ (NSString *)calculateSHA256FromData:(NSData *)data {
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"SHA256 hash of data: %@", output);
return output;
}
+ (NSString *)calculateSHA256FromFile:(NSString *)filePath {
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
if (!fileData) {
NSLog(@"Failed to read file for SHA256 calculation");
return nil;
}
NSString *sha256Hash = [self calculateSHA256FromData:fileData];
NSLog(@"SHA256 hash of file %@: %@", filePath, sha256Hash);
return sha256Hash;
}
@end
// MARK: - 3. SHA1 and SHA512
@interface AdvancedHash : NSObject
+ (NSString *)calculateSHA1FromString:(NSString *)string;
+ (NSString *)calculateSHA512FromString:(NSString *)string;
@end
@implementation AdvancedHash
+ (NSString *)calculateSHA1FromString:(NSString *)string {
const char *cStr = [string UTF8String];
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"SHA1 hash: %@", output);
return output;
}
+ (NSString *)calculateSHA512FromString:(NSString *)string {
const char *cStr = [string UTF8String];
unsigned char digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"SHA512 hash: %@", output);
return output;
}
@end
// MARK: - 4. HMAC (Hash-based Message Authentication Code)
@interface HMACHash : NSObject
+ (NSString *)calculateHMACSHA256:(NSString *)data withKey:(NSString *)key;
@end
@implementation HMACHash
+ (NSString *)calculateHMACSHA256:(NSString *)data withKey:(NSString *)key {
const char *cData = [data UTF8String];
const char *cKey = [key UTF8String];
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
NSLog(@"HMAC-SHA256: %@", output);
return output;
}
@end
// MARK: - 5. Hash Comparison
@interface HashComparator : NSObject
+ (BOOL)compareString:(NSString *)string1 withString:(NSString *)string2 usingSHA256:(BOOL)useSHA256;
+ (BOOL)verifyFileIntegrity:(NSString *)filePath withExpectedHash:(NSString *)expectedHash;
@end
@implementation HashComparator
+ (BOOL)compareString:(NSString *)string1 withString:(NSString *)string2 usingSHA256:(BOOL)useSHA256 {
NSString *hash1, *hash2;
if (useSHA256) {
hash1 = [SHA256Hash calculateSHA256FromString:string1];
hash2 = [SHA256Hash calculateSHA256FromString:string2];
} else {
hash1 = [MD5Hash calculateMD5FromString:string1];
hash2 = [MD5Hash calculateMD5FromString:string2];
}
BOOL equal = [hash1 isEqualToString:hash2];
NSLog(@"Hashes equal: %@", equal ? @"YES" : @"NO");
return equal;
}
+ (BOOL)verifyFileIntegrity:(NSString *)filePath withExpectedHash:(NSString *)expectedHash {
NSString *actualHash = [SHA256Hash calculateSHA256FromFile:filePath];
if (!actualHash) {
return NO;
}
BOOL valid = [actualHash caseInsensitiveCompare:expectedHash] == NSOrderedSame;
NSLog(@"File integrity: %@", valid ? @"VALID" : @"INVALID");
return valid;
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Hash Calculation Examples ===\n");
// 1. MD5 hash
NSLog(@"--- 1. MD5 Hash ---");
NSString *md5 = [MD5Hash calculateMD5FromString:@"Hello, World!"];
NSLog(@"MD5: %@", md5);
NSString *testData = @"Test data for MD5";
NSData *data = [testData dataUsingEncoding:NSUTF8StringEncoding];
[MD5Hash calculateMD5FromData:data];
// 2. SHA256 hash
NSLog(@"\n--- 2. SHA256 Hash ---");
NSString *sha256 = [SHA256Hash calculateSHA256FromString:@"Hello, World!"];
NSLog(@"SHA256: %@", sha256);
// 3. File hash
NSLog(@"\n--- 3. File Hash ---");
NSString *testFile = @"/tmp/hash_test.txt";
[@"Content for hash calculation" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[SHA256Hash calculateSHA256FromFile:testFile];
// 4. SHA1 and SHA512
NSLog(@"\n--- 4. SHA1 and SHA512 ---");
[AdvancedHash calculateSHA1FromString:@"Hello, World!"];
[AdvancedHash calculateSHA512FromString:@"Hello, World!"];
// 5. HMAC
NSLog(@"\n--- 5. HMAC ---");
[HMACHash calculateHMACSHA256:@"message data" withKey:@"secret key"];
// 6. Hash comparison
NSLog(@"\n--- 6. Hash Comparison ---");
BOOL equal = [HashComparator compareString:@"password1"
withString:@"password1"
usingSHA256:YES];
NSLog(@"Same strings have same hash: %@", equal ? @"YES" : @"NO");
BOOL different = [HashComparator compareString:@"password1"
withString:@"password2"
usingSHA256:YES];
NSLog(@"Different strings have same hash: %@", different ? @"YES" : @"NO");
// 7. File integrity verification
NSLog(@"\n--- 7. File Integrity Verification ---");
NSString *expectedHash = [SHA256Hash calculateSHA256FromFile:testFile];
BOOL valid = [HashComparator verifyFileIntegrity:testFile
withExpectedHash:expectedHash];
NSLog(@"Integrity check: %@", valid ? @"PASSED" : @"FAILED");
// Cleanup
[[NSFileManager defaultManager] removeItemAtPath:testFile error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== Hash Calculation Examples Completed ===");
}
return 0;
}
💻 Symmetric Encryption objectivec
🔴 complex
⭐⭐⭐⭐
AES encryption and decryption using CommonCrypto with CBC mode and PKCS7 padding
⏱️ 35 min
🏷️ objectivec, macos, cryptography, encryption
Prerequisites:
Intermediate Objective-C, Foundation framework, CommonCrypto
// macOS Objective-C Symmetric Encryption Examples
// Using CommonCrypto for AES encryption
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>
// MARK: - 1. AES Encryption/Decryption
@interface AESCipher : NSObject
+ (NSData *)encryptData:(NSData *)data
withKey:(NSData *)key
iv:(NSData *)iv
error:(NSError **)error;
+ (NSData *)decryptData:(NSData *)data
withKey:(NSData *)key
iv:(NSData *)iv
error:(NSError **)error;
+ (NSData *)encryptString:(NSString *)string
withPassword:(NSString *)password
error:(NSError **)error;
+ (NSString *)decryptData:(NSData *)data
withPassword:(NSString *)password
error:(NSError **)error;
@end
@implementation AESCipher
+ (NSData *)encryptData:(NSData *)data
withKey:(NSData *)key
iv:(NSData *)iv
error:(NSError **)error {
if (key.length != kCCKeySizeAES256 && key.length != kCCKeySizeAES128 && key.length != kCCKeySizeAES192) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Invalid key size"}];
}
return nil;
}
if (iv.length != kCCBlockSizeAES128) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:2
userInfo:@{NSLocalizedDescriptionKey: @"Invalid IV size"}];
}
return nil;
}
NSMutableData *encryptedData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
size_t encryptedLength = 0;
CCCryptorStatus status = CCCrypt(kCCEncrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
key.bytes,
key.length,
iv.bytes,
data.bytes,
data.length,
encryptedData.mutableBytes,
encryptedData.length,
&encryptedLength);
if (status != kCCSuccess) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:status
userInfo:@{NSLocalizedDescriptionKey: @"Encryption failed"}];
}
return nil;
}
encryptedData.length = encryptedLength;
NSLog(@"Data encrypted successfully (%lu bytes)", (unsigned long)encryptedLength);
return [encryptedData copy];
}
+ (NSData *)decryptData:(NSData *)data
withKey:(NSData *)key
iv:(NSData *)iv
error:(NSError **)error {
if (key.length != kCCKeySizeAES256 && key.length != kCCKeySizeAES128 && key.length != kCCKeySizeAES192) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Invalid key size"}];
}
return nil;
}
if (iv.length != kCCBlockSizeAES128) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:2
userInfo:@{NSLocalizedDescriptionKey: @"Invalid IV size"}];
}
return nil;
}
NSMutableData *decryptedData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
size_t decryptedLength = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
key.bytes,
key.length,
iv.bytes,
data.bytes,
data.length,
decryptedData.mutableBytes,
decryptedData.length,
&decryptedLength);
if (status != kCCSuccess) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:status
userInfo:@{NSLocalizedDescriptionKey: @"Decryption failed"}];
}
return nil;
}
decryptedData.length = decryptedLength;
NSLog(@"Data decrypted successfully (%lu bytes)", (unsigned long)decryptedLength);
return [decryptedData copy];
}
+ (NSData *)encryptString:(NSString *)string
withPassword:(NSString *)password
error:(NSError **)error {
// Derive key from password using PBKDF2
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
// Generate salt (in production, use a random salt)
uint8_t salt[kCCKeySizeAES256];
for (NSInteger i = 0; i < kCCKeySizeAES256; i++) {
salt[i] = (uint8_t)i;
}
// Derive key
uint8_t key[kCCKeySizeAES256];
int result = CCKeyDerivationPBKDF(kCCPBKDF2,
passwordData.bytes,
passwordData.length,
salt,
kCCKeySizeAES256,
kPRFHmacAlgSHA256,
10000, // iterations
key,
kCCKeySizeAES256);
if (result != kCCSuccess) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:result
userInfo:@{NSLocalizedDescriptionKey: @"Key derivation failed"}];
}
return nil;
}
NSData *keyData = [NSData dataWithBytes:key length:kCCKeySizeAES256];
// Generate IV
uint8_t iv[kCCBlockSizeAES128];
for (NSInteger i = 0; i < kCCBlockSizeAES128; i++) {
iv[i] = (uint8_t)(i * 2);
}
NSData *ivData = [NSData dataWithBytes:iv length:kCCBlockSizeAES128];
// Encrypt
NSData *plaintext = [string dataUsingEncoding:NSUTF8StringEncoding];
return [self encryptData:plaintext withKey:keyData iv:ivData error:error];
}
+ (NSString *)decryptData:(NSData *)data
withPassword:(NSString *)password
error:(NSError **)error {
// Derive key from password (same salt as encryption)
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
uint8_t salt[kCCKeySizeAES256];
for (NSInteger i = 0; i < kCCKeySizeAES256; i++) {
salt[i] = (uint8_t)i;
}
uint8_t key[kCCKeySizeAES256];
CCKeyDerivationPBKDF(kCCPBKDF2,
passwordData.bytes,
passwordData.length,
salt,
kCCKeySizeAES256,
kPRFHmacAlgSHA256,
10000,
key,
kCCKeySizeAES256);
NSData *keyData = [NSData dataWithBytes:key length:kCCKeySizeAES256];
// Generate IV (same as encryption)
uint8_t iv[kCCBlockSizeAES128];
for (NSInteger i = 0; i < kCCBlockSizeAES128; i++) {
iv[i] = (uint8_t)(i * 2);
}
NSData *ivData = [NSData dataWithBytes:iv length:kCCBlockSizeAES128];
// Decrypt
NSData *decryptedData = [self decryptData:data withKey:keyData iv:ivData error:error];
if (!decryptedData) {
return nil;
}
return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
}
@end
// MARK: - 2. Secure Key Generation
@interface SecureKeyGenerator : NSObject
+ (NSData *)generateRandomKeyOfSize:(size_t)size;
+ (NSData *)generateRandomIV;
+ (NSData *)deriveKeyFromPassword:(NSString *)password
salt:(NSData *)salt
keySize:(size_t)keySize;
@end
@implementation SecureKeyGenerator
+ (NSData *)generateRandomKeyOfSize:(size_t)size {
NSMutableData *key = [NSMutableData dataWithLength:size];
int result = SecRandomCopyBytes(kSecRandomDefault, size, key.mutableBytes);
if (result != errSecSuccess) {
NSLog(@"Failed to generate random key");
return nil;
}
NSLog(@"Generated random key (%zu bytes)", size);
return [key copy];
}
+ (NSData *)generateRandomIV {
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
int result = SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, iv.mutableBytes);
if (result != errSecSuccess) {
NSLog(@"Failed to generate random IV");
return nil;
}
NSLog(@"Generated random IV (%zu bytes)", kCCBlockSizeAES128);
return [iv copy];
}
+ (NSData *)deriveKeyFromPassword:(NSString *)password
salt:(NSData *)salt
keySize:(size_t)keySize {
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *key = [NSMutableData dataWithLength:keySize];
int result = CCKeyDerivationPBKDF(kCCPBKDF2,
passwordData.bytes,
passwordData.length,
salt.bytes,
salt.length,
kPRFHmacAlgSHA256,
10000,
key.mutableBytes,
keySize);
if (result != kCCSuccess) {
NSLog(@"Failed to derive key from password");
return nil;
}
NSLog(@"Derived key from password (%zu bytes)", keySize);
return [key copy];
}
@end
// MARK: - 3. File Encryption
@interface FileCipher : NSObject
+ (BOOL)encryptFile:(NSString *)inputPath
toFile:(NSString *)outputPath
withKey:(NSData *)key
error:(NSError **)error;
+ (BOOL)decryptFile:(NSString *)inputPath
toFile:(NSString *)outputPath
withKey:(NSData *)key
error:(NSError **)error;
@end
@implementation FileCipher
+ (BOOL)encryptFile:(NSString *)inputPath
toFile:(NSString *)outputPath
withKey:(NSData *)key
error:(NSError **)error {
// Read input file
NSData *inputData = [NSData dataWithContentsOfFile:inputPath];
if (!inputData) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to read input file"}];
}
return NO;
}
// Generate random IV
NSData *iv = [SecureKeyGenerator generateRandomIV];
// Encrypt data
NSData *encryptedData = [AESCipher encryptData:inputData withKey:key iv:iv error:error];
if (!encryptedData) {
return NO;
}
// Write IV + encrypted data to output
NSMutableData *outputData = [NSMutableData dataWithData:iv];
[outputData appendData:encryptedData];
BOOL success = [outputData writeToFile:outputPath options:NSDataWritingAtomic error:error];
if (success) {
NSLog(@"File encrypted successfully: %@", outputPath);
}
return success;
}
+ (BOOL)decryptFile:(NSString *)inputPath
toFile:(NSString *)outputPath
withKey:(NSData *)key
error:(NSError **)error {
// Read input file
NSData *inputData = [NSData dataWithContentsOfFile:inputPath];
if (!inputData || inputData.length < kCCBlockSizeAES128) {
if (error) {
*error = [NSError errorWithDomain:@"CryptoError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Invalid encrypted file"}];
}
return NO;
}
// Extract IV from first block
NSData *iv = [inputData subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
NSData *encryptedData = [inputData subdataWithRange:NSMakeRange(kCCBlockSizeAES128, inputData.length - kCCBlockSizeAES128)];
// Decrypt data
NSData *decryptedData = [AESCipher decryptData:encryptedData withKey:key iv:iv error:error];
if (!decryptedData) {
return NO;
}
// Write to output
BOOL success = [decryptedData writeToFile:outputPath options:NSDataWritingAtomic error:error];
if (success) {
NSLog(@"File decrypted successfully: %@", outputPath);
}
return success;
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Symmetric Encryption Examples ===\n");
// 1. AES encryption/decryption with key and IV
NSLog(@"--- 1. AES Encryption/Decryption ---");
// Generate random key and IV
NSData *key = [SecureKeyGenerator generateRandomKeyOfSize:kCCKeySizeAES256];
NSData *iv = [SecureKeyGenerator generateRandomIV];
NSString *plaintext = @"Secret message to encrypt!";
NSData *plainData = [plaintext dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSData *encrypted = [AESCipher encryptData:plainData withKey:key iv:iv error:&error];
if (encrypted) {
NSLog(@"Encrypted data length: %lu bytes", (unsigned long)encrypted.length);
}
NSData *decrypted = [AESCipher decryptData:encrypted withKey:key iv:iv error:&error];
if (decrypted) {
NSString *decryptedText = [[NSString alloc] initWithData:decrypted encoding:NSUTF8StringEncoding];
NSLog(@"Decrypted: %@", decryptedText);
}
// 2. Password-based encryption
NSLog(@"\n--- 2. Password-Based Encryption ---");
NSString *password = @"mySecretPassword123!";
NSString *message = @"Confidential data";
NSData *pwdEncrypted = [AESCipher encryptString:message withPassword:password error:&error];
NSString *pwdDecrypted = [AESCipher decryptData:pwdEncrypted withPassword:password error:&error];
if (pwdDecrypted) {
NSLog(@"Password-based decrypted: %@", pwdDecrypted);
}
// 3. Key derivation
NSLog(@"\n--- 3. Key Derivation ---");
NSData *salt = [SecureKeyGenerator generateRandomKeyOfSize:16];
NSData *derivedKey = [SecureKeyGenerator deriveKeyFromPassword:@"userPassword"
salt:salt
keySize:kCCKeySizeAES256];
if (derivedKey) {
NSLog(@"Derived key length: %lu bytes", (unsigned long)derivedKey.length);
}
// 4. File encryption
NSLog(@"\n--- 4. File Encryption ---");
NSString *testFile = @"/tmp/test_encrypt.txt";
NSString *encryptedFile = @"/tmp/test_encrypt.enc";
NSString *decryptedFile = @"/tmp/test_decrypt.txt";
[@"This is a secret file content!" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
BOOL success = [FileCipher encryptFile:testFile
toFile:encryptedFile
withKey:key
error:&error];
if (success) {
NSLog(@"File encrypted: %@", encryptedFile);
success = [FileCipher decryptFile:encryptedFile
toFile:decryptedFile
withKey:key
error:&error];
if (success) {
NSString *content = [NSString stringWithContentsOfFile:decryptedFile
encoding:NSUTF8StringEncoding
error:nil];
NSLog(@"Decrypted file content: %@", content);
}
}
// Cleanup
[[NSFileManager defaultManager] removeItemAtPath:testFile error:nil];
[[NSFileManager defaultManager] removeItemAtPath:encryptedFile error:nil];
[[NSFileManager defaultManager] removeItemAtPath:decryptedFile error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== Symmetric Encryption Examples Completed ===");
}
return 0;
}