当前位置: 移动技术网 > IT编程>脚本编程>Python > Python 实现国产SM3加密算法的示例代码

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

2020年09月22日  | 移动技术网IT编程  | 我要评论
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加密算法的资料请关注移动技术网其它相关文章!

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网