0%

密码学

视频笔记:加密算法之 — — 密码学详解

密码学概论,讲述密码学运用领域和使用场景

网络安全 && 数据安全

示例:控制台 —> /var/log —> apache2 服务器 (明文传输数据,不安全!)

原则:

  1. 在网络上不允许明文传输用户隐私信息;
  2. 在本地不允许明文保存用户隐私信息;

加密 — 密码学

base64 编码

可以将二进制数据进行编码,编码成只有 65 个字符文本文件(字符)!

字符:0 ~9, az, AZ, +/=

编码后文件数据会比原有文件大 1/3 左右。

原理

base64 编码:8 位的二进制 ASCII 编码 —> 6 位的 base64 编码

base64 编码表:

0~63,64 个字符,还有 = 表示空格,总共 65 个字符。

示例:

Man 转换为 base64 编码:TWFu

M 的 ASCII 编码 十进制为 77 ,二进制为 01001101:

前 6 位二进制 010011 (十进制为 19)在上面的 base64 编码表中为 T 。

因此 M ➡ T 。

空格情况

因为是把 8 个字节转换为 6 个字节进行编码,势必会产生位数不对应的问题。因此会使用 0 来补齐,用 = 表示全 0 的情况。(注意到 base64 总会编码补齐为 4 个字符一组)

因此,单独的 M 用 base64 编码 ➡ TQ==

Objective-C 代码

// base64编码
- (NSString *)base64Encode:(NSString *)string {
    // 1.将字符串转换为二进制
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    // 2.二进制数据进行编码
    return [data base64EncodedStringWithOptions:0];
}

// base64解码
- (NSString *)base64Decode:(NSString *)string {
    // 1.字符串转换为二进制
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
    // 2.解码
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

哈希算法 \ 对称加密 \ 非对称加密 算法简介

上世纪 70 年代开始 RSA — 非对称加密算法

RSA — 非对称加密算法

  • 公钥加密,私钥解密;
  • 私钥加密,公钥解密;

哈希(散列)函数

  • MD5
  • SHA1\SHA256\SHA512
  • HMAC

对称加密算法

  • DES
  • 3DES
  • RC2、RC4
  • AES (高级密码标准,美国国家安全局使用、Apple 钥匙串访问使用、Lastpass 使用了 256 位的 AES 密钥),以目前现阶段计算机的运行效率,要暴力破解 AES 加密算法,需要上千万年。

散列函数

算法都是公开的。

  • 对相同的数据加密,得到的结果是一样的。
  • 对不同的数据加密,得到的结果是定长的。(比如 MD5 对不同的数据加密,得到 32 个字符)
  • 加密之后的数据是没法解密的。(不可逆运算

MD5 加密

GitHub 源码:jerilimov/NSHash——NSData、NSString 的分类,添加了 MD5、SHA1、SHA256、SHA512 加密算法

NSString *pwd = @"123456";
pwd = [pwd MD5];
NSLog(@"MD5 = %@",pwd);
// MD5 = e10adc3949ba59abbe56e057f20f883e

像 MD5 这样的加密算法是无法反向解密的,但是对相同的数据加密,得到的结果是一样的。

于是 CMD5 利用散列函数的这种特性,将加密前的数据和加密后的数据进行映射保存,可以实现反向查询。

将刚才 123456 加密后的 MD5 输入,可以反向查询出原始数据:

MD5 加盐:对数据先加盐,再进行 MD5 加密,可以增加结果的复杂度

/* 盐,足够长,足够复杂,足够咸*/
static NSString *slat = @"5O9Jc!9%N^6Kd*dcS9Or$&fSVWmC^xku2@Lg0xd8CL0Sl$omN6zQS7c7YrHhtwn@";

NSString *pwd = @"123456";
pwd = [[pwd stringByAppendingString:slat] MD5];
NSLog(@"MD5 = %@",pwd);
// MD5 = 04f60881265e2b240b217f8deaaa8e12

再将此 MD5 密码放到该网站上进行查询:

没有查到,结果显示,被反向查询出来的难度就会加大。

缺点:盐是固定的,如果盐被泄露,数据就会不安全。

HMAC 加密

//-----------------------------------------------------
#import <Foundation/Foundation.h>

@interface NSString (Hash)
- (NSString *)hmacMD5StringWithKey:(NSString *)key;
- (NSString *)hmacSHA1StringWithKey:(NSString *)key;
- (NSString *)hmacSHA256StringWithKey:(NSString *)key;
- (NSString *)hmacSHA512StringWithKey:(NSString *)key;
@end

#import "NSString+Hash.h"
#import <CommonCrypto/CommonHMAC.h>
@implementation NSString (Hash)

- (NSString *)hmacMD5StringWithKey:(NSString *)key
{
    return [self hmacStringUsingAlg:kCCHmacAlgMD5 withKey:key];
}
- (NSString *)hmacSHA1StringWithKey:(NSString *)key
{
    return [self hmacStringUsingAlg:kCCHmacAlgSHA1 withKey:key];
}
- (NSString *)hmacSHA256StringWithKey:(NSString *)key
{
    return [self hmacStringUsingAlg:kCCHmacAlgSHA256 withKey:key];
}
- (NSString *)hmacSHA512StringWithKey:(NSString *)key
{
    return [self hmacStringUsingAlg:kCCHmacAlgSHA512 withKey:key];
}
#pragma mark - Helpers
- (NSString *)hmacStringUsingAlg:(CCHmacAlgorithm)alg withKey:(NSString *)key
{
    size_t size;
    switch (alg) {
        case kCCHmacAlgMD5:
            size = CC_MD5_DIGEST_LENGTH;
            break;
        case kCCHmacAlgSHA1:
            size = CC_SHA1_DIGEST_LENGTH;
            break;
        case kCCHmacAlgSHA224:
            size = CC_SHA224_DIGEST_LENGTH;
            break;
        case kCCHmacAlgSHA256:
            size = CC_SHA256_DIGEST_LENGTH;
            break;
        case kCCHmacAlgSHA384:
            size = CC_SHA384_DIGEST_LENGTH;
            break;
        case kCCHmacAlgSHA512:
            size = CC_SHA512_DIGEST_LENGTH;
            break;
        default:
            return nil;
    }

    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *messageData = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData *mutableData = [NSMutableData dataWithLength:size];
    CCHmac(alg, keyData.bytes, keyData.length, messageData.bytes, messageData.length, mutableData.mutableBytes);
    return [self stringFromBytes:(unsigned char *)mutableData.bytes length:(int)mutableData.length];
}
- (NSString *)stringFromBytes:(unsigned char *)bytes length:(int)length
{
    NSMutableString *mutableString = @"".mutableCopy;
    for (int i = 0; i < length; i++)
        [mutableString appendFormat:@"%02x", bytes[i]];
    return [NSString stringWithString:mutableString];
}
@end

测试

// HMAC 用一个密钥加密,并且做了两次散列。
// 在实际的开发中,密钥来自于服务器。——对应一个帐号,一个KEY
NSString *pwd = @"123456";
pwd = [pwd hmacMD5StringWithKey:@"Key"];
NSLog(@"MD5 = %@",pwd);
// MD5 = a7cac7471d2c9eb7a944e07d44d305ca

将此 MD5 密码放到该网站上查询也是查不到的。

项目实际使用流程:

  1. 服务器根据用户帐号生成 KEY,发送给客户端;
  2. 客户端获得 KEY 并保存到本地,使用 KEY 对数据进行 HMAC 加密,将加密后的数据发送给服务器;
  3. 服务器对加密后对数据进行验证。

客户端登录时,没有 KEY 就先根据帐号从服务器获取 KEY 保存到本地,再将获得的 KEY 对密码进行加密。

防止 KEY 泄露,对 KEY 进行非对称加密、定期更换 KEY。

QQ 设备锁:

  • 本地有 KEY—— 为授权手机。
  • 本地没有 KEY,未授权设备,需要允许服务器发送 KEY。允许一次登录,本地不保存 KEY,允许多次登录,保存 KEY 到本地。
  • 短信验证码登录获取 KEY。
  • 申诉获取 KEY。

HMAC 加密 + 时间戳(不加秒)

之前:

验证方式:HMAC 密码直接匹配是否正确。

现在:

客户端:(HMAC 密码 +“201711010358”).MD5 校验

服务器:

  1. (HMAC 密码 +“201711010359”).MD5 校验
  2. (HMAC 密码 +“201711010358”).MD5 校验

密码验证有效期最长 2 分钟,超过 2 分钟,验证失败。

有经验的服务器人员,会在返回数据时,返回时间戳。

登录等待时间,不要超过 6 秒!!!提示用户:你的网络不稳定,请稍后再试!

终端测试命令:

md5 -s "string" #这是 Apple 用的 openssl 标准进行的MD5加密

MD5 使用场景,百度搜索引擎 (拆词搜索思路) 运用 以及百度云盘文件识别运用

搜索引擎的拆词搜索 && 词库

无论搜索 Apple Blue Sky, 还是搜索 Sky Blue Apple, 得到的返回结果是一样的。

原理

先计算各个单词的 MD5

  • MD5 (“Apple”) = 9f6290f4436e5a2351f12e03b6433c3c
  • MD5 (“Blue”) = 9594eec95be70e7b1710f730fdda33d9
  • MD5 (“Sky”) = 03462a41aec357b74c89eb8d272532f7

然后再对 MD5 值进行按位相加,得到的结果是一样的。

再去搜索匹配结果的数据。

散列碰撞:两个不同的数据,哈希之后,得到相同的哈希值!

从理论的角度出发,有无限个碰撞可能!

MD5 32 为字符,它能表达的数据个数是有限的,而被加密的数据是无限个。

SHA512/

其他使用场景

通过数据的散列值,判断数据是否相等,保存云盘数据(相同的数据在云上保存一份)。

正版软件使用哈希进行文件识别。

对下载后的软件安装版进行 MD5 校验,判断安装包是否被污染。

欢迎关注我的其它发布渠道