zoukankan      html  css  js  c++  java
  • 加密和签名方案

    场景一
    转账交易:
    假设我要做个转账的app叫支付宝,要完成转账的功能,转账时,需要输入对方支付宝账号和姓名,然后点击转账,输入支付密码,就可以完成转账的功能。
    实现方式,客户端通过http协议发送转账报文给服务端
    报文无加密和签名机制
    现在用户甲要转账给用户乙。
    安全隐患
    网络传输不安全,如果有人截取客户端请求报文,进行篡改,比如篡改收款方的支付宝账号和真实姓名,那么服务端就会把钱转到别的地方去。
    结论:需要防止报文被篡改
    场景二
    某商城A要接支付宝移动支付,大致流程:

    1. 客户端app调用支付宝的sdk发送支付报文
    2. 客户端接收支付宝服务端的处理响应
    3. 商户服务端接收支付宝服务端的交易成功通知
      客户端发送请求的安全隐患同场景一
      服务端接收通知时,存在如下隐患,黑客甲,去商城A
      人为模拟支付宝的通知报文,将订单变成成功。
      这是一个通知报文要做签名的案例
      需要注意的是,步骤2和3同样需要做签名验证
      结论:需要确认报文来自真实合法的服务端(其实在商户对商户的通信过程中,也需要确认报文来自真实合法的客户端)

    场景一和场景二的最终结论:

    1. 安全网络通信过程中,需要防止报文被篡改
    2. 安全网络通信过程中,需要客户端和服务端双方确认对方的身份,即交易完成后,不可抵赖

    方案一 对称加密签名机制
    具体方案:用一种对称加密算法将报文加密,并得出一个签名串
    举例:MD5加密签名,签名串=md5(原文&密钥)(其他对称加密算法签名道理是一样的,不做详述)
    假设最终的报文是:最终报文=原文&签名串
    此方案达到的效果:
    如果黑客截取报文,并篡改原文,那么服务端进行验签的时候,将不会通过。
    因为原文变化了,算出的签名串会改变,那么黑客需要重新计算出签名串
    要算出签名串,需要知道如下要素
    签名算法(包含加密算法),原文,密钥
    前2个肯定是会暴露的,无法保密,而客户端是app,密钥也是暴露的,所以签名串会被重新计算出来,因此黑客将成功篡改转账报文。
    方案二 对称加密签名,动态密钥
    从方案一我们得出一个结论:
    签名算法(包含加密算法),原文,密钥三者只要保证其中一个不被黑客截取,将无法算出签名串,也就无法篡改报文。
    那么我们可以动态生成签名的密钥,并用rsa公钥对其进行加密(此处rsa私钥在服务端,不会泄密,因为签名密钥不会被解密),然后传至服务端
    次方案用于场景一,可以解决报文被篡改的问题。
    但是服务端就无法确认客户端是否合法,尤其在机构与机构通信的时候,这个方案就更不可取。
    且次方案不适合于方案2,支付宝服务端发通知的时候,总不能动态产生密钥,这样你就无法判定报文是否是支付宝服务端发送来的。
    方案三 报文加密(对称加非对称)
    从方案一我们得出一个结论:
    签名算法(包含加密算法),原文,密钥三者只要保证其中一个不被黑客截取,将无法算出签名串,也就无法篡改报文。
    那么我们就采取对报文加密,可用方式是对称加密和非对称加密
    1.对称加密:3des
    签名串=md5(原文&密钥1)
    最终报文=3des密钥2&签名串
    传输过程中,报文是加密的,无法篡改(因为无法拿到用户关键信息,如session,tokenId等认证信息),看似没有问题,但是密钥1和密钥2都可能泄密,而且3des会被解密掉,所以又回到方案一的结果。
    2.非对称加密+对称加密:3des+rsa+md5
    那么我们可以从方案二吸取经验,用rsa密钥加密对称加密密钥
    签名串=md5(原文&密钥1)
    最终报文=3des密钥2|签名串|rsarsa公钥
    此方案仍然有方案二的缺陷,只能解决场景1,不能解决场景2
    原因在于签名的密钥,服务端和客户端是一样的,无法产生唯一性身份
    我们需要用rsa来签名

    方案四 rsa签名+https
    报文加密是必须的,那么我们用https加密,其原理同非对称加密+对称加密
    场景一方案:
    客户端产生一对公私钥 pubKey_c,priKey_c
    服务端产生一对公私钥 pubkey_s,priKey_s
    客户端与服务端置换公钥
    最终持有情况如下:
    客户端:pubkey_s,priKey_c
    服务端:pubKey_c,priKey_s
    客户端发送报文:
    签名串=rsapriKey_c
    最终报文=https(报文原文+签名串);
    场景二,相对于场景二
    服务端用pubKey_c做验签,
    产生效果:客户端私钥priKey_c没有被盗取时,可以防止报文被篡改,且服务端可以确认信息来自合法的客户端,在机构与机构通信时,次种假设是成立的。
    客户端是app, 客户端私钥priKey_c会被盗取,不能保证客户端的合法性(即客户端可以不是官方提供的),但仍然可以防止报文被篡改。
    服务端响应报文时:
    签名串=rsapriKey_s
    最终报文=https(报文原文+签名串);
    产生效果:因为服务端的私钥priKey_s在理论上是不会泄密的,所以可以保证响应报文不会被篡改,且来自真实合法的服务端
    场景二方案:
    支付宝服务端发送报文:
    签名串=rsapriKey_s
    最终报文=https(报文原文+签名串);
    客户端用pubkey_s来验签即可,可保证,报文不会被篡改,且来自真实合法的服务端

  • 相关阅读:
    FastJson---高性能JSON开发包
    mybatis中大于等于小于等于的写法
    MarkDown 使用说明示例
    Get和Post的参数传值
    规则引擎 资料收集
    ORA-01033错误解决方案
    mybatis 参数为String,用_parameter 取值
    php中实现记住密码下次自动登录的例子
    php 应用 bootstrap-fileinput 上传文件 插件 操作的方法
    AJAX 跨域请求
  • 原文地址:https://www.cnblogs.com/tangyanbo/p/5062806.html
Copyright © 2011-2022 走看看