DES算法
☆提供高质量的数据保护,防止数据未经授权的泄露和未被察觉的修改
☆具有相当高的复杂性,使得破译的开销超过可能获得的利益,同时又要便于理解和掌握
☆DES密码体制的安全性应该不依赖于算法的保密,其安全性仅以加密密钥的保密为基础
☆实现经济,运行有效,并且适用于多种完全不同的应用
苹果本身支持DES加密,在项目中引入头文件 CommonCrypto/CommonCryptor.h 即可使用相关函数.
我自己对其进行了封装,支持ARC与非ARC
YXCrypto.h
// // YXCrypto.h // 用秘钥给字符串加密或者解密 // // Created by YouXian on 14-3-18. // Copyright (c) 2014年 YouXian. All rights reserved. // #import <Foundation/Foundation.h> @interface YXCrypto : NSObject /*! * 给字符串加密 */ + (NSString *)DesEncryptString:(NSString*)src WithKey:(NSString *)key; /*! * 给字符串解密 */ + (NSString *)DesDecryptString:(NSString*)src WithKey:(NSString *)key; @end
YXCrypto.m
// // YXCrypto.m // 用秘钥给字符串加密或者解密 // // Created by YouXian on 14-3-18. // Copyright (c) 2014年 YouXian. All rights reserved. // #import "YXCrypto.h" #import <CommonCrypto/CommonCryptor.h> #if __has_feature(objc_arc) // ARC #define Auto_Release(obj) #define Safe_Release(obj) #else // 非ARC #define Auto_Release(obj) [obj autorelease] #define Safe_Release(obj) [obj release]; obj = nil #endif static YXCrypto *shareInstance = nil; @implementation YXCrypto /*! * 给字符串加密 */ + (NSString *)DesEncryptString:(NSString*)src WithKey:(NSString *)key { NSString* strRet = @""; if (shareInstance == nil) { shareInstance = [[YXCrypto alloc] init]; } // encrypt source content NSData* bytes = [src dataUsingEncoding:NSUTF8StringEncoding]; NSData* data = [shareInstance DesCryptWithOperation:kCCEncrypt bytes:bytes key:key]; // format bytes to visible string char* pBuff = (char*)[data bytes]; for (int i=0; i<data.length; i++) { strRet = [strRet stringByAppendingFormat:@"%02X", pBuff[i]& 0xFF]; } return strRet; } /*! * 给字符串解密 */ + (NSString *)DesDecryptString:(NSString*)src WithKey:(NSString *)key { if (shareInstance == nil) { shareInstance = [[YXCrypto alloc] init]; } static unsigned char _map_ch2hex[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0, 0, 0, 0, 0, 0, 0, // :, ;, <, =, >, ?, @, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, }; // decode source content to bytes unsigned char* bytes = (unsigned char*)malloc((src.length+1)*sizeof(unsigned char)); [[src uppercaseString] getCString:(char*)bytes maxLength:src.length+1 encoding:NSUTF8StringEncoding]; unsigned char *p1 = bytes, *p2 = bytes; int n = src.length/2; for (int i=0; i<n; i++) { *p1 = _map_ch2hex[*p2-'0'] * 0x10 + _map_ch2hex[*(p2+1)-'0']; p1++; p2+=2; } NSData* data = [NSData dataWithBytes:bytes length:n]; // decrypt source bytes NSData* dataOut = [shareInstance DesCryptWithOperation:kCCDecrypt bytes:data key:key]; free(bytes); NSString* strRet = [[NSString alloc] initWithData:dataOut encoding:NSUTF8StringEncoding]; Auto_Release(strRet); return strRet; } - (NSData *)DesCryptWithOperation:(CCOperation)operation bytes:(NSData*)bytes key:(NSString *)key { NSUInteger dataLength = [bytes length]; size_t bufferSize = ([bytes length] + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1); unsigned char *buffer = (unsigned char *)malloc(bufferSize*sizeof(unsigned char)); memset((void*)buffer, 0, bufferSize); size_t numBytesCrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(operation, kCCAlgorithmDES, kCCOptionPKCS7Padding | kCCOptionECBMode, (void const*)[key UTF8String], kCCKeySizeDES, NULL, [bytes bytes], dataLength, (void*)buffer, bufferSize, &numBytesCrypted); NSData* dataRet = nil; if (cryptStatus == kCCSuccess) { dataRet = [[NSData alloc] initWithBytes:buffer length:numBytesCrypted]; Auto_Release(dataRet); } free(buffer); return dataRet; } @end
使用:
附录1:https://github.com/alfaromeodev/Cryptor
// // Cryptor.h // test // // Created by Da Zhang on 11/5/12. // Copyright 2012 __MyCompanyName__. All rights reserved. // #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> @interface Cryptor : NSObject { } /* all the methods below only support utf8 string */ + (NSString *)encodeMD5:(NSString *)str; + (NSString *)encodeDES:(NSString *)plainString key:(NSString *)key; + (NSString *)decodeDES:(NSString *)decodedString key:(NSString*)key; + (NSString *)encodeBase64:(NSString *)plainString; + (NSString *)decodeBase64:(NSString *)decodedString; @end
// // Cryptor.m // test // // Created by Da Zhang on 11/5/12. // Copyright 2012 __MyCompanyName__. All rights reserved. // #import "Cryptor.h" @interface Cryptor () + (NSString *)encodeBase64WithData:(NSData *)objData; + (NSData *)decodeBase64WithUTF8String:(NSString *)strBase64; + (NSString *)parseByte2HexString:(Byte *)bytes; @end static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const short _base64DecodingTable[256] = { -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 }; @implementation Cryptor #pragma mark private section + (NSData *)decodeBase64WithUTF8String:(NSString *)strBase64 { const char * objPointer = [strBase64 cStringUsingEncoding:NSUTF8StringEncoding]; int intLength = strlen(objPointer); int intCurrent; int i = 0, j = 0, k; unsigned char * objResult; objResult = calloc(intLength, sizeof(char)); // Run through the whole string, converting as we go while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) { if (intCurrent == '=') { if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) { // the padding character is invalid at this point -- so this entire string is invalid free(objResult); return nil; } continue; } intCurrent = _base64DecodingTable[intCurrent]; if (intCurrent == -1) { // we're at a whitespace -- simply skip over continue; } else if (intCurrent == -2) { // we're at an invalid character free(objResult); return nil; } switch (i % 4) { case 0: objResult[j] = intCurrent << 2; break; case 1: objResult[j++] |= intCurrent >> 4; objResult[j] = (intCurrent & 0x0f) << 4; break; case 2: objResult[j++] |= intCurrent >>2; objResult[j] = (intCurrent & 0x03) << 6; break; case 3: objResult[j++] |= intCurrent; break; } i++; } // mop things up if we ended on a boundary k = j; if (intCurrent == '=') { switch (i % 4) { case 1: // Invalid state free(objResult); return nil; case 2: k++; // flow through case 3: objResult[k] = 0; } } // Cleanup and setup the return NSData NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease]; free(objResult); return objData; } + (NSString *)encodeBase64WithData:(NSData *)objData { const unsigned char * objRawData = [objData bytes]; char * objPointer; char * strResult; // Get the Raw Data length and ensure we actually have data int intLength = [objData length]; if (intLength == 0) return nil; // Setup the String-based Result placeholder and pointer within that placeholder strResult = (char *)calloc(((intLength + 2) / 3) * 4, sizeof(char)); objPointer = strResult; // Iterate through everything while (intLength > 2) { // keep going until we have less than 24 bits *objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; *objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)]; *objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f]; // we just handled 3 octets (24 bits) of data objRawData += 3; intLength -= 3; } // now deal with the tail end of things if (intLength != 0) { *objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; if (intLength > 1) { *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; *objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2]; *objPointer++ = '='; } else { *objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4]; *objPointer++ = '='; *objPointer++ = '='; } } // Terminate the string-based result *objPointer = '\0'; // Return the results as an NSString object return [NSString stringWithCString:strResult encoding:NSUTF8StringEncoding]; } + (NSString *)parseByte2HexString:(Byte *)bytes { NSMutableString *hexStr = [[NSMutableString alloc]init]; int i = 0; if(bytes) { while (bytes[i] != '\0') { NSString *hexByte = [NSString stringWithFormat:@"%x",bytes[i] & 0xff];///16进制数 if([hexByte length]==1) [hexStr appendFormat:@"0%@", hexByte]; else [hexStr appendFormat:@"%@", hexByte]; i++; } } //NSLog(@"bytes 的16进制数为:%@",hexStr); return hexStr; } #pragma mark public section + (NSString *)encodeMD5:(NSString *)str { const char *cStr = [str UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5( cStr, strlen(cStr), result ); return [NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] ]; } + (NSString *)encodeBase64:(NSString *)plainString { return [Cryptor encodeBase64WithData:[plainString dataUsingEncoding:NSUTF8StringEncoding]]; } + (NSString *)decodeBase64:(NSString *)decodedString { NSData * objData = [Cryptor decodeBase64WithUTF8String:decodedString]; return [[NSString alloc] initWithData:objData encoding:NSUTF8StringEncoding]; } + (NSString *)encodeDES:(NSString *)plainString key:(NSString *)key { NSString *ciphertext = nil; const char *textBytes = [plainString UTF8String]; NSUInteger dataLength = strlen(textBytes); unsigned char buffer[1024]; memset(buffer, 0, sizeof(char)); Byte iv[] = {1,2,3,4,5,6,7,8}; size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, [key UTF8String], kCCKeySizeDES, iv, textBytes, dataLength, buffer, 1024, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted]; ciphertext = [[Cryptor encodeBase64WithData:data] autorelease]; } return ciphertext; } + (NSString *)decodeDES:(NSString*)decodedString key:(NSString*)key { NSData* cipherData = [Cryptor decodeBase64WithUTF8String:decodedString]; unsigned char buffer[1024]; memset(buffer, 0, sizeof(char)); size_t numBytesDecrypted = 0; Byte iv[] = {1,2,3,4,5,6,7,8}; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, [key UTF8String], kCCKeySizeDES, iv, [cipherData bytes], [cipherData length], buffer, 1024, &numBytesDecrypted); NSString* plainText = nil; if (cryptStatus == kCCSuccess) { NSData* data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted]; plainText = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; } return plainText; } @end
附录2:AES加密
NSData+AES.h + NSData+AES.m
#import <Foundation/Foundation.h> /** * Adds AES encryption and decryption capabilities to NSData. */ @interface NSData (AES) /** * Encrypt NSData using AES256 with a given symmetric encryption key. * @param key The symmetric encryption key */ - (NSData *)AES256EncryptWithKey:(NSString *)key; /** * Decrypt NSData using AES256 with a given symmetric encryption key. * @param key The symmetric encryption key */ - (NSData *)AES256DecryptWithKey:(NSString *)key; @end
#import "NSData+AES.h" #import <CommonCrypto/CommonCryptor.h> @implementation NSData (AES) - (NSData *)AES256EncryptWithKey:(NSString *)key { // 'key' should be 32 bytes for AES256, will be null-padded otherwise char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or //equal to the input size plus the size of one block. //That's why we need to add the size of one block here size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, NULL /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { //the returned NSData takes ownership of the buffer and will free it on deallocation return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); //free the buffer; return nil; } - (NSData *)AES256DecryptWithKey:(NSString *)key { // 'key' should be 32 bytes for AES256, will be null-padded otherwise char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or //equal to the input size plus the size of one block. //That's why we need to add the size of one block here size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, NULL /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesDecrypted); if (cryptStatus == kCCSuccess) { //the returned NSData takes ownership of the buffer and will free it on deallocation return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); //free the buffer; return nil; } @end