栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python等同于PHP的MCRYPT_RIJNDAEL_256 CBC

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python等同于PHP的MCRYPT_RIJNDAEL_256 CBC

您是否尝试过这个(也包括在下面)?它实现了16、24或32字节的Rijndael分组密码。您正在使用256位(32字节)版本的分组密码。

"""A pure python (slow) implementation of rijndael with a decent interfaceTo include -from rijndael import rijndaelTo do a key setup -r = rijndael(key, block_size = 16)key must be a string of length 16, 24, or 32blocksize must be 16, 24, or 32. Default is 16To use -ciphertext = r.encrypt(plaintext)plaintext = r.decrypt(ciphertext)If any strings are of the wrong length a ValueError is thrown"""# ported from the Java reference pre by Bram Cohen, April 2001# this pre is public domain, unless someone makes # an intellectual property claim against the reference # pre, in which case it can be made public domain by # deleting all the comments and renaming all the variablesimport copyimport stringshifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],          [[0, 0], [1, 5], [2, 4], [3, 3]],          [[0, 0], [1, 7], [3, 5], [4, 4]]]# [keysize][block_size]num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}A = [[1, 1, 1, 1, 1, 0, 0, 0],     [0, 1, 1, 1, 1, 1, 0, 0],     [0, 0, 1, 1, 1, 1, 1, 0],     [0, 0, 0, 1, 1, 1, 1, 1],     [1, 0, 0, 0, 1, 1, 1, 1],     [1, 1, 0, 0, 0, 1, 1, 1],     [1, 1, 1, 0, 0, 0, 1, 1],     [1, 1, 1, 1, 0, 0, 0, 1]]# produce log and alog tables, needed for multiplying in the# field GF(2^m) (generator = 3)alog = [1]for i in range(255):    j = (alog[-1] << 1) ^ alog[-1]    if j & 0x100 != 0:        j ^= 0x11B    alog.append(j)log = [0] * 256for i in range(1, 255):    log[alog[i]] = i# multiply two elements of GF(2^m)def mul(a, b):    if a == 0 or b == 0:        return 0    return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]# substitution box based on F^{-1}(x)box = [[0] * 8 for i in range(256)]box[1][7] = 1for i in range(2, 256):    j = alog[255 - log[i]]    for t in range(8):        box[i][t] = (j >> (7 - t)) & 0x01B = [0, 1, 1, 0, 0, 0, 1, 1]# affine transform:  box[i] <- B + A*box[i]cox = [[0] * 8 for i in range(256)]for i in range(256):    for t in range(8):        cox[i][t] = B[t]        for j in range(8): cox[i][t] ^= A[t][j] * box[i][j]# S-boxes and inverse S-boxesS =  [0] * 256Si = [0] * 256for i in range(256):    S[i] = cox[i][0] << 7    for t in range(1, 8):        S[i] ^= cox[i][t] << (7-t)    Si[S[i] & 0xFF] = i# T-boxesG = [[2, 1, 1, 3],    [3, 2, 1, 1],    [1, 3, 2, 1],    [1, 1, 3, 2]]AA = [[0] * 8 for i in range(4)]for i in range(4):    for j in range(4):        AA[i][j] = G[i][j]        AA[i][i+4] = 1for i in range(4):    pivot = AA[i][i]    if pivot == 0:        t = i + 1        while AA[t][i] == 0 and t < 4: t += 1 assert t != 4, 'G matrix must be invertible' for j in range(8):     AA[i][j], AA[t][j] = AA[t][j], AA[i][j] pivot = AA[i][i]    for j in range(8):        if AA[i][j] != 0: AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]    for t in range(4):        if i != t: for j in range(i+1, 8):     AA[t][j] ^= mul(AA[i][j], AA[t][i]) AA[t][i] = 0iG = [[0] * 4 for i in range(4)]for i in range(4):    for j in range(4):        iG[i][j] = AA[i][j + 4]def mul4(a, bs):    if a == 0:        return 0    r = 0    for b in bs:        r <<= 8        if b != 0: r = r | mul(a, b)    return rT1 = []T2 = []T3 = []T4 = []T5 = []T6 = []T7 = []T8 = []U1 = []U2 = []U3 = []U4 = []for t in range(256):    s = S[t]    T1.append(mul4(s, G[0]))    T2.append(mul4(s, G[1]))    T3.append(mul4(s, G[2]))    T4.append(mul4(s, G[3]))    s = Si[t]    T5.append(mul4(s, iG[0]))    T6.append(mul4(s, iG[1]))    T7.append(mul4(s, iG[2]))    T8.append(mul4(s, iG[3]))    U1.append(mul4(t, iG[0]))    U2.append(mul4(t, iG[1]))    U3.append(mul4(t, iG[2]))    U4.append(mul4(t, iG[3]))# round constantsrcon = [1]r = 1for t in range(1, 30):    r = mul(2, r)    rcon.append(r)del Adel AAdel pivotdel Bdel Gdel boxdel logdel alogdel idel jdel rdel sdel tdel muldel mul4del coxdel iGclass rijndael:    def __init__(self, key, block_size = 16):        if block_size != 16 and block_size != 24 and block_size != 32: raise ValueError('Invalid block size: ' + str(block_size))        if len(key) != 16 and len(key) != 24 and len(key) != 32: raise ValueError('Invalid key size: ' + str(len(key)))        self.block_size = block_size        ROUNDS = num_rounds[len(key)][block_size]        BC = block_size // 4        # encryption round keys        Ke = [[0] * BC for i in range(ROUNDS + 1)]        # decryption round keys        Kd = [[0] * BC for i in range(ROUNDS + 1)]        ROUND_KEY_COUNT = (ROUNDS + 1) * BC        KC = len(key) // 4        # copy user material bytes into temporary ints        tk = []        for i in range(0, KC): tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |     (ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))        # copy values into round key arrays        t = 0        j = 0        while j < KC and t < ROUND_KEY_COUNT: Ke[t // BC][t % BC] = tk[j] Kd[ROUNDS - (t // BC)][t % BC] = tk[j] j += 1 t += 1        tt = 0        rconpointer = 0        while t < ROUND_KEY_COUNT: # extrapolate using phi (the round key evolution function) tt = tk[KC - 1] tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^            (S[(tt >>  8) & 0xFF] & 0xFF) << 16 ^            (S[ tt        & 0xFF] & 0xFF) <<  8 ^            (S[(tt >> 24) & 0xFF] & 0xFF)       ^            (rcon[rconpointer]    & 0xFF) << 24 rconpointer += 1 if KC != 8:     for i in range(1, KC):         tk[i] ^= tk[i-1] else:     for i in range(1, KC // 2):         tk[i] ^= tk[i-1]     tt = tk[KC // 2 - 1]     tk[KC // 2] ^= (S[ tt        & 0xFF] & 0xFF)       ^          (S[(tt >>  8) & 0xFF] & 0xFF) <<  8 ^          (S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^          (S[(tt >> 24) & 0xFF] & 0xFF) << 24     for i in range(KC // 2 + 1, KC):         tk[i] ^= tk[i-1] # copy values into round key arrays j = 0 while j < KC and t < ROUND_KEY_COUNT:     Ke[t // BC][t % BC] = tk[j]     Kd[ROUNDS - (t // BC)][t % BC] = tk[j]     j += 1     t += 1        # inverse MixColumn where needed        for r in range(1, ROUNDS): for j in range(BC):     tt = Kd[r][j]     Kd[r][j] = U1[(tt >> 24) & 0xFF] ^      U2[(tt >> 16) & 0xFF] ^      U3[(tt >>  8) & 0xFF] ^      U4[ tt        & 0xFF]        self.Ke = Ke        self.Kd = Kd    def encrypt(self, plaintext):        if len(plaintext) != self.block_size: raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))        Ke = self.Ke        BC = self.block_size // 4        ROUNDS = len(Ke) - 1        if BC == 4: SC = 0        elif BC == 6: SC = 1        else: SC = 2        s1 = shifts[SC][1][0]        s2 = shifts[SC][2][0]        s3 = shifts[SC][3][0]        a = [0] * BC        # temporary work array        t = []        # plaintext to ints + key        for i in range(BC): t.append((ord(plaintext[i * 4    ]) << 24 |ord(plaintext[i * 4 + 1]) << 16 |ord(plaintext[i * 4 + 2]) <<  8 |ord(plaintext[i * 4 + 3])        ) ^ Ke[0][i])        # apply round transforms        for r in range(1, ROUNDS): for i in range(BC):     a[i] = (T1[(t[ i] >> 24) & 0xFF] ^  T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^  T3[(t[(i + s2) % BC] >>  8) & 0xFF] ^  T4[ t[(i + s3) % BC]        & 0xFF]  ) ^ Ke[r][i] t = copy.copy(a)        # last round is special        result = []        for i in range(BC): tt = Ke[ROUNDS][i] result.append((S[(t[ i] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF) result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF) result.append((S[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF) result.append((S[ t[(i + s3) % BC]        & 0xFF] ^  tt       ) & 0xFF)        return ''.join(map(chr, result))    def decrypt(self, ciphertext):        if len(ciphertext) != self.block_size: raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(ciphertext)))        Kd = self.Kd        BC = self.block_size // 4        ROUNDS = len(Kd) - 1        if BC == 4: SC = 0        elif BC == 6: SC = 1        else: SC = 2        s1 = shifts[SC][1][1]        s2 = shifts[SC][2][1]        s3 = shifts[SC][3][1]        a = [0] * BC        # temporary work array        t = [0] * BC        # ciphertext to ints + key        for i in range(BC): t[i] = (ord(ciphertext[i * 4    ]) << 24 |         ord(ciphertext[i * 4 + 1]) << 16 |         ord(ciphertext[i * 4 + 2]) <<  8 |         ord(ciphertext[i * 4 + 3])        ) ^ Kd[0][i]        # apply round transforms        for r in range(1, ROUNDS): for i in range(BC):     a[i] = (T5[(t[ i] >> 24) & 0xFF] ^  T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^  T7[(t[(i + s2) % BC] >>  8) & 0xFF] ^  T8[ t[(i + s3) % BC]        & 0xFF]  ) ^ Kd[r][i] t = copy.copy(a)        # last round is special        result = []        for i in range(BC): tt = Kd[ROUNDS][i] result.append((Si[(t[ i] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF) result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF) result.append((Si[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF) result.append((Si[ t[(i + s3) % BC]        & 0xFF] ^  tt       ) & 0xFF)        return ''.join(map(chr, result))def encrypt(key, block):    return rijndael(key, len(block)).encrypt(block)def decrypt(key, block):    return rijndael(key, len(block)).decrypt(block)

请注意,该

rijndael.py
文件仅实现分组密码。该
encrypt
/
decrypt
功能只会处理恰恰是块大小明文。这意味着这些函数的调用者将必须提供操作的分组密码模式以及他自己的零填充。

示例python代码(请注意,来自Java程序员):

class zeropad:    def __init__(self, block_size):        assert block_size > 0 and block_size < 256        self.block_size = block_size    def pad(self, pt):        ptlen = len(pt)        padsize = self.block_size - ((ptlen + self.block_size - 1) % self.block_size + 1)        return pt + "" * padsize    def unpad(self, ppt):        assert len(ppt) % self.block_size == 0        offset = len(ppt)        if (offset == 0): return ''        end = offset - self.block_size + 1        while (offset > end): offset -= 1; if (ppt[offset] != ""):     return ppt[:offset + 1]        assert falseclass cbc:    def __init__(self, padding, cipher, iv):        assert padding.block_size == cipher.block_size;        assert len(iv) == cipher.block_size;        self.padding = padding        self.cipher = cipher        self.iv = iv    def encrypt(self, pt):        ppt = self.padding.pad(pt)        offset = 0        ct = ''        v = self.iv        while (offset < len(ppt)): block = ppt[offset:offset + self.cipher.block_size] block = self.xorblock(block, v) block = self.cipher.encrypt(block) ct += block offset += self.cipher.block_size v = block        return ct;    def decrypt(self, ct):        assert len(ct) % self.cipher.block_size == 0        ppt = ''        offset = 0        v = self.iv        while (offset < len(ct)): block = ct[offset:offset + self.cipher.block_size] decrypted = self.cipher.decrypt(block) ppt += self.xorblock(decrypted, v) offset += self.cipher.block_size v = block        pt = self.padding.unpad(ppt)        return pt;    def xorblock(self, b1, b2):        # sorry, not very Pythonesk        i = 0        r = '';        while (i < self.cipher.block_size):  r += chr(ord(b1[i]) ^ ord(b2[i]))  i += 1        return r


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/402137.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号