暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

新优特性之安全算法

开源中间件 2021-09-10
740

一 综述


Java语言是一个充分考虑了安全特性平台,在设计之初就有沙箱模式,针对互联网和嵌入式应用场景。


JDK中划分为几个大的安全功能点:

  • 平台安全,如强类型,自动内存管理,字节码校验,安全类加载等。这部分是Java语言规范定义的。

  • 加密技术,提供各种加密能力,如数字签名,消息摘要,加密算法,消息验证码,密钥生成等。属于JCA和JCE技术规范内容。

  • 认证和访问控制,如登录认证和扩展机制,资源的权限赋予。属于JAAS技术,也是JavaEE安全的基础。

  • 安全通信,提供了网络数据传输的安全API和实现,如TLS,SASL等。属于JSSE技术。

  • PKI公钥基础设施,提供了工具来管理密钥和证书,支持证书库,过期策略等。


Java的版本更新,安全特性是版本升级的主力,很多小的版本变化,都是加强安全补丁。

在Oracle的网站上,提供了详细的安全补丁说明,如https://www.oracle.com/technetwork/topics/security/alerts-086861.html

另外每个版本发布时的release note,也会给出安全方面的详细说明。


从JDK 7到JDK 11,Java一直在不断的改进和完善安全功能。

  • JDK7,加入了TLS1.1和TLS1.2支持(其实在JDK6后续版本就提供TLS1.2支持,但不是可以公开下载版本)

  • JDK8中,AES算法运算可以利用CPU能力,提供AEAD密码套件,支持SHA-224消息摘要算法等

  • JDK9安全特性就更多了,提供了DTLS即数据传输加密,PKCS12成为证书库默认格式,ALPN协议协商扩展,GHash和RSA的CPU硬件支持,安全随机数基于DRBG实现,SHA-3消息摘要,这个版本中SHA-1被禁用了。

  • JDK10中,OpenJDK中的证书也内置了根证书

  • JDK11中,实现了最新的TLS1.3功能,加入ChaCha20-Poly1305流式加密算法等。


安全是现代互联网和企业应用非常重要的功能,所谓安全无小事。


二 加密算法


密码的算法按照不同方面可以分为很多种类,这里以加密方式和作用来分类阐述。


1. 消息摘要算法


消息摘要用于数据完整性校验。任何消息经过散列函数处理之后,都会计算得到唯一的散列值。如果被校验的数据中有哪怕一点儿变动,生成的散列值都会有非常大的不同。


散列值最常见的应用就是验证下载包的完整性了。我们经常在下载软件路径下,如某个Linux发行版的iso文件,可以看到有对应的散列字符串。通过用工具计算软件的散列值并比较,就可以验证下载的软件是否完整,有没有被篡改。


常见的摘要算法有MD,SHA等大的分类。

  • MD5是之前最常用的,但很早以前就不安全了,现在只用作一般文件的完整性验证。

  • SHA是目前使用的主力,比如在Maven仓库中,每个jar包都会对应一个sha1文件,用来记录jar包的散列值信息。SHA算法是MD之上改良而来的,摘要长度更长,安全性更高。被广泛使用的SHA-1算法在2005年就被山东大学的王小云教授提出了碰撞算法,但计算量巨大。到了2017年2月,Google公司利用其强有力的计算资源,构造出SHA-1碰撞实例。从此SHA-1被认为不再能信任的安全算法,JDK9中就被禁用了。


当前我们使用SHA-2(SHA-256,SHA-224等)甚至SHA3,来完成散列计算。使用较多的是SHA-256算法,对于任意长度的消息,都会产生一个256 bit长的哈希值。


2. 对称加密算法


对称加密的意思是加密解密都使用同一组密钥,是应用时间最长,范围最广,频率最高的加密算法。


按照加密方式分为流密码和分组密码,分组密码工作模式又可以分为ECB,CBC,CFB,OFB,CTR等,一般来说,密钥长度决定了加密算法的安全性。


对称加密算法之前的标准是DES算法,因为密钥偏短只有56位,安全性受到严重威胁,而且还是半公开的算法。后来衍生出DESede(3DES三重DES算法),增加了安全性。后来国际范围内公开征集算法方案,经过一番竞争后,AES成为替代者。


目前采用最广泛的是AES(Rijndael)算法,支持128,192,256位的密钥长度,具有很高的安全性。

在Java7以前,JRE中有安全限制,如果需要使用位数长密钥算法,需要获得无限制策略文件,目前JDK中已经没有这个限制。


JDK8中加入AES利用CPU对于加解密能力的指令集功能,这样利用硬件能力,性能可以达到8倍。


JDK11加入ChaCha20-Poly1305流式加密算法,是ChaCha20流密码和Poly1305消息认证码(MAC)结合的一种应用在互联网安全协议中的认证加密算法,由Google公司针对ARM架构为Android移动操作系统中Chrome设计的,对于移动终端来说,有很高的效率,具有算法精简、安全性强、兼容性强等特点。

有一些网站做了优化,对于PC访问使用AES算法,而对于移动应用访问,就使用ChaCha20-Poly1305算法。


3. 非对称加密算法


对称加密算法中,加解密使用同一个密钥,这样就存在较大的非算法安全隐患,如果密钥被破解了,以及密钥的传递中被敌对方获得,那么信息内容就泄漏了。

而非对称加密算法采用公钥私钥两个密码,公钥是公开的,每个人都可以获得,而私钥需要自己妥善保存。

这两个密钥,一个用于加密,另一个用来解密。比如甲要给乙发送一段密文,甲就用乙的公钥进行加密,任何人截获这段密文也不知其含义,只有乙受到后,可以用手中的私钥进行解密。


非对称加密的算法,构成密钥基于数学算法,主要分成以下几种:


  • RSA算法是最典型的非对称加密算法,RSA分别是提出者,麻省理工学院的三位学者姓氏的打头字母。基于大数因子分解难题,即两个大的质数相乘得到一个乘积非常容易,而反过来,把一个大数分解成两个大的质数却非常困难。目前Java提供了各种密钥长度的RSA实现,默认为1024位。在JDK9中,也利用CPU指令集进行的算法运算加速。

  • ECC(Elliptic Curves Cryptography)椭圆曲线加密算法,以椭圆曲线理论为基础,得到相同强度的加密能力所需要的密钥更小。JDK7中加入了ECC算法支持。

  • 密钥交换算法(Diffe-Hellman)用于安全的传递密钥,ECDH是基于椭圆曲线加密算法的密钥交换算法。从Java7开始,提供对ECDH算法的支持,默认密钥长度为256位。


4. 数字签名算法


我们在日常生活中经常要签名,表示对行为的认可,起到抗否认的作用。

数字签名就是利用软件实现的安全方式,目前法律已经认可,和手写签名具有相同的法律效力。


数字签名算法要求能够验证数据完整性,认证数据来源。数据的提供方可以对自己发送的数据进行签名处理,给出对应的签名作为凭证,数据接收方就可以想办法验证该签名是否有效。如果任何人或者机构都可以进行签名处理,那么签名就没有意义。签名是通过发送方的私钥进行加密,并且由权威机构进行认证并签发证书,接收方收到证书后,通过使用权威机构和发送方的公钥进行解密并查看,来验证证书的有效性。


对数据的签名,一般是对数据的原始信息做摘要散列处理,然后再签名,这样运算速度快多了。


数字签名算法分为RSA, DSA,ECDSA等,RSA之前有介绍,DSA和ECDSA都是源于离散对数问题,DSA是基于DSS的数字签名算法。DSA和ECC结合后就是ECDSA算法,目前是使用最广的签名算法。


5. 随机数算法


JDK中提供了随机数SecureRandom算法,随机数也是广泛应用于生活之中,比如银行转帐使用的短信验证码,如果这个码有章可循被破解,就无法起到随机验证的作用了。


JDK9提供了基于DRBG的随机数实现。随机数在生成过程中,种子非常重要,随机数种子发生器一般可以分成真随机数发生器(NRBG)和伪随机数发生器(DRBG)两类。

  • 真随机数发生器一般基于物理或化学熵源,比如原子运行轨迹、环境噪音、电路噪声,空气中颗粒数等等。

  • 伪随机数发生器一般只依赖软件算法实现,在确定输入(种子)的情况下,它的输出也就确定了。


在Java中软件实现了伪随机发生器,有纯Java实现的算法,以及在Linux上通过/dev/random实现的本地随机数种子发生器。


三 数字证书


数字证书(Digital Certificate)也称为电子证书,类似生活中的身份证件,用于标识网络中物件的身份。现实生活中,身份证件由公安机关颁发,网络中身份凭证由权威的数字证书认证机构(Certificate Authority, CA)签发,只有经过CA签发的证书才有可认证性。


数字证书采用了公钥基础设施PKI,使用了相应的加密算法确保网络应用的安全性:

  • 非对称加密算法对数据进行加解密操作,确保数据机密性

  • 数字签名算法对数据进行签名/验证操作,确保数据完整性和抗否认性

  • 消息摘要算法对数字证书做摘要处理,确保数字证书完整性


JDK提供了keytool工具对证书进行操作和管理证书。原来keystore文件是Java原生的密钥/信任库文件。JDK9以后,使用PKCS12(p12)格式,即个人信息交换语法标准,作为缺省格式,方便和openssl采用的pem格式进行导入导出。


keystore文件(truststore)文件中可以存放密钥和信任库,比如应用服务器可以设置环境变量指定密钥存放文件和信任库文件,用于和其他网站或者服务器进行安全通信。


OpenJDK10以后,证书库rootcert也不再为空,而是加入了国际上主要的权威证书机构。


四 TLS安全协议


目前我们常用的网站都使用https协议,就是基于SSL/TLS的HTTP协议。


SSL是安全套接字层Secure Socket Layer,由现代浏览器鼻祖Netscape网景公司研发,位于TCP/IP的网络传输层,作为提供安全和数据完整性的一种安全协议。


TLS传输层安全Transport Layer Security,是SSL的继任者,TLS1.0和SSL3.0几乎兼容。目前SSL已经都不建议使用,TLS1.0和1.1也已经过时,目前主要使用的是TLS1.2协议。


TLS涉及到多种加密算法,包括消息摘要算法,对称和非对称加密算法,密钥交换算法,随机数产生,数字签名算法。可以说前面所述的算法几乎都运用了。


TLS在通信之前有一系列的握手协议:

  1. 协商算法,服务器和客户端都确认可以使用的加密算法,SSL信息和随机数信息。

  2. 验证证书,客户端验证服务器的证书是否可信,认证机构是否通过证书可信性认证。如果为双向认证,则服务器也需要验证客户端的证书。

  3. 产生密钥,构建会话密钥,采用密钥交换算法来生成和交换会话密钥,这个过程用到了随机数,非对称加密算法。

  4. 加密交互,进入正式会话阶段后,客户端和服务器都采用生成的会话密钥,也是对称加密密钥来进行信息加密传递。


使用浏览器访问网站时,总是能看到地址栏有一个绿色的小锁,点击后可以看到证书和加密算法信息,比如某一个网站的连接加密信息为:

TLS_ECDHE_WITH_AES_256_CBC_SHA256,TLS1.2

就表示使用TLS1.2协议,采用ECDHE密钥交换算法,使用SHA-256摘要散列,通信加密方式为256位的AES算法,CBC填充模式。


JDK11加入了今年才通过成为技术标准的TLS1.3协议,TLS 1.3设计的首要目标就是避免之前版本存在的缺陷,相关的改动如下:

  • 禁止使用RSA密钥传输算法。

  • 禁止一些安全性较弱的密码原语如MD5的使用。

  • 不再支持重协商握手模式。

  • 握手消息采取了加密操作。

  • 实现了握手协议和记录协议的密钥分离。

  • 实现了会话密钥与整个握手消息的绑定。

  • 记录层只能使用AEAD(Authenticated Encryption with Additional Data)认证加密模式。



TLS1.3更快速,安全,更有效率。当然的普及使用还有一个过程,但HTTP2被广泛采纳会加快HTTPS的普及,也会提高新的TLS协议的使用率。


五 总结


Java语言对于安全的实现是全方位的,再辅以Bouncy Castle等三方库,能够完成绝大多数安全需要。当然目前比起操作系统C语言实现的库,功能上效率上还是逊色不少,但一直在不断完善,对于开发平台而言,JDK的安全性值得信赖。


文章转载自开源中间件,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论