dailyLearning -- 移动端常用的加解密方式

一、MD5

MD5加密, 全称是Message Digest Algorithm 5, 译为“消息摘要算法第5版”, 是最常用的加密方式之一, 对输入信息生成唯一的128位散列值(32个字符). 其主要特点是 不可逆, 相同数据的 MD5值肯定一样, 不同数据的 MD5值不一样(不绝对, 但基本不会相同).

MD5算法的性质:
  • 压缩性: 任意长度的数据, 算出的 MD5值长度都是固定的.
  • 容易计算: 从原数据计算出 MD5值很容易.
  • 抗修改性: 对元数据进行任何改动, 哪怕修改一个字节, 所得到的 MD5值都有很大的区别.
  • 弱抗碰撞: 一直元数据和其 MD5值, 想找到一个具有相同 MD5值得数据(即伪造数据) 是非常困难的.
  • 强抗碰撞: 想找到两个不同的数据, 使他们具有相同的 MD5值, 是非常困难的.
MD5的应用

由于MD5加密算法具有较好的安全性,而且免费,因此该加密算法被广泛使用.
主要运用在数字签名、文件完整性验证以及口令加密等方面.
在移动端常见对一些关键字段进行加密.

ObjC 代码实现:
//苹果包装了MD5加密的方法,使用起来十分的方便。 
//这里我们一般通过类别的方式, 为 NSString 添加 MD5加密方法
#import  "NSString+hash.h"
//1、导入头文件:
#import

//2、MD5加密方法:
- (NSString *) md5:(NSString *) input {
    const char *cStr = [input UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
    
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    
    for(int i = 0; i < CC_MD5_DIGEST_LENGTH; I++)
        [output appendFormat:@"%02x", digest[I]];
    
    return  output;
}

//3、调用MD5方法
    NSString *str = @"123456";
    
    NSString *result = [self md5:str];
    
    NSLog(@"%@",result);

终端测试命令: echo -n abc|openssl md5 给字符串abc加密

注:
MD5虽然说是不可逆的 但是由于有网站 http://www.cmd5.com 的存在,专门用来查询MD5码 所以有的简单的MD5码是可以在这里搜到源码的。
为了让MD5码更加安全 涌现了很多其他方法 如 加盐. 盐要足够长足够乱 得到的MD5码就很难查到。

MD5的改进

加盐(Salt):在明文的固定位置
插入随机串,然后再进行MD5
先加密,后乱序:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序
栗子:
导入NSString+hash.h (上面MD5应用封装的方法)封装好的加密分类算法下面是封装好的demo:

#import "ViewController.h"
#import "NSString+Hash.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   
   [self MD5];
   
   [self MD5Salt:@"san"];
   
   [self doubleMD5];
   
   [self MD5Reorder];
}

MD5加密
-(void)MD5{
   NSString *pwd = @"123456";
   NSString *pwdMD5 = [pwd md5String];
   NSLog(@"%@",pwdMD5);
}

/**
* 撒盐 加密 MD5($pass.$salt)
*/
-(void)MD5Salt:(NSString *)salt{
   NSString *pwd = @"123456";
   pwd =[pwd stringByAppendingString:salt]; 撒盐:随机地往明文中插入任意字符串
   NSString *pwdMD5 = [pwd md5String];
   NSLog(@"%@",pwdMD5);
}

/**
*  MD5(MD5($pass))
*/
- (void)doubleMD5{
   NSString *pwd = @"123456";
   NSString *pwdMD5MD5 = [[pwd md5String]md5String];
   NSLog(@"%@",pwdMD5MD5);
}

/**
*  先加密,后乱序
*/
- (void)MD5Reorder{

   NSString *pwd = @"123456";
   NSString *pwdMD5 = [pwd md5String];
   NSLog(@"oldpwdMD5=%@",pwdMD5);
   NSString *prefix = [pwdMD5 substringFromIndex:3]; 从下标为3的开始截取(包含3)
   NSString *subfix = [pwdMD5 substringToIndex:3];   截取0到3的字符串(不包含3)
   pwdMD5 = [prefix stringByAppendingString:subfix];
   NSLog(@"newpwdMD5=%@",pwdMD5);
}
@end

二、HMAC 加密

此加密方法需要先生成密钥, 然后再对字符串(常见密码加密) 进行 MD5和 HMAC 加密, 数据库中需要存放当时使用的密钥和密码加密后的密文.
例:
在用户登录时 再次对填入的密码进行加密, 并且还要加上当前时间(精确到分钟) 再次 HMAC 加密, 服务器也会拿出以前存放的密文加上时间进行加密. 所以就算密码的密文在中途被截取, 也只有在1分钟内破译才有效, 大大加强了安全性. 考虑到网络延迟的因素, 一般服务器会多算一种答案, 如, 23分过来的密码, 他会把 23分和22分的都算一下和用户匹配, 只要对上一个, 就允许登录.

  • 如图 用户注册与用户登录


    dailyLearning -- 移动端常用的加解密方式_第1张图片
    用户注册

    dailyLearning -- 移动端常用的加解密方式_第2张图片
    与用户登录

    HMAC现在使用的比较广泛, 安全级别更高, 破解难度高.
    但还是有风险:每次结果一致, 有可能被暴力破解.
    要想做到的安全级别更更高, 现在密码学要求:同样的算法, 同样的密码明文, 每次的结果不一样.

ObjC 代码实现:
NSString *password = [self hMacWithPwd:@"这是密码"];

// 这里 使用服务器时间,生成带时间戳的密码
//对密码进行 hMac
- (NSString *)hMacWithPwd:(NSString *)pwd {

    //1.设置密钥key
    NSString *key = @"123456".md5String;

    //2.对密钥key对密码进行HMac
    NSString *hMacPwd = [pwd hmacMD5StringWithKey:key];

    //3.获得当前服务器的系统时间
    NSURL*url = [NSURL URLWithString:@"这里是获取服务器时间的 URL"];

    //使用同步获取时间(注意:这里要使用同步,确定先获得服务器的时间,后面的代码才能执行)
    NSData *timeData = [NSData dataWithContentsOfURL:url];

    //反序列化取出时间
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:timeData options:0 error:NULL];

    NSString *dateStr = dict[@"key"];

    //4.用密码+ 时间 生成密码
    hMacPwd =[hMacPwd stringByAppendingString:dateStr];

    //5.返回hmac 结果
    return [hMacPwd hmacMD5StringWithKey:key];
}

类别方法

//计算HMAC MD5散列结果
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
    const char *keyData = key.UTF8String;
    const char *strData = self.UTF8String;
    uint8_t buffer[CC_MD5_DIGEST_LENGTH];
    
    CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}

终端测试命令: echo -n "string" | openssl dgst -md5 -hmac "key"

你可能感兴趣的:(dailyLearning -- 移动端常用的加解密方式)