Module refinery.lib.serpent
This implementation of the Serpent cipher is based on the original C reference implementation, available from the official website. The C macros for each of the round operations were turned into a Python function, and the unrolled loops were reverted back because the performance gain in Python would be negligible for the substantial loss of readability.
All functions allow a "swap" option to be passed which will has the equivalent effect of reversing the byte order of the input. This option is available because different implementations use different byte orders for the various parts of the algorithm.
Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# flake8: noqa
"""
This implementation of the Serpent cipher is based on the original C reference implementation, available
from the [official website](https://www.cl.cam.ac.uk/~rja14/serpent.html). The C macros for each of the
round operations were turned into a Python function, and the unrolled loops were reverted back because the
performance gain in Python would be negligible for the substantial loss of readability.
All functions allow a "swap" option to be passed which will has the equivalent effect of reversing the
byte order of the input. This option is available because different implementations use different byte
orders for the various parts of the algorithm.
"""
from __future__ import annotations
from typing import List
from struct import pack, unpack
from refinery.lib.crypto import (
rotl32 as ROL,
rotr32 as ROR,
)
PHI = 0x9E3779B9
def RND00(a, b, c, d):
t01 = b ^ c
t02 = a | d
t03 = a ^ b
z = t02 ^ t01
t05 = c | z
t06 = a ^ d
t07 = b | c
t08 = d & t05
t09 = t03 & t07
y = t09 ^ t08
t11 = t09 & y
t12 = c ^ d
t13 = t07 ^ t11
t14 = b & t06
t15 = t06 ^ t13
w = ~ t15 & 0xFFFFFFFF
t17 = w ^ t14
x = t12 ^ t17
return w, x, y, z
def RND01(a, b, c, d):
t01 = a | d
t02 = c ^ d
t03 = ~ b & 0xFFFFFFFF
t04 = a ^ c
t05 = a | t03
t06 = d & t04
t07 = t01 & t02
t08 = b | t06
y = t02 ^ t05
t10 = t07 ^ t08
t11 = t01 ^ t10
t12 = y ^ t11
t13 = b & d
z = ~ t10 & 0xFFFFFFFF
x = t13 ^ t12
t16 = t10 | x
t17 = t05 & t16
w = c ^ t17
return w, x, y, z
def RND02(a, b, c, d):
t01 = a | c
t02 = a ^ b
t03 = d ^ t01
w = t02 ^ t03
t05 = c ^ w
t06 = b ^ t05
t07 = b | t05
t08 = t01 & t06
t09 = t03 ^ t07
t10 = t02 | t09
x = t10 ^ t08
t12 = a | d
t13 = t09 ^ x
t14 = b ^ t13
z = ~ t09 & 0xFFFFFFFF
y = t12 ^ t14
return w, x, y, z
def RND03(a, b, c, d):
t01 = a ^ c
t02 = a | d
t03 = a & d
t04 = t01 & t02
t05 = b | t03
t06 = a & b
t07 = d ^ t04
t08 = c | t06
t09 = b ^ t07
t10 = d & t05
t11 = t02 ^ t10
z = t08 ^ t09
t13 = d | z
t14 = a | t07
t15 = b & t13
y = t08 ^ t11
w = t14 ^ t15
x = t05 ^ t04
return w, x, y, z
def RND04(a, b, c, d):
t01 = a | b
t02 = b | c
t03 = a ^ t02
t04 = b ^ d
t05 = d | t03
t06 = d & t01
z = t03 ^ t06
t08 = z & t04
t09 = t04 & t05
t10 = c ^ t06
t11 = b & c
t12 = t04 ^ t08
t13 = t11 | t03
t14 = t10 ^ t09
t15 = a & t05
t16 = t11 | t12
y = t13 ^ t08
x = t15 ^ t16
w = ~ t14 & 0xFFFFFFFF
return w, x, y, z
def RND05(a, b, c, d):
t01 = b ^ d
t02 = b | d
t03 = a & t01
t04 = c ^ t02
t05 = t03 ^ t04
w = ~ t05 & 0xFFFFFFFF
t07 = a ^ t01
t08 = d | w
t09 = b | t05
t10 = d ^ t08
t11 = b | t07
t12 = t03 | w
t13 = t07 | t10
t14 = t01 ^ t11
y = t09 ^ t13
x = t07 ^ t08
z = t12 ^ t14
return w, x, y, z
def RND06(a, b, c, d):
t01 = a & d
t02 = b ^ c
t03 = a ^ d
t04 = t01 ^ t02
t05 = b | c
x = ~ t04 & 0xFFFFFFFF
t07 = t03 & t05
t08 = b & x
t09 = a | c
t10 = t07 ^ t08
t11 = b | d
t12 = c ^ t11
t13 = t09 ^ t10
y = ~ t13 & 0xFFFFFFFF
t15 = x & t03
z = t12 ^ t07
t17 = a ^ b
t18 = y ^ t15
w = t17 ^ t18
return w, x, y, z
def RND07(a, b, c, d):
t01 = a & c
t02 = ~ d & 0xFFFFFFFF
t03 = a & t02
t04 = b | t01
t05 = a & b
t06 = c ^ t04
z = t03 ^ t06
t08 = c | z
t09 = d | t05
t10 = a ^ t08
t11 = t04 & z
x = t09 ^ t10
t13 = b ^ x
t14 = t01 ^ x
t15 = c ^ t05
t16 = t11 | t13
t17 = t02 | t14
w = t15 ^ t17
y = a ^ t16
return w, x, y, z
def make_subkeys(key: bytearray, swap: bool = False):
if len(key) > 32:
raise ValueError
if swap:
key = key[::-1]
key = B'\0' * (-len(key) % 4) + key
K = [0] * 132
L = len(key) // 4
for i, v in enumerate(reversed(unpack(F'>{L}L', key))):
K[i] = v
if L < 8:
K[L] = 1
for i in range(8, 16):
K[i] = ROL(K[i-8] ^ K[i-5] ^ K[i-3] ^ K[i-1] ^ PHI ^ (i-8), 11)
K[:8] = K[8:16]
for i in range(8, 132):
K[i] = ROL(K[i-8] ^ K[i-5] ^ K[i-3] ^ K[i-1] ^ PHI ^ i, 11)
RNDS = [RND00, RND01, RND02, RND03, RND04, RND05, RND06, RND07]
for i, k in enumerate(range(3, -30, -1)):
a, b = i * 4, (i + 1) * 4
K[a:b] = RNDS[k % 8](*K[a:b])
return K
def serpent_encrypt(plaintext: bytearray, subkeys: List[int], swap: bool = False) -> bytes:
if swap:
a, b, c, d = unpack('<4L', plaintext)
else:
d, c, b, a = unpack('>4L', plaintext)
RNDS = [RND00, RND01, RND02, RND03, RND04, RND05, RND06, RND07]
for k in range(31):
j = k * 4
a ^= subkeys[j + 0]
b ^= subkeys[j + 1]
c ^= subkeys[j + 2]
d ^= subkeys[j + 3]
w, x, y, z = RNDS[k % 8](a, b, c, d)
a = ROL(w, 13)
c = ROL(y, 3)
b = x ^ a ^ c
d = z ^ c ^ ((a<<3) & 0xFFFFFFFF)
b = ROL(b, 1)
d = ROL(d, 7)
a = a ^ b ^ d
c = c ^ d ^ ((b<<7) & 0xFFFFFFFF)
a = ROL(a, 5)
c = ROL(c, 22)
a ^= subkeys[124]
b ^= subkeys[125]
c ^= subkeys[126]
d ^= subkeys[127]
a, b, c, d = RND07(a, b, c, d)
a ^= subkeys[128]
b ^= subkeys[129]
c ^= subkeys[130]
d ^= subkeys[131]
if swap:
return pack('<4L', a, b, c, d)
else:
return pack('>4L', d, c, b, a)
def InvRND00(a, b, c, d):
t01 = c ^ d
t02 = a | b
t03 = b | c
t04 = c & t01
t05 = t02 ^ t01
t06 = a | t04
y = ~ t05 & 0xFFFFFFFF
t08 = b ^ d
t09 = t03 & t08
t10 = d | y
x = t09 ^ t06
t12 = a | t05
t13 = x ^ t12
t14 = t03 ^ t10
t15 = a ^ c
z = t14 ^ t13
t17 = t05 & t13
t18 = t14 | t17
w = t15 ^ t18
return w, x, y, z
def InvRND01(a, b, c, d):
t01 = a ^ b
t02 = b | d
t03 = a & c
t04 = c ^ t02
t05 = a | t04
t06 = t01 & t05
t07 = d | t03
t08 = b ^ t06
t09 = t07 ^ t06
t10 = t04 | t03
t11 = d & t08
y = ~ t09 & 0xFFFFFFFF
x = t10 ^ t11
t14 = a | y
t15 = t06 ^ x
z = t01 ^ t04
t17 = c ^ t15
w = t14 ^ t17
return w, x, y, z
def InvRND02(a, b, c, d):
t01 = a ^ d
t02 = c ^ d
t03 = a & c
t04 = b | t02
w = t01 ^ t04
t06 = a | c
t07 = d | w
t08 = ~ d & 0xFFFFFFFF
t09 = b & t06
t10 = t08 | t03
t11 = b & t07
t12 = t06 & t02
z = t09 ^ t10
x = t12 ^ t11
t15 = c & z
t16 = w ^ x
t17 = t10 ^ t15
y = t16 ^ t17
return w, x, y, z
def InvRND03(a, b, c, d):
t01 = c | d
t02 = a | d
t03 = c ^ t02
t04 = b ^ t02
t05 = a ^ d
t06 = t04 & t03
t07 = b & t01
y = t05 ^ t06
t09 = a ^ t03
w = t07 ^ t03
t11 = w | t05
t12 = t09 & t11
t13 = a & y
t14 = t01 ^ t05
x = b ^ t12
t16 = b | t13
z = t14 ^ t16
return w, x, y, z
def InvRND04(a, b, c, d):
t01 = b | d
t02 = c | d
t03 = a & t01
t04 = b ^ t02
t05 = c ^ d
t06 = ~ t03 & 0xFFFFFFFF
t07 = a & t04
x = t05 ^ t07
t09 = x | t06
t10 = a ^ t07
t11 = t01 ^ t09
t12 = d ^ t04
t13 = c | t10
z = t03 ^ t12
t15 = a ^ t04
y = t11 ^ t13
w = t15 ^ t09
return w, x, y, z
def InvRND05(a, b, c, d):
t01 = a & d
t02 = c ^ t01
t03 = a ^ d
t04 = b & t02
t05 = a & c
w = t03 ^ t04
t07 = a & w
t08 = t01 ^ w
t09 = b | t05
t10 = ~ b & 0xFFFFFFFF
x = t08 ^ t09
t12 = t10 | t07
t13 = w | x
z = t02 ^ t12
t15 = t02 ^ t13
t16 = b ^ d
y = t16 ^ t15
return w, x, y, z
def InvRND06(a, b, c, d):
t01 = a ^ c
t02 = ~ c & 0xFFFFFFFF
t03 = b & t01
t04 = b | t02
t05 = d | t03
t06 = b ^ d
t07 = a & t04
t08 = a | t02
t09 = t07 ^ t05
x = t06 ^ t08
w = ~ t09 & 0xFFFFFFFF
t12 = b & w
t13 = t01 & t05
t14 = t01 ^ t12
t15 = t07 ^ t13
t16 = d | t02
t17 = a ^ x
z = t17 ^ t15
y = t16 ^ t14
return w, x, y, z
def InvRND07(a, b, c, d):
t01 = a & b
t02 = a | b
t03 = c | t01
t04 = d & t02
z = t03 ^ t04
t06 = b ^ t04
t07 = d ^ z
t08 = ~ t07 & 0xFFFFFFFF
t09 = t06 | t08
t10 = b ^ d
t11 = a | d
x = a ^ t09
t13 = c ^ t06
t14 = c & t11
t15 = d | x
t16 = t01 | t10
w = t13 ^ t15
y = t14 ^ t16
return w, x, y, z
def serpent_decrypt(ciphertext: bytearray, subkeys: List[int], swap: bool = False) -> bytes:
if swap:
a, b, c, d = unpack('<4L', ciphertext)
else:
d, c, b, a = unpack('>4L', ciphertext)
RNDS = [InvRND00, InvRND01, InvRND02, InvRND03, InvRND04, InvRND05, InvRND06, InvRND07]
a ^= subkeys[128]
b ^= subkeys[129]
c ^= subkeys[130]
d ^= subkeys[131]
w, x, y, z = InvRND07(a, b, c, d)
w ^= subkeys[124]
x ^= subkeys[125]
y ^= subkeys[126]
z ^= subkeys[127]
for k in range(30, -1, -1):
j = 4 * k
c = ROR(y, 22)
a = ROR(w, 5)
c = c ^ z ^ ((x<<7) & 0xFFFFFFFF)
a = a ^ x ^ z
d = ROR(z, 7)
b = ROR(x, 1)
d = d ^ c ^ ((a<<3) & 0xFFFFFFFF)
b = b ^ a ^ c
c = ROR(c, 3)
a = ROR(a, 13)
w, x, y, z = RNDS[k % 8](a, b, c, d)
w ^= subkeys[j + 0]
x ^= subkeys[j + 1]
y ^= subkeys[j + 2]
z ^= subkeys[j + 3]
if swap:
return pack('<4L', w, x, y, z)
else:
return pack('>4L', z, y, x, w)
Functions
def RND00(a, b, c, d)
-
Expand source code Browse git
def RND00(a, b, c, d): t01 = b ^ c t02 = a | d t03 = a ^ b z = t02 ^ t01 t05 = c | z t06 = a ^ d t07 = b | c t08 = d & t05 t09 = t03 & t07 y = t09 ^ t08 t11 = t09 & y t12 = c ^ d t13 = t07 ^ t11 t14 = b & t06 t15 = t06 ^ t13 w = ~ t15 & 0xFFFFFFFF t17 = w ^ t14 x = t12 ^ t17 return w, x, y, z
def RND01(a, b, c, d)
-
Expand source code Browse git
def RND01(a, b, c, d): t01 = a | d t02 = c ^ d t03 = ~ b & 0xFFFFFFFF t04 = a ^ c t05 = a | t03 t06 = d & t04 t07 = t01 & t02 t08 = b | t06 y = t02 ^ t05 t10 = t07 ^ t08 t11 = t01 ^ t10 t12 = y ^ t11 t13 = b & d z = ~ t10 & 0xFFFFFFFF x = t13 ^ t12 t16 = t10 | x t17 = t05 & t16 w = c ^ t17 return w, x, y, z
def RND02(a, b, c, d)
-
Expand source code Browse git
def RND02(a, b, c, d): t01 = a | c t02 = a ^ b t03 = d ^ t01 w = t02 ^ t03 t05 = c ^ w t06 = b ^ t05 t07 = b | t05 t08 = t01 & t06 t09 = t03 ^ t07 t10 = t02 | t09 x = t10 ^ t08 t12 = a | d t13 = t09 ^ x t14 = b ^ t13 z = ~ t09 & 0xFFFFFFFF y = t12 ^ t14 return w, x, y, z
def RND03(a, b, c, d)
-
Expand source code Browse git
def RND03(a, b, c, d): t01 = a ^ c t02 = a | d t03 = a & d t04 = t01 & t02 t05 = b | t03 t06 = a & b t07 = d ^ t04 t08 = c | t06 t09 = b ^ t07 t10 = d & t05 t11 = t02 ^ t10 z = t08 ^ t09 t13 = d | z t14 = a | t07 t15 = b & t13 y = t08 ^ t11 w = t14 ^ t15 x = t05 ^ t04 return w, x, y, z
def RND04(a, b, c, d)
-
Expand source code Browse git
def RND04(a, b, c, d): t01 = a | b t02 = b | c t03 = a ^ t02 t04 = b ^ d t05 = d | t03 t06 = d & t01 z = t03 ^ t06 t08 = z & t04 t09 = t04 & t05 t10 = c ^ t06 t11 = b & c t12 = t04 ^ t08 t13 = t11 | t03 t14 = t10 ^ t09 t15 = a & t05 t16 = t11 | t12 y = t13 ^ t08 x = t15 ^ t16 w = ~ t14 & 0xFFFFFFFF return w, x, y, z
def RND05(a, b, c, d)
-
Expand source code Browse git
def RND05(a, b, c, d): t01 = b ^ d t02 = b | d t03 = a & t01 t04 = c ^ t02 t05 = t03 ^ t04 w = ~ t05 & 0xFFFFFFFF t07 = a ^ t01 t08 = d | w t09 = b | t05 t10 = d ^ t08 t11 = b | t07 t12 = t03 | w t13 = t07 | t10 t14 = t01 ^ t11 y = t09 ^ t13 x = t07 ^ t08 z = t12 ^ t14 return w, x, y, z
def RND06(a, b, c, d)
-
Expand source code Browse git
def RND06(a, b, c, d): t01 = a & d t02 = b ^ c t03 = a ^ d t04 = t01 ^ t02 t05 = b | c x = ~ t04 & 0xFFFFFFFF t07 = t03 & t05 t08 = b & x t09 = a | c t10 = t07 ^ t08 t11 = b | d t12 = c ^ t11 t13 = t09 ^ t10 y = ~ t13 & 0xFFFFFFFF t15 = x & t03 z = t12 ^ t07 t17 = a ^ b t18 = y ^ t15 w = t17 ^ t18 return w, x, y, z
def RND07(a, b, c, d)
-
Expand source code Browse git
def RND07(a, b, c, d): t01 = a & c t02 = ~ d & 0xFFFFFFFF t03 = a & t02 t04 = b | t01 t05 = a & b t06 = c ^ t04 z = t03 ^ t06 t08 = c | z t09 = d | t05 t10 = a ^ t08 t11 = t04 & z x = t09 ^ t10 t13 = b ^ x t14 = t01 ^ x t15 = c ^ t05 t16 = t11 | t13 t17 = t02 | t14 w = t15 ^ t17 y = a ^ t16 return w, x, y, z
def make_subkeys(key, swap=False)
-
Expand source code Browse git
def make_subkeys(key: bytearray, swap: bool = False): if len(key) > 32: raise ValueError if swap: key = key[::-1] key = B'\0' * (-len(key) % 4) + key K = [0] * 132 L = len(key) // 4 for i, v in enumerate(reversed(unpack(F'>{L}L', key))): K[i] = v if L < 8: K[L] = 1 for i in range(8, 16): K[i] = ROL(K[i-8] ^ K[i-5] ^ K[i-3] ^ K[i-1] ^ PHI ^ (i-8), 11) K[:8] = K[8:16] for i in range(8, 132): K[i] = ROL(K[i-8] ^ K[i-5] ^ K[i-3] ^ K[i-1] ^ PHI ^ i, 11) RNDS = [RND00, RND01, RND02, RND03, RND04, RND05, RND06, RND07] for i, k in enumerate(range(3, -30, -1)): a, b = i * 4, (i + 1) * 4 K[a:b] = RNDS[k % 8](*K[a:b]) return K
def serpent_encrypt(plaintext, subkeys, swap=False)
-
Expand source code Browse git
def serpent_encrypt(plaintext: bytearray, subkeys: List[int], swap: bool = False) -> bytes: if swap: a, b, c, d = unpack('<4L', plaintext) else: d, c, b, a = unpack('>4L', plaintext) RNDS = [RND00, RND01, RND02, RND03, RND04, RND05, RND06, RND07] for k in range(31): j = k * 4 a ^= subkeys[j + 0] b ^= subkeys[j + 1] c ^= subkeys[j + 2] d ^= subkeys[j + 3] w, x, y, z = RNDS[k % 8](a, b, c, d) a = ROL(w, 13) c = ROL(y, 3) b = x ^ a ^ c d = z ^ c ^ ((a<<3) & 0xFFFFFFFF) b = ROL(b, 1) d = ROL(d, 7) a = a ^ b ^ d c = c ^ d ^ ((b<<7) & 0xFFFFFFFF) a = ROL(a, 5) c = ROL(c, 22) a ^= subkeys[124] b ^= subkeys[125] c ^= subkeys[126] d ^= subkeys[127] a, b, c, d = RND07(a, b, c, d) a ^= subkeys[128] b ^= subkeys[129] c ^= subkeys[130] d ^= subkeys[131] if swap: return pack('<4L', a, b, c, d) else: return pack('>4L', d, c, b, a)
def InvRND00(a, b, c, d)
-
Expand source code Browse git
def InvRND00(a, b, c, d): t01 = c ^ d t02 = a | b t03 = b | c t04 = c & t01 t05 = t02 ^ t01 t06 = a | t04 y = ~ t05 & 0xFFFFFFFF t08 = b ^ d t09 = t03 & t08 t10 = d | y x = t09 ^ t06 t12 = a | t05 t13 = x ^ t12 t14 = t03 ^ t10 t15 = a ^ c z = t14 ^ t13 t17 = t05 & t13 t18 = t14 | t17 w = t15 ^ t18 return w, x, y, z
def InvRND01(a, b, c, d)
-
Expand source code Browse git
def InvRND01(a, b, c, d): t01 = a ^ b t02 = b | d t03 = a & c t04 = c ^ t02 t05 = a | t04 t06 = t01 & t05 t07 = d | t03 t08 = b ^ t06 t09 = t07 ^ t06 t10 = t04 | t03 t11 = d & t08 y = ~ t09 & 0xFFFFFFFF x = t10 ^ t11 t14 = a | y t15 = t06 ^ x z = t01 ^ t04 t17 = c ^ t15 w = t14 ^ t17 return w, x, y, z
def InvRND02(a, b, c, d)
-
Expand source code Browse git
def InvRND02(a, b, c, d): t01 = a ^ d t02 = c ^ d t03 = a & c t04 = b | t02 w = t01 ^ t04 t06 = a | c t07 = d | w t08 = ~ d & 0xFFFFFFFF t09 = b & t06 t10 = t08 | t03 t11 = b & t07 t12 = t06 & t02 z = t09 ^ t10 x = t12 ^ t11 t15 = c & z t16 = w ^ x t17 = t10 ^ t15 y = t16 ^ t17 return w, x, y, z
def InvRND03(a, b, c, d)
-
Expand source code Browse git
def InvRND03(a, b, c, d): t01 = c | d t02 = a | d t03 = c ^ t02 t04 = b ^ t02 t05 = a ^ d t06 = t04 & t03 t07 = b & t01 y = t05 ^ t06 t09 = a ^ t03 w = t07 ^ t03 t11 = w | t05 t12 = t09 & t11 t13 = a & y t14 = t01 ^ t05 x = b ^ t12 t16 = b | t13 z = t14 ^ t16 return w, x, y, z
def InvRND04(a, b, c, d)
-
Expand source code Browse git
def InvRND04(a, b, c, d): t01 = b | d t02 = c | d t03 = a & t01 t04 = b ^ t02 t05 = c ^ d t06 = ~ t03 & 0xFFFFFFFF t07 = a & t04 x = t05 ^ t07 t09 = x | t06 t10 = a ^ t07 t11 = t01 ^ t09 t12 = d ^ t04 t13 = c | t10 z = t03 ^ t12 t15 = a ^ t04 y = t11 ^ t13 w = t15 ^ t09 return w, x, y, z
def InvRND05(a, b, c, d)
-
Expand source code Browse git
def InvRND05(a, b, c, d): t01 = a & d t02 = c ^ t01 t03 = a ^ d t04 = b & t02 t05 = a & c w = t03 ^ t04 t07 = a & w t08 = t01 ^ w t09 = b | t05 t10 = ~ b & 0xFFFFFFFF x = t08 ^ t09 t12 = t10 | t07 t13 = w | x z = t02 ^ t12 t15 = t02 ^ t13 t16 = b ^ d y = t16 ^ t15 return w, x, y, z
def InvRND06(a, b, c, d)
-
Expand source code Browse git
def InvRND06(a, b, c, d): t01 = a ^ c t02 = ~ c & 0xFFFFFFFF t03 = b & t01 t04 = b | t02 t05 = d | t03 t06 = b ^ d t07 = a & t04 t08 = a | t02 t09 = t07 ^ t05 x = t06 ^ t08 w = ~ t09 & 0xFFFFFFFF t12 = b & w t13 = t01 & t05 t14 = t01 ^ t12 t15 = t07 ^ t13 t16 = d | t02 t17 = a ^ x z = t17 ^ t15 y = t16 ^ t14 return w, x, y, z
def InvRND07(a, b, c, d)
-
Expand source code Browse git
def InvRND07(a, b, c, d): t01 = a & b t02 = a | b t03 = c | t01 t04 = d & t02 z = t03 ^ t04 t06 = b ^ t04 t07 = d ^ z t08 = ~ t07 & 0xFFFFFFFF t09 = t06 | t08 t10 = b ^ d t11 = a | d x = a ^ t09 t13 = c ^ t06 t14 = c & t11 t15 = d | x t16 = t01 | t10 w = t13 ^ t15 y = t14 ^ t16 return w, x, y, z
def serpent_decrypt(ciphertext, subkeys, swap=False)
-
Expand source code Browse git
def serpent_decrypt(ciphertext: bytearray, subkeys: List[int], swap: bool = False) -> bytes: if swap: a, b, c, d = unpack('<4L', ciphertext) else: d, c, b, a = unpack('>4L', ciphertext) RNDS = [InvRND00, InvRND01, InvRND02, InvRND03, InvRND04, InvRND05, InvRND06, InvRND07] a ^= subkeys[128] b ^= subkeys[129] c ^= subkeys[130] d ^= subkeys[131] w, x, y, z = InvRND07(a, b, c, d) w ^= subkeys[124] x ^= subkeys[125] y ^= subkeys[126] z ^= subkeys[127] for k in range(30, -1, -1): j = 4 * k c = ROR(y, 22) a = ROR(w, 5) c = c ^ z ^ ((x<<7) & 0xFFFFFFFF) a = a ^ x ^ z d = ROR(z, 7) b = ROR(x, 1) d = d ^ c ^ ((a<<3) & 0xFFFFFFFF) b = b ^ a ^ c c = ROR(c, 3) a = ROR(a, 13) w, x, y, z = RNDS[k % 8](a, b, c, d) w ^= subkeys[j + 0] x ^= subkeys[j + 1] y ^= subkeys[j + 2] z ^= subkeys[j + 3] if swap: return pack('<4L', w, x, y, z) else: return pack('>4L', z, y, x, w)