美文网首页
iOS 对称加密 DES,3DES,AES128,AES256

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

作者: 传说中的汽水枪 | 来源:发表于2019-12-23 18:27 被阅读0次

    前言

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

    加解密的黑盒过程

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

    加解密

    DES/3DES加解密过程

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

    AES128/AES256加解密过程

    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 <CommonCrypto/CommonCryptor.h>

    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<data.length; i++) {
            NSString *newHexStr = [NSString stringWithFormat:@"%x", bytes[i] & 0xff]; //16进制数
            newHexStr = [newHexStr uppercaseString];
            if ([newHexStr length] == 1) {
                newHexStr = [NSString stringWithFormat:@"0%@",newHexStr];
            }
            string = [string stringByAppendingString:newHexStr];
        }
        return string;
    }
    - (NSData *)dataFromString:(NSString *)string {
        const char *ch = [[string lowercaseString] cStringUsingEncoding:NSUTF8StringEncoding];
        NSMutableData *data = [NSMutableData data];
        while (*ch) {
            if (*ch == ' ') {
                continue;
            }
            char byte = 0;
            if ('0' <= *ch && *ch <= '9') {
                byte = *ch - '0';
            } else if ('a' <= *ch && *ch <= 'f') {
                byte = *ch - 'a' + 10;
            } else if ('A' <= *ch && *ch <= 'F') {
                byte = *ch - 'A' + 10;
            }
            ch++;
            byte = byte << 4;
            if (*ch) {
                if ('0' <= *ch && *ch <= '9') {
                    byte += *ch - '0';
                } else if ('a' <= *ch && *ch <= 'f') {
                    byte += *ch - 'a' + 10;
                } else if('A' <= *ch && *ch <= 'F') {
                    byte += *ch - 'A' + 10;
                }
                ch++;
            }
            [data appendBytes:&byte length:1];
        }
        return data;
    }
    @end
    

    具体可以参考: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

          本文链接:https://www.haomeiwen.com/subject/mthtoctx.html