Cryptographie macOS Objective-C - Exemples

Exemples cryptographie macOS Objective-C incluant calcul de hash, chiffrement symétrique et codage Base64

💻 Codage Base64 objectivec

🟢 simple ⭐⭐

Encoder et décoder données vers/depuis format Base64 via APIs Foundation

⏱️ 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;
}

💻 Calcul de Hash objectivec

🟡 intermediate ⭐⭐⭐

Calculer les haches MD5 et SHA256 des chaînes et données via 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;
}

💻 Chiffrement Symétrique objectivec

🔴 complex ⭐⭐⭐⭐

Chiffrement et déchiffrement AES via CommonCrypto mode CBC padding PKCS7

⏱️ 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;
}