-
商用密码应用安全性评估(以下简称密评)之密码算法
密码算法指描述密码处理过程的一组运算规则或规程。
在GB/T 39786 《信息安全技术 信息系统密码应用基本要求》、GB/T 0115 《信息系统密码应用测评要求》的通用要求中都明确规定了:信息系统中使用的密码算法应符合法律、法规的规定和密码相关国家标准、行业标准的有关要求。
密码算法作为密评中的通用要求,所有级别的信息系统都应遵循。虽然其不作为单独的测评项而是融入到具体的指标中进行测评,但是涉及密码算法的高风险判定无缓解措施且密码算法的密码强度已加入了量化评估规则。本文将对密码算法进行详解:
-
密码算法的分类
-
对称密码算法
def SMJ(x):#SM4加密算法X = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
X[0] = (x >> 96) & 0xffffffff
X[1] = (x >> 64) & 0xffffffff
X[2] = (x >> 32) & 0xffffffff
X[3] = (x >> 0) & 0xffffffff
for i in range(33):
X[i+4] = X[i]^T_(X[i+1]^X[i+2]^X[i+3]^rk[i])#轮函数return (X[35]<<96)^(X[34]<<64)^(X[33]<<32)^X[32]
if __name__ == '__main__':
MK = int(input("请输入加密密钥: "), 16)
print(MK)
MK0=(MK>>96)&0Xffffffff
MK1=(MK>>64)&0Xffffffff
MK2=(MK>>32)&0Xffffffff
MK3=(MK>>0)&0Xffffffff
K_(MK0, MK1, MK2, MK3)
message = input('输入待加密的消息:n')
M = mpz(binascii.hexlify(message.encode('utf-8')), 16)
#x = int(input("请输入明文: "), 16)
print("密文为:{:x}".format(SMJ(M)))
-
非对称密码算法(公钥密码算法)
import gmpy2
from gmpy2 import mpz
import binascii
def gen_prime(rs):
"""生成二进制位数为1024的随机素数"""p = gmpy2.mpz_urandomb(rs, 1024)
while not gmpy2.is_prime(p):
p = p + 1
return p
def gen_key():"""生成密钥"""
rs = gmpy2.random_state()
p = gen_prime(rs)
q = gen_prime(rs)
return p, q
def encrypt(e, n, message):
"""将输入消息转换成16进制数字并加密,支持utf-8字符串"""M = mpz(binascii.hexlify(message.encode('utf-8')), 16)
C = gmpy2.powmod(M, e, n)
return C
def decrypt(d, n, C):
"""对输入的密文进行解密并解码"""
M = gmpy2.powmod(C, d, n)
return binascii.unhexlify(format(M, 'x')).decode('utf-8')
def main():
# 密钥生成
p, q = gen_key()
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = gmpy2.invert(e, phi)
# 输入消息message = input('输入待加密的消息:n')
# 加密C = encrypt(e, n, message)
print('16进制密文:', hex(C))
# 解密print('解密后的消息:', decrypt(d, n, C))
p = gen_prime(rs)
if __name__ == '__main__':
q = gen_prime(rs)
return p, q
def encrypt(e, n, message):
"""将输入消息转换成16进制数字并加密,支持utf-8字符串"""
M = mpz(binascii.hexlify(message.encode('utf-8')), 16)
C = gmpy2.powmod(M, e, n)
return C
def decrypt(d, n, C):
"""对输入的密文进行解密并解码"""
M = gmpy2.powmod(C, d, n)
return binascii.unhexlify(format(M, 'x')).decode('utf-8')
def main():#密钥生成
p, q = gen_key()
n = p * q
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = gmpy2.invert(e, phi)
phi = (p - 1) * (q - 1)
e = 65537
d = gmpy2.invert(e, phi)# 输入消息
message = input('输入待加密的消息:n')
# 加密C = encrypt(e, n, message)
print('16进制密文:', hex(C))
# 解密print('解密后的消息:', decrypt(d, n, C))
if __name__ == '__main__':# 加密
C = encrypt(e, n, message)
print('16进制密文:', hex(C))
# 解密print('解密后的消息:', decrypt(d, n, C))
print('16进制密文:', hex(C))
if __name__ == '__main__':
# 解密
print('解密后的消息:', decrypt(d, n, C))
if __name__ == '__main__':main()
运行结果:
def encry_sm2(args, PB, M):
p, a, b, h, G, n = args # 序列解包
M_bytes = bytes(M, encoding='ascii')
print("A1:用随机数发生器产生随机数k∈[1,n-1]")
k = random.randint(1, n-1)#生成随机数k 用于生成公钥
k_hex = hex(k)[2:] # k_hex 是k的十六进制串形式
print("生成的随机数是:", k_hex)
print("nA2:计算椭圆曲线点C1=[k]G=(x1,y1),将C1的数据类型转换为比特串")
C1 = mult_point(G, k, p, a)print("椭圆曲线点C1=[k]G=(x1,y1)的坐标是:", tuple(map(hex, C1)))
C1_bits = point_to_bits(C1)
print("椭圆曲线点C1=[k]G=(x1,y1)的坐标的比特串形式是:", C1_bits)
print("nA3:计算椭圆曲线点S = [h]PB")
S = mult_point(PB, h, p, a)
if S == 0:
raise Exception("计算得到的S是无穷远点")
print("A3椭圆曲线点S = [h]PB的坐标是:", tuple(map(hex, S)))
print("nA4:计算椭圆曲线点[k]PB=(x2,y2),将坐标x2、y2 的数据类型转换为比特串")
x2, y2 = mult_point(PB, k, p, a)print("椭圆曲线点[k]PB=(x2,y2)的坐标是:", tuple(map(hex, (x2, y2))))
x2_bits = fielde_to_bits(x2)
print("x2的比特串形式是:", x2_bits)
y2_bits = fielde_to_bits(y2)
print("y2的比特串形式是:", y2_bits)
print("nA5:计算t=KDF(x2 ∥ y2, klen),若t为全0比特串,则返回A1")
M_hex = bytes_to_hex(M_bytes)
klen = 4 * len(M_hex)
print("明文消息的比特串长度klen是:", klen)
t = KDF(x2_bits + y2_bits, klen)print("通过KDF算法计算得到的t=KDF(x2 ∥ y2, klen)是:", t)
if eval('0b' + t) == 0:
raise Exception("KDF返回了全零串,请检查KDF算法!")
t_hex = bits_to_hex(t)
print("t的十六进制表示形式是:", t_hex)
print("nA6:计算计算C2 = M ⊕ t")
C2 = eval('0x' + M_hex + '^' + '0b' + t)#"^"表示异或操作
print("计算的C2是:", hex(C2)[2:])
print("nA7:计算C3 = Hash(x2 ∥ M ∥ y2)")
x2_bytes = bits_to_bytes(x2_bits)
y2_bytes = bits_to_bytes(y2_bits)
hash_list = [i for i in x2_bytes + M_bytes + y2_bytes]
C3 = sm3.sm3_hash(hash_list)print("计算的C3 = Hash(x2 ∥ M ∥ y2)是:", C3)
print("nA8:输出密文C = C1 ∥ C2 ∥ C3")
C1_hex = bits_to_hex(C1_bits)
C2_hex = hex(C2)[2:]
C3_hex = C3
C_hex = C1_hex + C2_hex + C3_hex
print("加密得到的密文是:", C_hex)
return C_hex
密钥派生函数KDF部分代码:
def KDF(Z, klen):
v = 256 # 密码杂凑函数采用SM3if klen >= (pow(2, 32) - 1) * v:
raise Exception("密钥派生函数KDF出错,请检查klen的大小!")
ct = 0x00000001
if klen % v == 0:
l = klen // v
else:
l = klen // v + 1
Ha = []
for i in range(l): # i从0到 klen/v-1(向上取整),共l个元素
s = Z + int_to_bits(ct).rjust(32, '0') # s存储 Z || ct 的比特串形式 # 注意,ct要填充为32位
s_bytes = bits_to_bytes(s) # s_bytes存储字节串形式
s_list = [i for i in s_bytes]
hash_hex = sm3.sm3_hash(s_list)
hash_bin = hex_to_bits(hash_hex)
Ha.append(hash_bin)
ct += 1
if klen % v != 0:
Ha[-1] = Ha[-1][:klen - v*(klen//v)]
k = ''.join(Ha)
return k
-
密码杂凑算法
def sm3(msg):"""
sm3加密主函数
:param msg: 待加密的字符串
:param msg: 待加密的字符串
:retur:return: sm3加密后的字符串
"""
# 字符串转化为比特串s_bin = str2bin(msg)
# 对消息进行填充s_fill = msg_fill(s_bin)# 对填充后的消息进行迭代压缩
s_sm3 = iteration_func(s_fill)
# 对于python2需要删除因长整型而引入的末尾的L字符,python3不存在该问题return s_sm3.upper().replace("L", "")
# 对于python2需要删除因长整型而引入的末尾的L字符,python3不存在该问题
return s_sm3.upper().replace("L", "")
-
密码算法的功能实现
在做商用密码测评时,应该知道商用密码算法的特点:
1. 复杂性:商用密码应该由多种不同的字符组成,包括大小写字母、数字和特殊符号等,以增加密码的强度。
2. 长度:密码的长度应该足够长,一般建议至少8个字符,但更长的密码更安全。
3. 不可预测性:密码应该是随机生成的,避免使用常见的字典词汇或者个人信息。定期更换:商用密码应定期更换,以减少密码被破解的风险。
4. 单一性:每个用户或每个账户应使用唯一的密码,避免重复使用密码。
5. 多因素认证:商用密码可以搭配其他认证方式,如指纹、身份证等,以提高安全性。
6. 密码管理软件:可以使用密码管理软件来生成和管理密码,以确保密码的安全性和易记性。
总之,商用密码是企业安全策略中的重要一环,在保护商业敏感信息和减少数据泄露方面起着至关重要的作用。
原文始发于微信公众号(瑞不可当):商用密码应用安全性评估之密码算法详解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论