加 密算法通常分为对称性加密算法和非对称性加密算法,对于对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行 加解密了。非对称算法与之不同,发送双方A,B事先均生成一堆密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,如果A要给B发送消 息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,B向A发送消息时为同样的道理。
几种对称性加密算法:AES,DES,3DES
DES是一种分组数据加密技术(先将数据分成固定长度的小数据块,之后进行加密),速度较快,适用于大量数据加密,而3DES是一种基于DES的加密算法,使用3个不同密匙对同一个分组数据块进行3次加密,如此以使得密文强度更高。
相较于DES和3DES算法而言,AES算法有着更高的速度和资源使用效率,安全级别也较之更高了,被称为下一代加密标准。
几种非对称性加密算法:RSA,DSA,ECC
RSA和DSA的安全性及其它各方面性能都差不多,而ECC较之则有着很多的性能优越,包括处理速度,带宽要求,存储空间等等。
几种线性散列算法(签名算法):MD5,SHA1,HMAC
这几种算法只生成一串不可逆的密文,经常用其效验数据传输过程中是否经过修改,因为相同的生成算法对于同一明文只会生成唯一的密文,若相同算法生成的密文不同,则证明传输数据进行过了修改。通常在数据传说过程前,使用MD5和SHA1算法均需要发送和接收数据双方在数据传送之前就知道密匙生成算法,而HMAC与之不同的是需要生成一个密匙,发送方用此密匙对数据进行摘要处理(生成密文),接收方再利用此密匙对接收到的数据进行摘要处理,再判断生成的密文是否相同。
对于各种加密算法的选用:
由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。
在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。
如果在选定了加密算法后,那采用多少位的密钥呢?一般来说,密钥越长,运行的速度就越慢,应该根据的我们实际需要的安全级别来选择,一般来说,RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。
对于几种加密算法的内部实现原理,我不想研究的太透彻,这些问题就留给科学家们去研究吧。而对于其实现而言,网上有很多开源版本,比较经典的是PorlaSSL(官网:http://en.wikipedia.org/wiki/PolarSSL)。其它语言如JAVA,OBJC也都有相应的类库可以使用。以下附上自己用OC封装的通用加密类:
CryptionUseSysLib.h // // CryptionUseSysLib.h // encoding // // Created by weiy on 12-7-25. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> @interface CryptionUseSysLib : NSObject{ } + (NSData *) md5:(NSString *)str; + (NSData *) doCipherUseAesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt; + (NSData *) doCipherUse3DesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt; + (NSData *) doCipherUseDesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt; + (NSData *) doCipherUseCastMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt; + (NSString *) encodeBase64WithString:(NSString *)strData; + (NSString *) encodeBase64WithData:(NSData *)objData; + (NSData *) decodeBase64WithString:(NSString *)strBase64; @end
CryptionUseSysLib.m // // CryptionUseSysLib.m // encoding // // Created by weiy on 12-7-25. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import "CryptionUseSysLib.h" 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 CryptionUseSysLib + (NSString *) md5:(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] ]; } + (NSData *)doCipher:(NSData *)sTextIn key:(NSData *)sKey Algorithm:(CCAlgorithm)algorithm context:(CCOperation)encryptOrDecrypt { NSData * dTextIn; dTextIn = [sTextIn mutableCopy]; NSMutableData * dKey = [sKey mutableCopy]; int moreSize = 0; //make key to standard; switch (algorithm) { case kCCAlgorithmDES: moreSize = kCCBlockSizeDES; [dKey setLength:kCCKeySizeDES]; break; case kCCAlgorithm3DES: moreSize = kCCBlockSize3DES; [dKey setLength:kCCKeySize3DES]; break; case kCCAlgorithmAES128: moreSize = kCCBlockSizeAES128; [dKey setLength:kCCKeySizeAES128]; break; case kCCAlgorithmCAST: moreSize = kCCBlockSizeCAST; [dKey setLength:kCCKeySizeMaxCAST]; break; case kCCAlgorithmRC4: case kCCAlgorithmRC2: moreSize = kCCBlockSizeRC2; [dKey setLength:kCCKeySizeMaxRC2]; break; default: return nil; break; } uint8_t *bufferPtr1 = NULL; size_t bufferPtrSize1 = 0; size_t movedBytes1 = 0; unsigned char iv[8]; memset(iv, 0, 8); bufferPtrSize1 = [sTextIn length] + moreSize; bufferPtr1 = malloc(bufferPtrSize1); memset((void *)bufferPtr1, 0, bufferPtrSize1); // cryption.... CCCryptorStatus ccStatus = CCCrypt(encryptOrDecrypt, // CCOperation op algorithm, // CCAlgorithm alg kCCOptionPKCS7Padding|kCCOptionECBMode, // CCOptions options [dKey bytes], // const void *key [dKey length], // size_t keyLength iv, // const void *iv [dTextIn bytes], // const void *dataIn [dTextIn length], // size_t dataInLength (void *)bufferPtr1, // void *dataOut bufferPtrSize1, // size_t dataOutAvailable &movedBytes1); // size_t *dataOutMoved // output situation after crypt switch (ccStatus) { case kCCSuccess: NSLog(@"SUCCESS"); break; case kCCParamError: NSLog(@"PARAM ERROR"); break; case kCCBufferTooSmall: NSLog(@"BUFFER TOO SMALL"); break; case kCCMemoryFailure: NSLog(@"MEMORY FAILURE"); break; case kCCAlignmentError: NSLog(@"ALIGNMENT ERROR"); break; case kCCDecodeError: NSLog(@"DECODE ERROR"); break; case kCCUnimplemented: NSLog(@"UNIMPLEMENTED"); break; default: break; } if (ccStatus == kCCSuccess){ NSData *result = [NSData dataWithBytes:bufferPtr1 length:movedBytes1]; free(bufferPtr1); return result; } free(bufferPtr1); return nil; } + (NSData*)doCipherUse3DesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt{ return [CryptionUseSysLib doCipher:sTextIn key:sKey Algorithm:kCCAlgorithm3DES context:encryptOrDecrypt]; } + (NSData *) doCipherUseCastMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt{ return [CryptionUseSysLib doCipher:sTextIn key:sKey Algorithm:kCCAlgorithmCAST context:encryptOrDecrypt]; } + (NSData*)doCipherUseDesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt{ return [CryptionUseSysLib doCipher:sTextIn key:sKey Algorithm:kCCAlgorithmDES context:encryptOrDecrypt]; } + (NSData*)doCipherUseAesMethod:(NSData *)sTextIn key:(NSData *)sKey context:(CCOperation)encryptOrDecrypt{ return [CryptionUseSysLib doCipher:sTextIn key:sKey Algorithm:kCCAlgorithmAES128 context:encryptOrDecrypt]; } + (NSString *)encodeBase64WithString:(NSString *)strData { return [CryptionUseSysLib encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]]; } + (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:NSASCIIStringEncoding]; } + (NSData *)decodeBase64WithString:(NSString *)strBase64 { const char * objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding]; 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; } @end