RSA & HASH

580 阅读10分钟

RSA & HASH

从苹果生成csr文件的步骤

  • iOS 没有办法使用pem进行加密解密的,使用的话需要在钥匙串访问中创建
  • 创建CSR文件 请求文件

16228811349880.png

WeChatf127d41806179cef074f47ae53c0fb46.png

WeChat92250c0ca6046b9ad0ac127b4a6fedf1.png

WeChat2e31f94251514d1e6074d35796527c53.png

通过openssl生成证书的步骤

  • 请求csr文件

    • 会填写一些组织的信息
    • 通过自己创建的私钥(private.pem)生成请求文件,在到签名机构去签名
    • 像https的证书也是一样的
    • 签名就是证明这个证书是合法的
    • 创建rsa的三个人创建了一个公司,成立了一个专门签名的机构,通过签名赚钱
    • 自己也可以签名 就是没有认证

WeChat106578c4a77ea845c34e8e03cccae9e6.png

WeChatf86301839819d8869f1a266d02375eac.png

请求csr文件的命令

openssl req -new -key private.pem -out rsacert.csr
  • 签名

    • 签名命令

      openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
      
    • 签名的结果

    WeChat7431f73a97e015a9f20f3da13691dee0.png

    • crt的最大用途。比如做https的请求,放到公司的服务器,需要别人接收
    • crt的内容 WeChat64d563dba5d5f947ac9e5eb3551c386e.png
  • 将crt转换为可以使用的 我们从苹果哪里拿到的就是这个

    • crt 转der命令

      openssl x509 -outform der -in rsacert.crt -out rsacert.der
      
    • 转换的结果
      WeChat43cfc79207ab464f5bd6131800508ca9.png

    • 拿到der之后,就可以在钥匙串访问中绑定一个密钥

  • 转换为p12文件

    • 命令

      openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
      
    • 转换的结果 需要输入密码
      WeChatb2c0279ff348f12ac7877df109183bcf.png

    • p12文件和der文件是一对的 有了这两个文件之后,在代码里面就可以做加密解密了 WeChatfee83850a8e4a9cf76d002462e87b2c4.png

总结 * private.pem是私钥 * public.pem 是公钥 * rsacert.csr 是请求文件 * rsacert.crt 是认证的证书 * rsacert.der 也是证书,只是转换了一下格式 * p12是私钥 * 最终通过rsacert.der 和 p12做加密和解密 代码里面只能用der和p12 * 加密和解密之后的文件都是二进制文件,iOS中就是NSData * 二进制文件没有办法去看加密之后的信息,为了展示二进制文件,会将二进制文件转码为base64

base64编码

  • 上面通过cat命令看到的就是base64编码的结果

  • 验证

    1. 创建message.txt文件
      WeChate8581135068e7b769f3c92c248783054.png

    2. 对文件进行编码 并查看内容
      WeChat4c2f40c2ec8d4f61c9f88b2488ba4139.png

    3. base64解码

      WeChatd8cc7eb1bdeea586a08ecbac1089c354.png

  • 原理 0~9 a~z A~Z + / = 65个字符组成的文本 维基百科Base64

  • 文本Man的base64编码 WeChat27a329c1ba5bd43c2da03f77c078a179.png

  • 通过上面的索引可以查表

    WeChatb6ee06876c2480eee52404dcf88ff67c.png

  • 如果只有两个字符,只有16个二进制位。16除以6除不尽,通过在空位补0,而且只在后面补0

    WeChatdabf51935b58231a08b222b9c77fab31.png

  • iOS中使用base64编码解码

    WeChatd6ab8a86bb9c3c2f4c8e60dbb436c9a4.png

总结 * base64就是对二进制以查表方式编码解码 * 只适用于表示二进制文件 比如hash值 加密的结果 * 编码之后文件会变大 所以不适合对大型的数据编码解码

RSA加密

  • 加载公钥私钥和加密解密
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1 加载公钥
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert" ofType:@"der"]];
    
    // 2 加载私钥
    [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p" ofType:@"p12"] password:@"123456"];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    // 加密
    NSData *result = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
    NSString *base64 = [result base64EncodedStringWithOptions:0];
    NSLog(@"加密的结果 %@", base64);
    
    // 解密
    NSData *jiemi = [[RSACryptor sharedRSACryptor] decryptData:result];
    
    NSLog(@"解密: %@", [[NSString alloc] initWithData:jiemi encoding:NSUTF8StringEncoding]);

}
  • 结果不一样是应为rsa中有一个填充模式
/*!
    @typedef SecPadding
    @abstract Supported padding types.
*/
typedef CF_OPTIONS(uint32_t, SecPadding)
{
    kSecPaddingNone      = 0,
    kSecPaddingPKCS1     = 1,
    kSecPaddingOAEP      = 2, // __OSX_UNAVAILABLE __IOS_AVAILABLE(2.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0),

    /* For SecKeyRawSign/SecKeyRawVerify only,
     ECDSA signature is raw byte format {r,s}, big endian.
     First half is r, second half is s */
    kSecPaddingSigRaw  = 0x4000,

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD2
       hash; standard ASN.1 padding will be done, as well as PKCS1 padding
       of the underlying RSA operation. */
    kSecPaddingPKCS1MD2  = 0x8000, // __OSX_DEPRECATED(10.0, 10.12, "MD2 is deprecated") __IOS_DEPRECATED(2.0, 5.0, "MD2 is deprecated") __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE,

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD5
       hash; standard ASN.1 padding will be done, as well as PKCS1 padding
       of the underlying RSA operation. */
    kSecPaddingPKCS1MD5  = 0x8001, // __OSX_DEPRECATED(10.0, 10.12, "MD5 is deprecated") __IOS_DEPRECATED(2.0, 5.0, "MD5 is deprecated") __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE,

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1
       hash; standard ASN.1 padding will be done, as well as PKCS1 padding
       of the underlying RSA operation. */
    kSecPaddingPKCS1SHA1 = 0x8002,
    
    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA224
     hash; standard ASN.1 padding will be done, as well as PKCS1 padding
     of the underlying RSA operation. */
    kSecPaddingPKCS1SHA224 = 0x8003, // __OSX_UNAVAILABLE __IOS_AVAILABLE(2.0),

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA256
     hash; standard ASN.1 padding will be done, as well as PKCS1 padding
     of the underlying RSA operation. */
    kSecPaddingPKCS1SHA256 = 0x8004, // __OSX_UNAVAILABLE __IOS_AVAILABLE(2.0),

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA384
     hash; standard ASN.1 padding will be done, as well as PKCS1 padding
     of the underlying RSA operation. */
    kSecPaddingPKCS1SHA384 = 0x8005, // __OSX_UNAVAILABLE __IOS_AVAILABLE(2.0),

    /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA512
     hash; standard ASN.1 padding will be done, as well as PKCS1 padding
     of the underlying RSA operation. */
    kSecPaddingPKCS1SHA512 = 0x8006, // __OSX_UNAVAILABLE __IOS_AVAILABLE(2.0),
};

kSecPaddingNone 不填充 秘文不变 其他的会变化

RSA的应用场景之一

  • 服务端(公钥) 客户端(私钥)
  • 手机安装app的时候,自带公钥
  • 服务端会定期更新下发到客户端的对称加密的密钥(key)
  • 公钥和私钥对密钥进行解密和加密
  • 密钥对传输的数据进行加密解密
  • 公钥也可以下发更新

RSA的应用场景之二 签名

Hash

常见的Hash算法

  • md5
  • sha1 sha256 sha512

常见的对称加密

  • DES
  • 3DES
  • AES 苹果用的就是这个 也叫做高级密码标准 美国安全局也是用这个

Hash的特点

  • 算法是公开的
  • 对相同数据运算,得到的结果是一样的
  • 对不同数据运算,如MD5得到结果默认是128位,32个字符(16进制标识)
  • 没法逆运算
    • hash的结果是有限的,但是数据是无限的,必然有两个或者多个数据有相同的hash值,也就是散列碰撞
  • 信息摘要,信息"指纹",是用来做数据识别的

Hash的用途

  • 用户密码的加密
  • 搜索引擎
  • 版权
  • 数字签名

用户密码的加密

  • 原则
    • 网络传输数据/本地保存数据(隐私数据) 不能明文
    • 服务端也不能保存明文密码

PS 公司的秘密泄露,都会承担相应的法律责任

  • 密码加密方式

    • RSA加密密码
      • 优点: 网络上泄露的可能低
      • 缺点
        • 服务端保存的是用户的真实密码(明文密码) 服务端的数据泄露了,存在安全隐患 (开发者最好不知道密码,最好使用hash)
        • 私钥和公钥对开发人员是开放的,开放人员可能会携带离开公司,存在隐患,而且更换用户的公钥成本比较大
    • Hash加密
      • 客户端 传输 和 服务端都不知道明文密码 更安全
  • Hash使用

    • md5
    • 加盐
      • md5(密码 + salt) salt就是一段固定的复杂的字符串
      • 逻辑设计 客户端/服务端配置,在注册的时候,将加密后的hash发给服务端,服务端将hash值保存在服务端,和账号保存在一起。再次登陆的时候,就将hash发给服务器,验证用户
      • 盐可能被开发者带走,不能用固定盐
    • HMAC加密
      • 服务端下发key, 客户端hmac做两次散列,一个账号一个key

      • 特点

        • 服务端下发key key就是不固定的salt
        • 客户端hmac做两次散列
        • 一个账号一个key
      • 注册流程

        • 发送账号到服务端,检测是否有用户注册 比如账号hankv587
        • 没有注册,服务端下发key和hankv587绑定在一起,将key下发给客户端
        • 客户端拿到key之后,输入密码,进行hmac加密
        • 将加密之后得到的hash值发送给服务端,服务端进行保存
        • 每次登陆的时候,都会将key下发
        • key比较小,可以使用RSA加密
        • 换手机之后,key重新下发。没有key说明不是授权登陆
        • 很多的app,授权登陆
        • 本地保存key最好使用钥匙串访问 钥匙串访问既可以是明文也可以加密
        • 更换密码的时候,再次输入密码,可以更换key
        • 钥匙串访问存入是加密,取出是解密
        • 更换key时,先输入密码,拿到原始的key做验证,验证通过更新key,客户端收到key,服务端更新key
      • 密码安全了,但是黑客可以模拟用户拿到hash值,再进行登陆

      • hash + 时间戳

        • 原始的登陆方式不变
        • 验证的方式变了 ((HMAC哈希值)+202006052134).md5 时间精确到分钟 是服务端下发的
        • 服务端((HMAC哈希值)+202006052135自己的时间).md5 验证没有通过
        • 服务端再验证上一分钟((HMAC哈希值)+202006052134自己的时间).md5 通过了
        • 黑客破解必须在59秒 登陆和授权都相对安全
        • 时间戳自定义 时间戳也可以RSA加密

搜索引擎

  • 比如 搜索 词库 iOS 长沙 Hank/长沙 iOS Hank
    • 计算每个词的hash值
      • MD5 ("iOS") = 1bdf605991920db11cbdf8508204c4eb
      • MD5 ("长沙") = 6b357589b12f6141fc48c4b0375ef2f9
      • MD5 ("Hank") = ba02b1e3410f72ad50c76f9c144d6b3
    • 将hash相加
      • 1bdf605991920db11cbdf8508204c4eb + 6b357589b12f6141fc48c4b0375ef2f9 + ba02b1e3410f72ad50c76f9c144d6b3
    • 次的顺序变化 结果值不变
  • 版权
    • 任意一个文件都能生成一个hash 上传一个愿文件,都会生成一个hash值
    • 但是用户下载,比如图片、视频,里面会加一些东西,内容是一样的,但是和原始文件不一样
    • 网盘 数据识别用的就是hash

数字签名

为什么用签名这个词.因为老外喜欢用支票,支票上面的签名能够证明这玩意是你的.那么数字签名顾名思义,就是用于鉴别数字信息的方法

  • 目的是验证这个二进制数据是不是原始的,是不是颁发机构颁发的
  • 用什么样的技术识别数据的真假?
    • Hash
  • 数据 + 数据的hash值
    • 收到数据的一方,会通过同样的算法,计算数据的hash值,并和收到的hash比较,如果不相同,说明数据被更改了
    • 但是hash值也一起被修改,验证就会通过
  • 数据 + RSA(数据的hash值)
    • 收到数据的一方,通过RSA解密,拿到数据的hash值
    • 通过相同的hash算法,计算数据的hash值
    • 比较两个hash值,如果不相同,说明数据被修改了 验证不通过
    • 传输的时候,hash不会被修改
  • 通过RSA加密数据,叫做数据签名
    • RSA(数据的hash值)成为原始数据的数据签名
  • 数字签名用途非常广泛 支付宝 各大银行 支付平台,iOS的签名验证
    • iOS的签名验证是代码签名
    • 数字签名签名的是数据
    • 本质上是一样的

总结

  • RSA终端的代码、RSA代码演示。
  • RSA的特点
    • RSA安全系数非常高 (因为整个业务逻辑非常安全 )
    • 加密效率非常低 (不能做大数据加密)
    • 用来加密关键数据! 例如加密hash值、hmac的key
  • Hash
    • 算法公开
    • 不可逆运算
    • 相同的数据结果相同
    • 不同的数据长度相同
    • 一般用户数据的识别 (密码、版权、百度云数据的识别)
  • Hash用途
    • 密码加密
      • MD5直接加密
        • 可以被反查询
      • 加盐 固定的盐有安全隐患
      • HMAC 通过动态的key来加密数据
        • HMAC(比较好的方案)
        • HASH + 时间戳 这样的方式 每次加密结果不一样 受时间的影响比较大
  • 数字签名
    • 算法: RSA + HASH
    • 目的:验证数据的完整性 不被篡改
    • 逻辑:
      • 1 数据报文 原始数据
      • 2 原始数据的HASH值
      • 3 原始数据的HASH值通过RSA得到结果 (数据签名)