美文网首页
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加密小记

    1 对称加密加密解密是同一个密钥,加解密速度快,常见的有DES,3DES,AES128,AES256等。DES已经...

  • iOS常用加解密方式

    AES128 AES128加密 AES128解密 3DES 3DES加密 3DES解密 DES DES加密 DES解密

  • 面试题总结

    1. iOS开发中的加密方式 iOS加密相关算法框架:CommonCrypto。 对称加密: DES、3DES、A...

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

    前言 最近开发的功能需要用对网络传输的数据进行加密,因此调研了常用了对称加密DES,3DES,AES128,AES...

  • android 3DES加密和MD5加密

    经常使用加密算法:DES、3DES、RC4、AES,RSA等;对称加密:des,3des,aes非对称加密:rsa...

  • Android 加密解密的几种方式总结

    经常使用加密算法:DES、3DES、RC4、AES,RSA等; 对称加密:des,3des,aes 非对称加密:r...

  • IOS的签名机制

    前言 了解IOS的数字签名机制之前我们需要掌握以下几个知识:加密解密(对称加密(DES 3DES AES),非对称...

  • iOS 签名机制

    前言 学习iOS签名机制,可参考如下学习路线: 加密解密(对称DES 3DES AES、非对称RSA)--->单向...

  • 密码学及iOS签名(一) —— 加密解密

    加密解密类型 对称加密 公钥密码(非对称加密) 对称加密(常见的DES、 3DES、AES) 在对称密码中,加密、...

  • 对称加密与非对称加密

    一.对称加密 常用的对称加密DES、AES,DES也有衍生的3DES等加密方式 对称加密用到的加密模式有ECB、C...

网友评论

      本文标题:iOS 对称加密 DES,3DES,AES128,AES256

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