前言
最近開發(fā)的功能需要用對網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)進(jìn)行加密不傅,因此調(diào)研了常用了對稱加密DES
,3DES
搁骑,AES128
,AES256
又固。做了如下的整理仲器。
加解密的黑盒過程
現(xiàn)在我們就是需要把plainString
變成cipherString
DES/3DES加解密過程
DES
加密過程有一步是把加密后的data
數(shù)據(jù)先轉(zhuǎn)場Base64
的data
數(shù)據(jù),然后進(jìn)行UTF8
轉(zhuǎn)化cipherString
直接通過Base64
轉(zhuǎn)成cipherData
AES128/AES256加解密過程
AES
的加密和解密過程是對稱的- 在轉(zhuǎn)化成字符串的時候口予,需要選擇
Base64
還是Hex
轉(zhuǎn)化
DES/3DES 實現(xiàn)代碼
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;
}
加密過程:
plainString
通過UTF8
變成plainData
plainData
通過DES
轉(zhuǎn)化為cipherData
cipherData
通過Base64
轉(zhuǎn)化為base64Data
base64Data
通過UTF8
轉(zhuǎn)化為可讀的cipherString
解密過程
cipherString
通過Base64
變成cipherData
cipherData
通過DES
轉(zhuǎn)化為plainData
plainData
通過UTF8
轉(zhuǎn)化為plainString
注意:
import <CommonCrypto/CommonCryptor.h>
- 如果是
3DES
娄周,那么把
kCCBlockSizeDES
->kCCBlockSize3DES
kCCAlgorithmDES
->kCCAlgorithm3DES
kCCKeySize3DES
->kCCKeySize3DES
。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轉(zhuǎn)化
在先介紹AES128/AES256
實現(xiàn)代碼之前沪停,先介紹兩種不常用的NSData
與NSString
轉(zhuǎn)化
直接上類和代碼:
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進(jìn)制數(shù)
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 *互相轉(zhuǎn)換
AES128/AES256 實現(xiàn)代碼
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;
}
加密過程:
plainString
通過UTF8
變成plainData
plainData
通過AES
轉(zhuǎn)化為cipherData
cipherData
通過Base64/Hex
轉(zhuǎn)化為cipherString
解密過程
cipherString
通過Base64/Hex
變成cipherData
cipherData
通過AES
轉(zhuǎn)化為plainData
plainData
通過UTF8
轉(zhuǎn)化為plainString
注意:
如果是
AES256
煤辨,那么把
kCCBlockSizeAES128
->kCCBlockSizeAES256
kCCAlgorithmAES128
->kCCAlgorithmAES256
kCCKeySizeAES128
->kCCKeySizeAES256
。
至此整個加解密就完成了木张。
補充众辨,使用工廠模式來創(chuàng)建加解密功能對象:
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 = @"我們看看快手了關(guān)鍵時刻了來快手見鬼了是就離開過樂扣樂扣結(jié)束觀看了";
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];
}