欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 实现国产SM3加密算法的示例代码

程序员文章站 2022-04-10 09:14:09
sm3是**采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。主要用于报告文件数字签名及验证。python3代码如下:from math import ceil#...

sm3是**采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。主要用于报告文件数字签名及验证。

python3代码如下:

from math import ceil

##############################################################################
#
#              国产sm3加密算法
#
##############################################################################

iv = "7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e"
iv = int(iv.replace(" ", ""), 16)
a = []
for i in range(0, 8):
  a.append(0)
  a[i] = (iv >> ((7 - i) * 32)) & 0xffffffff
iv = a


def out_hex(list1):
  for i in list1:
    print("%08x" % i)
  print("\n")


def rotate_left(a, k):
  k = k % 32
  return ((a << k) & 0xffffffff) | ((a & 0xffffffff) >> (32 - k))


t_j = []
for i in range(0, 16):
  t_j.append(0)
  t_j[i] = 0x79cc4519
for i in range(16, 64):
  t_j.append(0)
  t_j[i] = 0x7a879d8a


def ff_j(x, y, z, j):
  if 0 <= j and j < 16:
    ret = x ^ y ^ z
  elif 16 <= j and j < 64:
    ret = (x & y) | (x & z) | (y & z)
  return ret


def gg_j(x, y, z, j):
  if 0 <= j and j < 16:
    ret = x ^ y ^ z
  elif 16 <= j and j < 64:
    # ret = (x | y) & ((2 ** 32 - 1 - x) | z)
    ret = (x & y) | ((~ x) & z)
  return ret


def p_0(x):
  return x ^ (rotate_left(x, 9)) ^ (rotate_left(x, 17))


def p_1(x):
  return x ^ (rotate_left(x, 15)) ^ (rotate_left(x, 23))


def cf(v_i, b_i):
  w = []
  for i in range(16):
    weight = 0x1000000
    data = 0
    for k in range(i * 4, (i + 1) * 4):
      data = data + b_i[k] * weight
      weight = int(weight / 0x100)
    w.append(data)

  for j in range(16, 68):
    w.append(0)
    w[j] = p_1(w[j - 16] ^ w[j - 9] ^ (rotate_left(w[j - 3], 15))) ^ (rotate_left(w[j - 13], 7)) ^ w[j - 6]
    str1 = "%08x" % w[j]
  w_1 = []
  for j in range(0, 64):
    w_1.append(0)
    w_1[j] = w[j] ^ w[j + 4]
    str1 = "%08x" % w_1[j]

  a, b, c, d, e, f, g, h = v_i
  """
  print "00",
  out_hex([a, b, c, d, e, f, g, h])
  """
  for j in range(0, 64):
    ss1 = rotate_left(((rotate_left(a, 12)) + e + (rotate_left(t_j[j], j))) & 0xffffffff, 7)
    ss2 = ss1 ^ (rotate_left(a, 12))
    tt1 = (ff_j(a, b, c, j) + d + ss2 + w_1[j]) & 0xffffffff
    tt2 = (gg_j(e, f, g, j) + h + ss1 + w[j]) & 0xffffffff
    d = c
    c = rotate_left(b, 9)
    b = a
    a = tt1
    h = g
    g = rotate_left(f, 19)
    f = e
    e = p_0(tt2)

    a = a & 0xffffffff
    b = b & 0xffffffff
    c = c & 0xffffffff
    d = d & 0xffffffff
    e = e & 0xffffffff
    f = f & 0xffffffff
    g = g & 0xffffffff
    h = h & 0xffffffff

  v_i_1 = []
  v_i_1.append(a ^ v_i[0])
  v_i_1.append(b ^ v_i[1])
  v_i_1.append(c ^ v_i[2])
  v_i_1.append(d ^ v_i[3])
  v_i_1.append(e ^ v_i[4])
  v_i_1.append(f ^ v_i[5])
  v_i_1.append(g ^ v_i[6])
  v_i_1.append(h ^ v_i[7])
  return v_i_1


def hash_msg(msg):
  # print(msg)
  len1 = len(msg)
  reserve1 = len1 % 64
  msg.append(0x80)
  reserve1 = reserve1 + 1
  # 56-64, add 64 byte
  range_end = 56
  if reserve1 > range_end:
    range_end = range_end + 64

  for i in range(reserve1, range_end):
    msg.append(0x00)

  bit_length = (len1) * 8
  bit_length_str = [bit_length % 0x100]
  for i in range(7):
    bit_length = int(bit_length / 0x100)
    bit_length_str.append(bit_length % 0x100)
  for i in range(8):
    msg.append(bit_length_str[7 - i])

  # print(msg)

  group_count = round(len(msg) / 64)

  b = []
  for i in range(0, group_count):
    b.append(msg[i * 64:(i + 1) * 64])

  v = []
  v.append(iv)
  for i in range(0, group_count):
    v.append(cf(v[i], b[i]))

  y = v[i + 1]
  result = ""
  for i in y:
    result = '%s%08x' % (result, i)
  return result


def str2byte(msg): # 字符串转换成byte数组
  ml = len(msg)
  msg_byte = []
  msg_bytearray = msg # 如果加密对象是字符串,则在此对msg做encode()编码即可,否则不编码
  for i in range(ml):
    msg_byte.append(msg_bytearray[i])
  return msg_byte


def byte2str(msg): # byte数组转字符串
  ml = len(msg)
  str1 = b""
  for i in range(ml):
    str1 += b'%c' % msg[i]
  return str1.decode('utf-8')


def hex2byte(msg): # 16进制字符串转换成byte数组
  ml = len(msg)
  if ml % 2 != 0:
    msg = '0' + msg
  ml = int(len(msg) / 2)
  msg_byte = []
  for i in range(ml):
    msg_byte.append(int(msg[i * 2:i * 2 + 2], 16))
  return msg_byte


def byte2hex(msg): # byte数组转换成16进制字符串
  ml = len(msg)
  hexstr = ""
  for i in range(ml):
    hexstr = hexstr + ('%02x' % msg[i])
  return hexstr


def kdf(z, klen): # z为16进制表示的比特串(str),klen为密钥长度(单位byte)
  klen = int(klen)
  ct = 0x00000001
  rcnt = ceil(klen / 32)
  zin = hex2byte(z)
  ha = ""
  for i in range(int(rcnt)):
    msg = zin + hex2byte('%08x' % ct)
    # print(msg)
    ha = ha + hash_msg(msg)
    # print(ha)
    ct += 1
  return ha[0: klen * 2]


def sm3_hash(msg, hexstr=0):
  """
  封装方法,外部调用
  :param msg: 二进制流(如若需要传入字符串,则把str2byte方法里msg做encode()编码一下,否则不编码)
  :param hexstr: 0
  :return: 64位sm3加密结果
  """
  if (hexstr):
    msg_byte = hex2byte(msg)
  else:
    msg_byte = str2byte(msg)
  return hash_msg(msg_byte)


if __name__ == '__main__':
  print(sm3_hash(b'sm3test'))# 打印结果:901053b4681483b737dd2dd9f9a7f56805aa1b03337f8c1abb763a96776b8905

以上就是python 实现国产sm3加密算法的示例代码的详细内容,更多关于python 实现国产sm3加密算法的资料请关注其它相关文章!