以前寫文章總喜歡先廢話一堆,這次就免了,直入主題。
加 密算法通常分爲對稱性加密算法和非對稱性加密算法,對於對稱性加密算法,信息接收雙方都需事先知道密匙和加解密算法且其密匙是相同的,之後便是對數據進行 加解密了。非對稱算法與之不同,發送雙方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