[python]Siphash算法

[python]Siphash算法,第1张

本代码中的消息与密钥实例为论文[1]附录A的测试向量。


import math

class SipHash():
    def __init__(self):
        # initial constants
        self.v_0 = 0x736f6d6570736575
        self.v_1 = 0x646f72616e646f6d
        self.v_2 = 0x6c7967656e657261
        self.v_3 = 0x7465646279746573
        self.k_0 = 0
        self.k_1 = 0

    def password(self,pwd):
        # 初始化密钥:将pwd转换为k_0和k_1
        # 需先确认计算机的编码方式(本人计算机是小端编码)
        self.k_0 = int((pwd[:8])[::-1].hex(), 16)
        self.k_1 = int((pwd[8:])[::-1].hex(), 16)

    def siphash_fill(self,msg):
        # 消息填充,使填充后长度为64bits的整数倍
        # 输入参数msg为bytes类型
        length = len(msg)                   # msg的长度(单位:bytes)
        w = math.ceil((length + 1) / 8)     # msg能够划分的消息块个数(每个消息块64bits)
        remain_len = w * 8 - length         # 需填充的长度

        msg_new = bytearray((w * 8))        # 填充后的消息长度,单位:byte

        # 将msg的数据存储至msg_new_bytes中
        for i in range(w * 8 - remain_len):
            msg_new[i] = msg[i]

        # 填充0
        for i in [w * 8 - remain_len, w * 8 - 1]:
            msg_new[i] = 0

        # 最后1字节填充msg的长度模256
        msg_new[w * 8 - 1] = length % 256

        return msg_new

    def SipRound(self,a,b,c,d):
        #轮函数计算,内部状态为64比特,运算应保留后64位
        a = (a + b) & 0xffffffffffffffff
        b = (((b << 13) | (b >> 51)) ^ a) & 0xffffffffffffffff

        c = (c + d) & 0xffffffffffffffff
        d = (((d << 16) | (d >> 48)) ^ c) & 0xffffffffffffffff

        a = ((a << 32) | (a >> 32)) & 0xffffffffffffffff

        c = (c + b) & 0xffffffffffffffff
        b = (((b << 17) | (b >> 47)) ^ c) & 0xffffffffffffffff

        a = (a + d) & 0xffffffffffffffff
        d = (((d << 21) | (d >> 43)) ^ a) & 0xffffffffffffffff

        c = ((c << 32) | (c >> 32)) & 0xffffffffffffffff

        return a, b, c, d

    def SipHash_2_4(self,msg,pwd):
        # 填充消息
        msg = self.siphash_fill(msg)
        # 初始化密钥
        self.password(pwd)

        # 初始状态与密钥异或
        self.v_0 ^= self.k_0
        self.v_1 ^= self.k_1
        self.v_2 ^= self.k_0
        self.v_3 ^= self.k_1

        # 压缩阶段
        length = len(msg) // 8
        for i in range(length):
            m = int((msg[i * 8:(i + 1) * 8])[::-1].hex(), 16)
            self.v_3 ^= m

            self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)
            self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)

            self.v_0 ^= m

        # 终结阶段
        self.v_2 ^= 0xff
        self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)
        self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)
        self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)
        self.v_0, self.v_1, self.v_2, self.v_3 = self.SipRound(self.v_0, self.v_1, self.v_2, self.v_3)

        return self.v_0 ^ self.v_1 ^ self.v_2 ^ self.v_3

if __name__ == '__main__':
    msg = ''.join(chr(i) for i in range(15)).encode('utf-8')    # msg = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e'
    pwd = ''.join(chr(i) for i in range(16)).encode('utf-8')    # pwd = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

    test1 = SipHash()
    digest1 = test1.SipHash_2_4(msg,pwd)
    print("message: ", msg.hex())
    print("password:", pwd.hex())
    print("digest1: ", hex(digest1))

运行结果:

参考文献:
[1]. Aumasson J P , Bernstein D J . SipHash: a fast short-input PRF[J]. Lecture Notes in Computer Science, 2012.

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/570347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存