今天重新整理了一遍以前项目中经常用到过的几种加密的方式,发现以前其实对这几种加密的方式理解的不是特别的深刻首先从加密的本质是来看,是把一些不定长度的数据按照一定的编码规则输出为一种一定长度的数据串。这个是我理解的加密,其中不同的加密手段采用不同的编码规则。阅读之前先了解一些基本的概念:
1.简单的概念
明文:加密前的信息
密文:机密后的信息
算法:加密或解密的算法
密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao)
2.简单的例子
将123456每位数字都加1后得到234567,
其中123456就是明文,234567就是密文,加密密钥就是1,加密算法是每位加
3.对称加密和非对称加密
以上为例,
123456-->234567的加密密钥就是1,加密算法是每位+
234567-->123456的解密密钥也是1,解密算法是每位-
其中加密算法(+)和解密算法(-)相对称,这种加密算法就称作对称加密,
同样,如果加密算法和解密算法不对称就称之为非对称加密。
4.算法举例
对称加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法。
非对称加密算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC。
经典的哈希算法:MD2、MD4、MD5 和 SHA-1(目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密)
下面我们说一下我们常用到的加密手段
1.base64,这个加密手段是一些项目里面常用到的,一般采用这种加密手段十分好破解,他的加密实际作用不在于保密,你看看经过BASE64编码后的字符串,全部都是由标准键盘上面的常规字符组成,这样编码后的字符串在网关之间传递不会产生UNICODE字符串不能识别或者丢失的现象。你再仔细研究下EMAIL就会发现其实EMAIL就是用base64编码过后再发送的。然后接收的时候再还原。
还有一种情况下用BASE64编码也很好,比如一个图片文件,或者其他任何二进制文件。我可以把它编码成字符串。这样用XML或者数据库就能直接以文本的方式来存储这些文件了。
下面就说一下他的具体使用了:
首先你要先添加几个文件GTMBase64,这个是第三方的库可以从网络资源中获取,直接调用里面的算法
//加密算法
+(NSData *)encodeData:(NSData *)data {
return [self baseEncode:[data bytes]
length:[data length]
charset:kBase64EncodeChars
padded:YES];
}
//解密算法
+(NSData *)decodeData:(NSData *)data {
return [self baseDecode:[data bytes]
length:[data length]
charset:kBase64DecodeChars
requirePadding:YES];
}
从程序中我们可以看到无论是加密还是解密他处理的对象都是nsdata类型的
所以我们在加密解密之前要对数据进行二进制编码
实例说明:
//用户名
NSData*data_user=[userName_TF.text dataUsingEncoding:NSUTF8StringEncoding];
NSData*Data_U=[GTMBase64 encodeData:data_user];
NSString*username=[[NSString alloc]initWithData:Data_U encoding:NSUTF8StringEncoding];
2.下面说一下MD5加密的作用和用法
首先要知道MD5加密原理和性质,MD5首先他是一个安全的算列算法,他有两个特点。其一,输入两段明文也就是原始数据,不会得到相同的输出值。
其二,他的过程是不可逆的也就是说根据输出值,是不能得到原始的明文的。所以要解密MD5没有现成的算法,只能用穷举法,把可能出现的明文,用MD5算法散列之后,把得到的散列值和原始的数据形成一个一对一的映射表,然后在所谓的解密的时候,都是通过这个映射表来查找其所对应的原始明文。
而绝对没有一种算法,可以通过输出加密后的散搜索列值算出原始明文。
使用算法:
- (NSString *)md5Encrypt {
const char *cStr = [self UTF8String];
unsigned char result[16];
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算法,直接调用这个算法就可以了用起来十分简单。
[nsstring md5Encrypt]—>返回值也是一个字符串。MD5加密可以生成一个16位的字符串或者是32位的字符串
3.SHA-1与MD5都是摘要算法,且为不可逆算法;
应用角度来讲,适用性比安全性重要,两个算法长度有所不同,SHA-1 160位,MD5 128位。
如果从安全角度,在计算出摘要后,对摘要进行签名,可以增加抗抵赖、防篡改的能力
//32位MD5加密方式
+ (NSString *)getMd5_32Bit_String:(NSString *)srcString isUppercase:(BOOL)isUppercase{
const char *cStr = [srcString UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, strlen(cStr), digest );
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[result appendFormat:@"%02x", digest[i]];
if (isUppercase) {
return [result uppercaseString];
}else{
return result;
}
}
//16位MD5加密方式
+ (NSString *)getMd5_16Bit_String:(NSString *)srcString isUppercase:(BOOL)isUppercase{
//提取32位MD5散列的中间16位
NSString *md5_32Bit_String=[self getMd5_32Bit_String:srcString isUppercase:NO];
NSString *result = [[md5_32Bit_String substringToIndex:24] substringFromIndex:8];//即9~25位
if (isUppercase) {
return [result uppercaseString];
}else{
return result;
}
}
//sha1加密方式
+ (NSString *)getSha1String:(NSString *)srcString{
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha256加密方式
+ (NSString *)getSha256String:(NSString *)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha384加密方式
+ (NSString *)getSha384String:(NSString *)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA384_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha512加密方式
+ (NSString*) getSha512String:(NSString*)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
[result appendFormat:@"%02x", digest[i]];
return result;
}
这是具体的算法,直接封装在一个类里面直接调用就可以了使用方法和MD5是一样的。
4.AES加密算法。
AES是DES的进化版
这个是我目前使用的具有保密性的一个加密算法这个加密的时候需要一个key值解密的时候也要需要同样的key值才可以解密,相当于一个口令。
加密算法使用
//密钥加密和解密的时候要用
#define kCryptingKey @"1102130405061708" /// 同上
#define kCryptingIv @"1102130405061708" /// 同上
@implementation Tool
+ (NSString*) encrypt:(NSString*)recource
{
NSData *data = [recource dataUsingEncoding:NSUTF8StringEncoding];
NSData *result = [self AES128EncryptWithKey:kCryptingKey withData:data iv:kCryptingIv];
return [self stringWithHexBytes:result];
}
+ (NSString*) decryptData:(NSData*)recource
{
NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:recource iv:kCryptingIv];
return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}
+ (NSString*) decrypt:(NSString*)recource
{
NSData* data=[self decodeFromHexidecimal:recource];
NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:data iv:kCryptingIv];
return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}
+ (NSData *) decodeFromHexidecimal:(NSString*)str
{
NSString *command = [NSString stringWithString:str];
command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend = [[NSMutableData data] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [command length]/2; i++) {
byte_chars[0] = [command characterAtIndex:i*2];
byte_chars[1] = [command characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
return commandToSend;
}
+ (NSData *)AES128EncryptWithKey:(NSString *)key withData:(NSData*)_data iv:(NSString *) iv
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [_data length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
unsigned long int newSize = 0;
if(diff > 0)
{
newSize = dataLength + diff;
}
char dataPtr[newSize];
memcpy(dataPtr, [_data bytes], [_data length]);
for(int i = 0; i < diff; i++)
{
dataPtr[i + dataLength] = 0x00;
}
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
memset(buffer, 0, bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, 0x0000,
keyPtr, kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
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 *)AES128DecryptWithKey:(NSString *)key withData:(NSData*)data iv:(NSString *) iv
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0x0000,
keyPtr, kCCBlockSizeAES128,
ivPtr,
[data bytes],
dataLength,
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;
}
+ (NSString*) stringWithHexBytes:(NSData*)_data {
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([_data length] * 2)];
const unsigned char *dataBuffer = [_data bytes];
int i;
for (i = 0; i < [_data length]; ++i) {
[stringBuffer appendFormat:@"%02lX", (unsigned long)dataBuffer[i]];
}
return [stringBuffer copy];
}
也是直接封装在一个类里面直接调用算法就可以了,一般来说加密的时候项目你的开发文档上会告诉你这里的密钥你只要把相应的部分替换就可以了。
5.RSA待更新