对于我们iOS工作人员,在做登陆这块儿的时候,密码一定要进行加密,然后才进行网络请求,要不然就会被其他人获取用来做一些对我们不利的事情。
base64(可以反编译)
首先,我谈一下base64,有人说这是一个加密算法,可我觉得这更像是一个编码工具,因为它完全是可逆的,分分钟就会被破解,而且网络上有很多破解的工具,直接可以破解,所以这个一定不能用于密码的“加密”,一些不需要特别加密的,例如用户名,我们可以用base64进行编码,让人不是一眼就能看出来是什么。base64在iOS5之前没有直接集成的API,所以老的程序有可能用的是三方库,iOS5之后我们可以直接在工程中进行调用。下方是我对base64的详细说明:http://blog.csdn.net/liyunxiangrxm/article/details/52062009
md5(不可逆)
然后我们说说MD5,MD5是一个比较严密的加密方式,因为他是不可逆的。如果大家想要了解MD5的原理,请自行查询,我这里只介绍在咱们iOS中是如何用的。
如果想用MD5直接进行加密的:可以直接用以下代码返回即可
方法一、
#import
@interface NSString (md5)
-(NSString *) md5HexDigest;
@end
#import "NSString+MD5HexDigest.h"
@implementation NSString (md5)
-(NSString *) md5HexDigest
{
const char *original_str = [self UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(original_str, strlen(original_str), result);
NSMutableString *hash = [NSMutableString string];
for (int i = 0; i < 16; i++)
[hash appendFormat:@"%02X", result[i]];
return [hash lowercaseString];
}
@end
方法二、
将字符串进行MD5加密,返回加密后的字符串。
#import // Need to import for CC_MD5 access
- (NSString *)md5:(NSString *)str
{
const char *cStr = [str UTF8String];
unsigned char result[16];
CC_MD5(cStr, strlen(cStr), result); // This is the md5 call
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]
];
}
1、当我们注册,登陆一套的时候,然后没有记住密码功能的,我们可以直接对密码进行MD5操作,注册的时候将MD5之后的密码传到服务端,服务端存储的是MD5之后的密码串,再次登陆的时候,客户端传过去MD5之后的密码与服务端存储的MD5后密码进行比对,当比对一样就返回成功,然后进行登陆。
然而这样还是不够严密,因为网上有一套数据库http://cmd5.com可以查到许多MD5的词条,所以还是不够严密,这是我们可以用加盐的方式进行,加盐就是在原有的密码上再加上一段很长的字符,然后一起进行MD5操作,这就是加盐。
这样还不够的话我们可以用HMAC +MD5的方式进行加密,(上方所说的方法已进行封装,可以直接用https://github.com/liyuunxiangGit/Security),然后还可以再加盐。方法 很多,这里不一一介绍了,大家可以看我的github,对其进行研究。
2、当我们想有记住密码的操作的时候,base64太容易解,MD5不可逆,如果存到用户中心的话很容易被取到,所以这是我想到的是用密码串,这个也已经封装好(网上应该有现成的三方库)我这里的https://github.com/liyuunxiangGit/Security/tree/master/%E9%92%A5%E5%8C%99%E4%B8%B2%E4%B8%89%E6%96%B9/SSKeychain
没有太详细的讲解,只是给大家一个思路。大家可以一起进行研究。
下方是从网上找了一张加密的图:大家可以看看
AES(可以反编译)
3、(文件加密)我之前还用到AES/CBC/PKCS5Padding 128位加密算法,加密后在BASE64编码。请求采用参数加密原则(json结构保留),结果采用整体加密原则(纯密文,解析完是json)。这里有找到的封装的方法可以一起研究:https://github.com/liyuunxiangGit/Security
下方是256位的封装的aes加密。
高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法。 以下实现代码中分别为NSData和NSString增加了一个Category。使用时直接调用即可。
需要注意的是,AES并不能作为HASH算法,加密并解密后的结果,并不一定与原文相同,使用时请注意进行结果验算。例如解密原文的长度,格式规则等。 NG实例
Objective-c的AES加密和解密算法的具体实现代码如下: 1.拓展NSData,增加AES256加密方法
//
//NSData+AES256.h
//
#import
#import
#import
@interface NSData(AES256)
-(NSData *) aes256_encrypt:(NSString *)key;
-(NSData *) aes256_decrypt:(NSString *)key;
@end
//
//NSData+AES256.m
//
#import "NSData+AES256.h"
@implementation NSData(AES256)
- (NSData *)aes256_encrypt:(NSString *)key //加密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
- (NSData *)aes256_decrypt:(NSString *)key //解密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
@end
//
//NSString +AES256.h
//
#import
#import
#import
#import "NSData+AES256.h"
@interface NSString(AES256)
-(NSString *) aes256_encrypt:(NSString *)key;
-(NSString *) aes256_decrypt:(NSString *)key;
@end
//
//NSString +AES256.h
//
@implementation NSString(AES256)
-(NSString *) aes256_encrypt:(NSString *)key
{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
//对数据进行加密
NSData *result = [data aes256_encrypt:key];
//转换为2进制字符串
if (result && result.length > 0) {
Byte *datas = (Byte*)[result bytes];
NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
for(int i = 0; i < result.length; i++){
[output appendFormat:@"%02x", datas[i]];
}
return output;
}
return nil;
}
-(NSString *) aes256_decrypt:(NSString *)key
{
//转换为2进制Data
NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [self length] / 2; i++) {
byte_chars[0] = [self characterAtIndex:i*2];
byte_chars[1] = [self characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
//对数据进行解密
NSData* result = [data aes256_decrypt:key];
if (result && result.length > 0) {
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]autorelease];
}
return nil;
}
@end