对非对称加密的再思考

概述

所谓非对称(Asymmetric)加密,就是一种使用两个密钥,来对信息进行加密和解密计算的算法体系。从其名称我们就可以理解,和对称加密体系中,加密和解密过程使用同一个密钥不同,非对称加密在加密和解密过程使用不同的密钥。这个特性,可以很好的解决加解密过程中,密钥共享和交换的问题,从而大大提高信息计算和处理的安全性。

非对称加密的密钥都是成对出现的,称为公钥(Public Key)和私钥(Private Key),公钥和私钥之间,其实是具有某种数学的关联关系,让其可以用于加解密算法当中。其中公钥是公开的,任何人都可以获取,通常使用公钥用于加密数据或验证数字签名;而私钥是保密的,只有密钥的拥有者知道,私钥用于解密数据或生成数字签名。

基于非对称加密的基本概念,在具体的实现路径上,还有不同的技术体系,如现在主流的非对称加密技术大体包括RSA和ECC两个大类。RSA算法的理论基础主要基于大数分解的数学难题;而ECC则是椭圆曲线上离散对数和点计算。它们的基本概念都是一种计算,在一个方向上可以非常简单和快速,而却很难从计算结果来推导输入的参数(最容易理解的就是两个非常大的素数相乘)。在早期由于RSA的概念清晰实现简单,相对应用比较广泛,但后来ECC具有安全性更强,相对密钥更小,计算性能更好等特性,已经逐渐成为主流的非对称加密体系。在基础技术框架和要素来看,其实这两大体系的实现和应用并没有太大的区别,比如都有公钥和私钥,有密钥对生成过程,都可以支持加密解密、签名验证等操作,都支持密钥协商等等,只是相关的参数和选项略有差异。

本文的主要目的并不是讨论一般的非对称加密的设计和实现,那样的材料和信息已经非常丰富了。而是笔者想要结合一些应用的经验,深入研究笔者在应用非对称加密过程中的一些问题,并提出一些想法和进行实践,能够更好的提升加密应用以至于信息安全方面的认知,从而有能力设计和改进现有的信息安全体系。

非对称加密的一般过程

笔者想要从非对称加密计算的一般过程入手。非对称加密一般应用过程和操作包括:

  • 密钥对生成

在进行非对称加密之前,需要先生成密钥对。然后使用密钥对对信息进行加密和解密的操作。密钥对由公钥和私钥构成,它们由数学关系保证其是严格对应的,其中私钥应当由生成方进行保密存储和使用;而公钥可以对外公布和分发。

在大多数应用场景中,私钥的生成是相对固定的,它在生成之后,就以机密信息的形式,保存在持久化存储(比如一个文件或者配置信息中)中,然后在应用系统中加载使用。一般没有特别的原因,不需要保存公钥,因为可以很容易从私钥计算得到。

现代计算机技术的发展,使这个密钥对生成的操作已经变得非常简单和廉价,一般情况下是完全可以实时操作的,受到的限制主要是管理和应用方面的,作为开发者不用太担心这个计算性能的问题。而且,随机生成和应用密钥对,也可以大幅度提升信息处理过程的安全性。

  • 公钥加密

公钥加密,是最简单直观的应用场景,用于对传输的信息进行加密。如果A要向B传输数据,它需要先获取B的公钥,然后使用B的公钥对信息进行加密。加密后向B传输加密数据。B收到数据后,使用自己的私钥(和公钥配对的)就可以对加密后的信息进行解密了。由于这个密文,只能通过私钥进行解密,没有共享密钥的交换过程,就可以保证过程和操作的安全性。

公钥加密的主要问题是如果仅使用公钥进行加密,由于加密机制的限制,和对称加密相比,公钥加密和私钥解密的效率比较低,不适合处理比较大的信息。

  • 私钥加密

刚开始接触私钥加密的开发者可能会感觉到很奇怪。私钥加密,就是可以使用公钥进行解密,那为什么要给一个人人都可以解密的信息进行加密呢。

这是因为,非对称加密,除了信息的加解密之外,还有一个常用的应用方式,就是签名和验证,这恰恰是通过私钥加密来实现的。比如,A需要向B传输一个信息,A就可以使用私钥对这个信息进行加密;B收到信息后,可以使用A的公钥进行正确的解密,由于这个信息只能用A的公钥解密,就可以确定肯定是由A的私钥进行的加密,从而确定这个信息只能来源于A,就是所谓的签名和验证。

签名的目的在于实现信息的完整性和不可否认性。对信息进行签名,任何人都可以通过签名来验证这个原始信息是完整的,并且由于只能使用公钥来进行验证,就可以确保这个信息确实是使用签名者的私钥进行的签名,在逻辑上确保这个信息来自签名者。而且签名者还无法否认,因为如果验证成功,说明别人无法使用私钥生成原文对应的签名信息。

新的思考

上面就是非对称加密的一般应用方式和基础的认知。但原来笔者和普通的开发者一样,知道如何使用这个过程,但其实并没有进一步深入思考,它是如何实现的,以及如何能够进行改进,来适应更高的安全需求。在这方面笔者原来有两个疑惑:

  • 非对称加密的效率

前面已经讨论到,由于相对的数学原理和操作比较复杂。如果使用公钥加密,它的执行效率相对是比较低的,加密信息的规模也受到限制。这样其实对在实际业务应用中的限制是比较大的。

  • 签名验证的过程黑箱

一般情况下,所谓的验证,都是通过对于信息的对比来实现的。但私钥加密(签名验证)的一般实现却不是如此,而是直接通过输入相关的参数,由相关的算法函数给出验证通过或者不通过的结果,开发者基本无法干预这个过程,而且作为一个"黑箱"的功能,也不知道其具体的实现方式和原理,就更谈不上对这个过程进行干预或者改进了。

针对上面的疑问,笔者以Nodejs的Crypto模块为基础,通过分析和整理非对称加密的算法体系,笔者认为,除了底层的非对称加密密钥体系之外,其实在应用方面,如果要对非对称加密进行扩展的应用,其核心应该是密钥协商技术。

关于密钥协商(Key Exchange)

在密码学系统中,密钥交换(协商)并不是它的学术名词Key Exchange,而是Diffie-Hellman(DH)。这个命名充分展示了行业对于这两位算法发明人的尊敬,事实上,他们也由于在密码学方面的杰出贡献,获得了2015年的图灵奖,完全配得上以名字来命名算法的荣誉。

所谓的密钥协商,就是两对非对称加密的密钥,在不进行密钥信息的加密情况下,基于自己的私钥,和对方的公钥,可以在不交换其他信息的情况下,使用数学方式,计算出来一个新的密钥,这个密钥可以由数学算法保证,在双方是一致的,如下面的公式所显示的那样:(VK是私钥,PK是公钥,DH是密钥协商算法函数)

DH(VKb,PKa) = DH(VKa,Pkb)

和各种对称和非对称的加密算法一样,基于相同的理念,具体的DH算法实现也有很多种类型,开发者可以根据喜好和熟悉程度,选择适合自己和应用场景的实现算法和函数库。

公钥加密改进

基于以上思考,我们其实可以提出一种更高效的"公钥加密"的方案。实际上不是直接使用公钥进行加密,而是先使用双方的密钥对协商出一个密钥,然后使用这个密钥对原始信息进行对称的加解密操作。

其基本方法和过程是(假设由A向B发送信息):

  • A、B分别生成自己的密钥对
  • A获得B的公钥PKb
  • A使用DH,使用VKa和PKb,计算协商密钥NK
  • A使用pkdf2等衍生算法,计算临时密钥NKt
  • A使用NKt对信息进行加密(对称加密)
  • A向B传输公钥PKa、密文E和NKt的衍生参数
  • B收到A的公钥PKa、密文E和衍生参数
  • B使用DH,使用VKb和PKa,计算协商密钥NK
  • B使用pkdf2和衍生参数,计算临时密钥NKt
  • B使用NKt,对密文进行解密,获得原文

这个过程的优势在于:

  • 可以处理较大规模的信息,因为在一次信息传输过程中,结合使用非对称加密和对称加密,不受非对称加密性能较差的限制
  • 每次加密没有使用固定的密钥,而是衍生的随机密钥,提供更高的安全性
  • 双方可以随时更新密钥对,实现完全动态加解密
  • 真正的加密强度可以随时调整(通过增加对称加密密钥长度和实现方式)
  • 对于原始密钥的保护更安全(只使用衍生密钥)

私钥加密(签名和验证)的改进

在传统的非对称加密签名和验证的应用过程中,一般的密码学程序库完全隐藏了其实现的技术细节,这样也会影响到对其算法的改进和升级。比如做签名验证的时候,传入原始数据和签名信息,只能得到一个验证结果,内部的处理完全是封闭的。

笔者构想,如果是想要对这一过程进行改进或者定制,其实可以按照非对称加密的原理,来进行处理。其核心是引入一个"临时非对称密钥"。基本过程如下(预设的场景是A对B传输信息,A签名,B验证):

  • A生成或者加载自己的密钥对(PKa/VKa)
  • A生成临时密钥对(PKt/VKt)
  • A使用自己的私钥VKa和临时公钥PKt,生成协商密钥NK
  • A使用NK,对原始信息I,使用加密摘要算法(HMAC),计算加密摘要IM,作为信息签名的签名部分
  • A对临时私钥VKt进行编码,附加到签名后面,作为其密钥部分
  • A将签名信息传输给B
  • B收到原始信息I(也可能是解密得到)和签名,并获得A的公钥PKa
  • B从签名信息中,分离出IM和Vkt
  • B使用VKt和Pka计算协商密钥NK
  • B使用NK,对原始信息I,使用加密摘要算法(HMAC),计算摘要结果IM2
  • B比较IM和IM2,确定验证结果

这种过程和算法的优点在于:

  • 每次签名和验证,都使用一次性的临时密钥,生成的动态签名信息,提供更高的安全性
  • 临时衍生密钥,可以很好的保护原始密钥
  • 可选摘要算法的实现,可以动态和持续改进安全性
  • 可选加入自定义信息和验证过程,提供更高的业务灵活性
  • 临时密钥对和HMAC都可以快速计算,保证签名和验证的处理效率
  • 每个组成阶段,都可以改进和升级

所以,在这个实现中,真正的签名信息,包括算法、临时私钥和摘要计算结果。

参考实现和示例代码

根据以上的实现构想,基于Nodejs的crypto模块,笔者编写了下列示例和实验代码:

这个实现和代码的要点如下:

  • 密码学套件使用Nodejs标准的crypto模块
  • 相关配置信息详见配置常量
  • 摘要函数使用SHA256,长度为32字节
  • 对称加密方式为 chacha20-poly1305
  • IV长度为12(随机设置),TAG长度为16(加密计算得到),都由算法确定
  • AAD暂时使用随机信息,规格同IV,理论上可以使用任意附加数据
  • ECDH使用crypto.ecdh类,曲线类型secp521r1
  • 使用预制密钥作为私钥,可推导出对应公钥,生产环境可以考虑随机生成,或者使用更复杂的密钥
  • 签名使用临时随机密钥对,由ECDH对象生成
  • 在标准情况下,ECDH的私钥长度为32,公钥长度为133
  • 有趣的是,computeSecret的密钥长度是不定的(65或者66),所以需要trim到32字节,作为标准对称加密密钥

小结

本文从笔者对非对称加密应用的两个问题出发,提出了相关思考和改进方式,并编写了示例代码进行了测试和验证。

相关推荐
WINGZINGLIU2 小时前
HttpSevletRequest Body信息不能被多次读取的问题
java·后端·安全
搬砖的前端2 小时前
【uniapp蓝牙】基于native.js链接ble和非ble蓝牙
开发语言·javascript·uni-app
minstbe2 小时前
半导体数据分析(二):徒手玩转STDF格式文件 -- 码农切入半导体系列
前端·javascript·数据库
学习溢出2 小时前
【网络安全】掌握 Active Directory 攻防审计实操知识点
网络·安全·web安全·网络安全·渗透测试
Dachui_11222 小时前
如何在铁威马NAS上安装内网穿透,实现对铁威马NAS的远程访问管理
安全·云原生·eureka·云计算·远程工作·csdn开发云
.生产的驴2 小时前
SpringBoot 开启热部署 项目热启动 一键调试无需 无需重启
java·运维·开发语言·spring boot·后端·spring·eclipse
德迅云安全杨德俊3 小时前
云服务器防御DDOS的方案
服务器·安全·web安全·ddos
打码人的日常分享4 小时前
【系统测试文档】系统测试计划,系统测试报告书,测试方案,测试记录,测试用例(Word原件)
运维·安全·系统安全·测试用例·需求分析·规格说明书
我码玄黄4 小时前
JS设计模式之中介者模式
javascript·设计模式·中介者模式
xue03054 小时前
react自定义hooks函数
javascript·react.js