当我们开发金融、国企、政府信息系统时,不仅要符合网络安全的等保二级、等保三级,还要求符合国密的安全要求,等保测评已经实行很久了,而国密测评近两年才刚开始。那什么是密码/国密?什么是密评?本文就关于密码/国密及应用进行基础的知识梳理、记录。

01、密码(国密)算法有哪些?

国产化替代大家应该都熟悉了,为了应对日益复杂多变的国际形势(丑国),保障我们的IT技术自助可控,从硬件到软件,都在进行着国产化替代。密码领域也不例外,国密就是用来代替国际密码的。先来了解下密码的分类,及对应的国密算法。

🚩国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,在一般信息化系统开发中主要使用公开的SM2(非对称)、SM3(摘要)、SM4(对称)三类算法。

Base64是一种编码格式,并不属于加密,常用于数据传输、兼容性问题。Base64编码本质上是一种将二进制数据转成文本数据的方案,将一些不适合传输的数据内容进行编码来适合传输。

1.1、对称加密(DES/AES⇒SM4)

🔸基本特点:

同一个秘钥进行加密、解密。因此秘钥的保密性就很重要,不能泄漏。

计算量小、效率高。

🔸应用场景:

数据加密存储。

加密通信,如HTTPS、SSL、VPN,会与其他加密算法混合使用。

1.2、非对称加密(RSA/ECC⇒SM2)

🔸基本特点:

密钥配对:一个私钥、一个公钥,用私钥加密,用公钥解密。注意每一个密钥对都是独一无二、天生一对的,只能配对的秘钥加密、解密。简单来说,公钥加密的数据,只能配对的私钥才能解密。

安全性高,但计算量大。

基本原理:利用某一数学公式,正向计算容易,反向推理则非常难。

🔸应用场景:

HTTPS、SSH协议,如Git的ssh认证。

HTTPS的安全传输就是混合了非对称加密、对称加密,非对称加密协商会话秘钥,用会话秘钥对称加密传输数据。

敏感数据的加密传输,如客户端登录时传输用户名、密码信息时,采用公钥加密数据,服务端私钥解密。

对数据进行签名、验签,保障数据的完整性,同时验证身份。

1.3、散列(摘要/哈希)算法(MD5/SHA⇒SM3)

🔸基本特点:

无需秘钥,“加密”后的数据不可逆。所以这也不算是“加密”,一般称为哈希(Hash)。

任何长度的数据生成的哈希值长度都固定。

相同数据每次生成的哈希值相同,不同的数据则不同。

🔸应用场景:

数据摘要/哈希,验证数据是否被篡改、或数据丢失,保障数据的完整性、不可篡改性。

单向加密保存数据,如密码的保存,密码的存储普遍都是存的哈希值,登录时比较其hash值即可。

🔸彩虹表破解:由于散列算法的特点(同一数据生成哈希值始终一样),如果存储了大量(海量)字符内容的哈希值,就很容易进行查询破解了,这就是彩虹表,暴力破解也是一样的道理。常用的6位数字密码是相当容易破解的,如CMD5这个网站就利用存储的大量密文字典,反向查询破解。怎么解决呢?

提升散列算法的安全性,常用方法就是加“盐”,核心思想就是在哈希过程中添加一些自定义的内容、规则,仅自己知道,从而避免被字典破解。

最简单的比如在密文中某一位置添加一串随机字符,只有自己知道,使用的时候去掉干扰字符即可。

加盐的具体方式很多,可以完全自己DIV,常用的一种模式如下图,加盐+双重哈希。

如果加盐的规则被窃取了,对于现代的硬件还是挺容易被破解的,只能设置尽量复杂的密码+定期更换了。

📢实际应用中,可能会多种加密算法组合使用。

比如HTTPS的安全数据传输就是同时用了对称加密、非对称加密,用非对称传送(动态)密钥,对称加密传输数据。参考《HTTP协议图文简述》

对一个数据进行多重加密,以防被破解。

02、什么是国密?

为了保障国家信息安全、自主可控,我国制定了自己的密码法律、法规,及配套的密码算法。《中华人民共和国密码法》中将密码划分为核心密码、普通密码和商用密码。

核心密码、 普通密码属于国家秘密,商业系统都不涉及。

商用密码用于保护不属于国家秘密的信息,公民、法人和其他 组织可以依法使用商用密码保护网络与信息安全,一般开发中接触更多的是商用密码。企业(民企、国企)系统、政务系统用的都是商用密码。

📢2018年2月,密标委发布了GM/T 0054-2018 《信息系统密码应用基本要求》简称国密0054标准,也是我们常说的国密标准。该标准中对信息系统各项(密码)安全制定了标准依据。因此,当我们开发金融、国企、政府信息系统时,越来越多的系统会要求符合国密标准。

2.1、国密标准

国密的安全技术要求如下图,从硬件、网络到系统、数据全方位的加密安全要求,对于软件系统开发而言就是数据传输、数据存储的加密,主要涉及SM2、SM3、SM4、SM9。

对于WEB应用,数据传输加密还是基于HTTPS协议,只是加密算法全面要替换为国密。这方面已经有比较完整的解放方案了,服务端用国密版Nginx(得益于开源的Nginx)。客户端用国密版的浏览器,如360的国密版浏览器、零信浏览器,基本都是基于chrome内核,内置了国密算法、国密CA。

对于数据加密,就主要是SM2(非对称)、SM3(摘要)、SM4(对称)三类算法了,替换掉以前常用的RSA、MD5、SHA算法。

2.2、还有密评?

做过国企、政府项目的都知道,系统都是要过安全测评(等保三级),对于密码现在也有了密评,就是评价系统是否符合国密安全要求,评测通过才能上线,没通过的系统就得改造升级了。

🥷🏻密评对象:关基(关键信息基础设施)、等保三级及以上系统、国家政务系统,密评频率为每年至少一次。

基础信息网络:电信网、广播电视网、互联网。

重要信息系统:能源、教育、公安、测绘地理信息、社保、交通、卫生计生、金融等涉及国计民生和基础信息资源的重要信息系统。

重要工业控制系统:核设施、航空航天、先进制造、石油石化、油气管网、电力系统、交通运输、水利枢纽、城市设施等重要工业控制系统。

面向社会服务的政务信息系统:党政机关和使用财政性资金的事业单位和团体组织使用的面向社会服务的信息系统。

密评的实施过程:方案评估》系统测试》定期检查,密评的执行是由专门的密评机构(公司)进行的。

03、开源密码库

对于国际加密算法是已经很成熟了,有很多开源的库,一些语言框架还内置了。但国密算法的开源库虽然没那么丰富,也基本够用了。

名称描述github

crypto-js

MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列 AES、DES、Rabbit、RC4、Triple DES 对称加解密

star=14.5K/fork=2.5K

JSEncrypt

非对称RSA加解密,只支持浏览器,不支持Node

star=6.3K/fork=2K

node-rsa

支持Node运行的RSA加解密库

star=1.3K/fork=211

Web Cryptography API

W3C制定的密码规范API,主流浏览器、Node15都已支持

opensm

开源国密SM2/SM3/SM4算法,基于GmSSL,基于OpenSSL1.1.0,7年前(老)

star=9/fork=1.5K

TencentKonaSMSuite

腾讯开源的国密套件SDK(Java)

star=191/fork=41

sm-crypto

国密算法sm2、sm3和sm4的JavaScript实现,有关联java版

star=576/fork=233

gm-crypto

国密算法sm2、sm3和sm4的JavaScript实现

star=135/fork=43

✅sm-crypto-v2

国密算法 sm2、sm3 和 sm4 的 JavaScript 实现

star=5/fork=223

GmSSL

北京大学国密开源库,包含多个版本Java、JS、PHP、Go...,没有npm包

star=4.1K/fork=1.5K

Tongsuo 铜锁

阿里开源的综合性基础密码库,功能比较全

star=724/fork=133

JSEncrypt的示例代码如下,使用很简单:

🚩秘钥有很多生成方式,如OpenSSL,下面示例用了在线小工具:在线生成公钥私钥对,RSA公私钥生成

国密的使用:sm-crypto-v2

npm install --save sm-crypto-v2

哈希sm3:结果值的长度为固定的256Bit = 32个字节 = 下面结果为64个字符。

import { sm3 } from 'sm-crypto-v2'

// 哈希算法,

console.log(sm3('123456')) //207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb

console.log(sm3('test')) //55e12e91650d2fec56ec74e1d3e4ddbfce2ef3a65890c2a19ecf88a307e76a23

console.log(sm3('admin')) //dc1fd00e3eeeb940ff46f457bf97d66ba7fcc36e0b20802383de142860e76ae6

比特(Bit):最小的二进制长度,值为0/1

字节(byte):8个二进制位,即 1 字节 = 8Bit

16进制字符每个字符的长度是4比特,刚好 2^4=16

非对称加密sm2:(sm2也可以用于数字签名)

import { sm2 } from 'sm-crypto-v2'

// 1.生成秘钥对(公钥、私钥)

const { publicKey, privateKey } = sm2.generateKeyPairHex()

console.table({ publicKey, privateKey }) // 公钥长度130位,私钥长度64

// 2. 加密

const encrypted = sm2.doEncrypt('123456', publicKey)

console.log(encrypted) //长度204,基于内容

// 3.解密

const decrypt = sm2.doDecrypt(encrypted, privateKey)

console.log(decrypt) //123456

参考资料

国密SSL实验室 https://www.gmssl.cn/

国家密码管理局-密码规范

前端加密·国密算法

密评专题 | 一文读懂“密评”实施流程

NodeJS下基于国密的JWT实现