开发者的密码学快速指南

密码学中的哈希(Hash)

哈希可以把任意给定的输入(任意长度的文本、数字)映射成为固定长度的输出(这个输出称作消息摘要,Message Digest)。

推荐的Hash

基于构造方法的不同,我们推荐开发者常用的哈希:

基于Merkle-Damgard构造的哈希

  1. SHA-2一族哈希函数:SHA-256,SHA-512
  2. 国密SM3

基于sponge构造的哈希

Keccak一族哈希函数:Keccak-256,SHA3一族哈希函数(SHA3-256,SHA3-512),SHAKE一族哈希函数(SHAKE128,SHAKE256)

其他

BLAKE2一族哈希函数:BLAKE2s,BLAKE2b,强度和SHA3类似

注意:SHA3被认为是比SHA2更安全的一族哈希函数

消息认证码(MAC)

消息认证码(MAC,Message Authentication Code),也叫做带有密钥的哈希,把给定的输入(任意长度的文本、数字)和一个密钥映射成固定长度的输出。

注意:这里的密钥往往是提前共享的,并不是在应用之前生成的。

推荐的MAC

  1. HMAC(Hash-based Message Authentication Code):HMAC-SHA256等
  2. KMAC(Keccak-based MAC)
  3. CMAC(Cipher-based MAC)

密钥衍生函数(KDF)

密钥衍生函数(KDF,Key Derivation Function)用来把一个长度任意的密码(Password)转换为顶长度的密钥(Key)。

密钥衍生函数算法往往通过一个随机数,盐(Salt)和很多轮的迭代计算,key stretching来生成一个密钥。这个盐值将会和最终生成的密钥共同存储。

推荐的KDF

Argon2:Argon2d,Argon2i,Argon2id(推荐这个),其相关参数包含使用内存大小m,并行因子p

注意:PBKDF2会受到GPU和ASIC攻击,因此被认为是老一代的KDF,不过在很多场合仍然会被使用。Bcrypt和Scrypt也可以使用,不过不如直接使用Argon2好。

伪随机数发生器(CSPRNG)

所有的伪随机数发生器都是从一个初始的随机数,叫做熵(entropy)作为初始种子开始的,经过高质量的随机数发生器(譬如AES,)不断产生随机数。产生一段时间会不停的更新种子,这个过程叫做reseed。

推荐的CSPRNG

Entropy的获得可以通过/dev/random(阻塞式,如果没有新的熵,则会等待)和/dev/urandom(非阻塞式,会通过secure entropy streching算法根据以前获得的entropy拓展)获取。

  1. Python用os.urandom()或者secrets
  2. Java用java.security.SecureRandom

对称加密(块加密算法)

这里的对称加密需要注意的地方主要包括算法,初始化向量(IV,Initialization Vector)和加密模式。其中,IV是不需要加密存储的,但每次要不一样。加密模式里面,有些需要填充算法(padding),有些不需要。有些有认证(Authenticated Encryption或者Authenticated Encryption with Associated Data),有些没有。

推荐的Block Cipher

  1. 无认证的:AES+CTR+NoPadding,SM4+CTR+NoPadding
  2. 有认证的:AES+GCM+NoPadding,ChaCha20+Poly1305+NoPadding(性能好于AES+GCM+NoPadding)

非对称加密

现在的非对称加密的使用方法一般是集成加密(IES,Integrated Encryption Scheme),包含了KEM(Key Encapsulation Mechanisms)和DEM(Data Encapsulation Mechanisms)。说的直白一些,非对称加密对称密钥,对称密钥加密数据。

RSA加密

基于质因子分解难题的加密系统,系统秘密参数p,q,系统公开参数n,公钥为随机数e,私钥为d。

ECC加密

椭圆曲线:一个函数定义的一条曲线,其定义域范围为有限域(所以曲线上的点都是离散的),曲线上的点关于x轴对称。因此,对于一个离散点P,可以压缩其坐标为x向量和一个比特(这个比特表示的是x轴之上的那个y坐标或者x轴之下的y坐标)。另外,对于公开的曲线,往往都有一个公开的基点G。

点和点之间可以做加法运算(点加运算)或点和整数之间做乘法运算(点乘运算)。0乘以一个点会得到一个特殊点叫做无穷远点。一条曲线上的所有点的个数叫做这条曲线的阶(order),order的计算包含无穷远点。有些曲线构成一个循环群,有些曲线有多个循环子群。对于循环子群,用曲线的公因子(cofactor)表示循环子群的个数。
常见的secp256k1就是单循环子群曲线,Curve25519有8个循环子群。

系统公开参数为椭圆曲线的系数,密钥为定义域内随机选取的整数k,公钥为EC上的点K=k*G。一般选择256比特的私钥,例如常见的曲线secp256k1(y^2 = x^3 + 7 mod p)和Curve25519。

曲线的参数列表一般包括:

  1. p(modulus)
  2. n(order)
  3. a(x的一次项系数)
  4. b(x的常数项系数)
  5. g(基点)
  6. h(cofactor)
posted @ 2021-10-11 16:11  alexanderzjs  阅读(304)  评论(0编辑  收藏  举报