iOS 对称加密 DES,3DES,AES128,AES256

前言

最近开发的功能需要用对网络传输的数据进行加密,因此调研了常用了对称加密DES3DESAES128AES256。做了如下的整理。

加解密的黑盒过程

现在我们就是需要把plainString变成cipherString

iOS 对称加密 DES,3DES,AES128,AES256_第1张图片
加解密

DES/3DES加解密过程

iOS 对称加密 DES,3DES,AES128,AES256_第2张图片
DES/3DES加解密过程
  1. DES加密过程有一步是把加密后的data数据先转场Base64data数据,然后进行UTF8转化
  2. cipherString直接通过Base64转成cipherData

AES128/AES256加解密过程

iOS 对称加密 DES,3DES,AES128,AES256_第3张图片
AES128/AES256加解密过程
  1. AES的加密和解密过程是对称的
  2. 在转化成字符串的时候,需要选择Base64还是Hex转化

DES/3DES 实现代码

KSAdEncryptionDES

- (NSString *)encrypt:(NSString *)plainString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString {
    [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"des encrypt"];
    if (plainString == nil) {
        return nil;
    }
    NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
    size_t bufferPtrSize = (plainData.length + kCCBlockSizeDES);
    unsigned char *buffer = (unsigned char *)malloc(bufferPtrSize);
    memset(buffer, 0, bufferPtrSize);
    size_t numBytesEncrypted = 0;
    const void *initializationVector = [self initializationVectorWithString:initializationVectorString];
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, [key UTF8String], kCCKeySizeDES, initializationVector, plainData.bytes, plainData.length, buffer, bufferPtrSize, &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *cipherData = [NSData dataWithBytesNoCopy:buffer length:(NSUInteger)numBytesEncrypted];
        NSData *base64Data = [cipherData base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
        NSString *cipherString = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
        return cipherString;
    }
    free(buffer);
    return nil;
}
- (NSString *)decrypt:(NSString *)cipherString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString {
    [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"des decrypt"];
    if (cipherString == nil) {
        return nil;
    }
    NSData *cipherData = [[NSData alloc] initWithBase64EncodedString:cipherString options:NSDataBase64DecodingIgnoreUnknownCharacters];
    size_t bufferPtrSize = (cipherData.length + kCCBlockSizeDES);
    unsigned char *buffer = (unsigned char *)malloc(bufferPtrSize);
    memset(buffer, 0, bufferPtrSize);
    size_t numBytesDecrypted = 0;
    const void *initializationVector = [self initializationVectorWithString:initializationVectorString];
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, [key UTF8String], kCCKeySizeDES, initializationVector, cipherData.bytes, cipherData.length, buffer, bufferPtrSize, &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *plainData = [NSData dataWithBytesNoCopy:buffer length:(NSUInteger)numBytesDecrypted];
        NSString *plainText = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
        return plainText;
    }
    free(buffer);
    return nil;
}

加密过程:

  1. plainString 通过UTF8变成plainData
  2. plainData 通过DES转化为cipherData
  3. cipherData 通过Base64转化为base64Data
  4. base64Data通过UTF8转化为可读的cipherString

解密过程

  1. cipherString 通过Base64变成cipherData
  2. cipherData 通过DES转化为plainData
  3. plainData 通过UTF8转化为plainString

注意:

  1. import

  2. 如果是3DES,那么把
    kCCBlockSizeDES->kCCBlockSize3DES
    kCCAlgorithmDES->kCCAlgorithm3DES
    kCCKeySize3DES->kCCKeySize3DES
  3. initializationVectorWithString:
- (const void *)initializationVectorWithString:(NSString *)string {
   if (string.length == 0) {
       return NULL;
   }
   NSData *initializationVectorData = [string dataUsingEncoding:NSUTF8StringEncoding];
   const void *initializationVector = initializationVectorData.bytes;
   return initializationVector;
}

NSData与NSString转化

在先介绍AES128/AES256实现代码之前,先介绍两种不常用的NSDataNSString转化
直接上类和代码:

typedef NS_ENUM(NSInteger, KSAdEncryptionDataStringEncoding) {
    KSAdEncryptionDataStringEncoding_Hex,
    KSAdEncryptionDataStringEncoding_Base64,
};

@interface KSAdEncryptionEncoding : NSObject


+ (instancetype)encryptionEncodingWithEncoding:(KSAdEncryptionDataStringEncoding)encoding;

- (NSString *)stringFromData:(NSData *)data;
- (NSData *)dataFromString:(NSString *)string;

@end

@implementation KSAdEncryptionEncoding

+ (instancetype)encryptionEncodingWithEncoding:(KSAdEncryptionDataStringEncoding)encoding {
    switch (encoding) {
        case KSAdEncryptionDataStringEncoding_Base64:
            return [KSAdEncryptionEncodingBase64 new];
        default:
            return [KSAdEncryptionEncodingHex new];
    }
}


- (NSString *)stringFromData:(NSData *)data {
    return nil;
}
- (NSData *)dataFromString:(NSString *)string {
    return nil;
}
@end

@implementation KSAdEncryptionEncodingBase64
- (NSString *)stringFromData:(NSData *)data {
    NSString *string = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    return string;
}
- (NSData *)dataFromString:(NSString *)string {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return data;
}
@end
@implementation KSAdEncryptionEncodingHex
- (NSString *)stringFromData:(NSData *)data {
    Byte *bytes = (Byte *)[data bytes];
    NSString *string = @"";
    for (NSInteger i = 0; i

具体可以参考:iOS NSString与char *互相转换

AES128/AES256 实现代码

KSAdEncryptionAES128

- (NSString *)encrypt:(NSString *)plainString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString {
    [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"aes128 encrypt"];
    if (plainString == nil) {
        return nil;
    }
    NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
    size_t bufferSize = plainData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    const void *initializationVector = [self initializationVectorWithString:initializationVectorString];
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, [key UTF8String], kCCKeySizeAES128, initializationVector, plainData.bytes, plainData.length, buffer, bufferSize, &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *cipherData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        NSString *cipherText = [self.encryptionEncoding stringFromData:cipherData];
        return cipherText;
    }
    free(buffer);
    return nil;
}
- (NSString *)decrypt:(NSString *)cipherString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString {
    [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"aes128 decrypt"];
    if (cipherString == nil) {
        return nil;
    }
    NSData *cipherData = [self.encryptionEncoding dataFromString:cipherString];
    size_t bufferSize = cipherData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    const void *initializationVector = [self initializationVectorWithString:initializationVectorString];
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, [key UTF8String], kCCKeySizeAES128, initializationVector, cipherData.bytes, cipherData.length, buffer, bufferSize, &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *plainData = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        NSString *plainText = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
        return plainText;
    }
    free(buffer);
    return nil;
}

加密过程:

  1. plainString 通过UTF8变成plainData
  2. plainData 通过AES转化为cipherData
  3. cipherData 通过Base64/Hex转化为cipherString

解密过程

  1. cipherString 通过Base64/Hex变成cipherData
  2. cipherData 通过AES转化为plainData
  3. plainData 通过UTF8转化为plainString

注意:

如果是AES256,那么把
kCCBlockSizeAES128->kCCBlockSizeAES256
kCCAlgorithmAES128->kCCAlgorithmAES256
kCCKeySizeAES128->kCCKeySizeAES256

至此整个加解密就完成了。

补充,使用工厂模式来创建加解密功能对象:

typedef NS_ENUM(NSInteger, KSAdEncryptionType) {
    KSAdEncryptionType_DES,
    KSAdEncryptionType_3DES,
    KSAdEncryptionType_AES128,
    KSAdEncryptionType_AES256,
};

@interface KSAdEncryption : NSObject
@property (nonatomic, readonly, strong) KSAdEncryptionEncoding *encryptionEncoding;
+ (instancetype)encryptionWithType:(KSAdEncryptionType)type encoding:(KSAdEncryptionDataStringEncoding)encoding;
- (NSString *)encrypt:(NSString *)plainString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString;
- (NSString *)decrypt:(NSString *)cipherString key:(NSString *)key initializationVectorString:(NSString *)initializationVectorString;
- (const void *)initializationVectorWithString:(NSString *)string;
@end

+ (instancetype)encryptionWithType:(KSAdEncryptionType)type encoding:(KSAdEncryptionDataStringEncoding)encoding {
    Class class = nil;
    switch (type) {
        case KSAdEncryptionType_DES:
            class = [KSAdEncryptionDES class];
            break;
        case KSAdEncryptionType_3DES:
            class = [KSAdEncryption3DES class];
            break;
        case KSAdEncryptionType_AES128:
            class = [KSAdEncryptionAES128 class];
            break;
        case KSAdEncryptionType_AES256:
        default:
            class = [KSAdEncryptionAES256 class];
            break;
    }
    KSAdEncryption *encryption = [class new];
    encryption.encryptionEncoding = [KSAdEncryptionEncoding encryptionEncodingWithEncoding:encoding];
    return encryption;
}

最后的测试代码:

    NSString *plainString = @"abc我们123";
    NSString *key = @"123key我们";
//    key = @"12345678";
    key = @"我们看看快手了关键时刻了来快手见鬼了是就离开过乐扣乐扣结束观看了";
    NSString *initializationVectorString = @"123456789";
    
    [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"plainString:%@ key:%@ initializationVectorString:%@", plainString, key, initializationVectorString];
    
    // des
    KSAdEncryption *desEncryption = [KSAdEncryption encryptionWithType:KSAdEncryptionType_DES encoding:KSAdEncryptionDataStringEncoding_Base64];
    
    NSString *cipherString = [desEncryption encrypt:plainString key:key initializationVectorString:initializationVectorString];
    NSString *plainFromCipherString = [desEncryption decrypt:cipherString key:key initializationVectorString:initializationVectorString];
    
    if ([plainFromCipherString isEqualToString:plainString]) {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption DES succeed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    } else {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption DES failed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    }
    // 3des
    KSAdEncryption *des3Encryption = [KSAdEncryption encryptionWithType:KSAdEncryptionType_3DES encoding:KSAdEncryptionDataStringEncoding_Base64];
    
    cipherString = [des3Encryption encrypt:plainString key:key initializationVectorString:initializationVectorString];
    plainFromCipherString = [des3Encryption decrypt:cipherString key:key initializationVectorString:initializationVectorString];
    
    if ([plainFromCipherString isEqualToString:plainString]) {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption 3DES succeed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    } else {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption 3DES failed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    }
    
    // aes128
    KSAdEncryption *aes128Encryption = [KSAdEncryption encryptionWithType:KSAdEncryptionType_AES128 encoding:KSAdEncryptionDataStringEncoding_Base64];
    
    cipherString = [aes128Encryption encrypt:plainString key:key initializationVectorString:initializationVectorString];
    plainFromCipherString = [aes128Encryption decrypt:cipherString key:key initializationVectorString:initializationVectorString];
    
    if ([plainFromCipherString isEqualToString:plainString]) {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption AES128 succeed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    } else {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption AES128 failed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    }
    
    // aes256
    KSAdEncryption *aes256Encryption = [KSAdEncryption encryptionWithType:KSAdEncryptionType_AES256 encoding:KSAdEncryptionDataStringEncoding_Base64];
    cipherString = [aes256Encryption encrypt:plainString key:key initializationVectorString:initializationVectorString];
    plainFromCipherString = [aes256Encryption decrypt:cipherString key:key initializationVectorString:initializationVectorString];
    if ([plainFromCipherString isEqualToString:plainString]) {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption AES256 succeed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    } else {
        [KSAdLogManager debugLogWithModule:KSAdLogModuleEncryption format:@"KSAdEncryption AES256 failed cipherString:%@ plainFromCipherString:%@", cipherString, plainFromCipherString];
    }

你可能感兴趣的:(iOS 对称加密 DES,3DES,AES128,AES256)