Module refinery.units.crypto.cipher.rc6
Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import List, Optional
from math import log2
from refinery.units.crypto.cipher import StandardBlockCipherUnit, Arg
from refinery.units.crypto.cipher.rc5 import rc5constants
from refinery.lib import chunks
from refinery.lib.crypto import (
rotr,
rotl,
BlockCipher,
BlockCipherFactory,
CipherMode,
CipherInterface,
BufferType,
)
_W = 32
_R = 20
class RC6(BlockCipher):
block_size: int
key_size = range(256)
_S: List[int]
_w: int
_r: int
_u: int
_m: int
_g: int
__slots__ = '_S', '_w', '_r', '_u', '_m', '_g'
def __init__(self, key: BufferType, mode: Optional[CipherMode] = None, word_size: int = _W, rounds: int = _R):
if word_size < 8 or word_size % 8:
raise ValueError(F'Invalid word size: {word_size}')
self._w = word_size
self._u = word_size // 8
self._r = rounds
self._g = int(log2(word_size))
self._m = (1 << word_size) - 1
super().__init__(key, mode)
@property
def block_size(self):
return self._u * 4
def block_decrypt(self, block) -> BufferType:
u = self._u
w = self._w
g = self._g
r = self._r
M = self._m
S = self._S
A, B, C, D = chunks.unpack(block, u)
C = C - S[2 * r + 3] & M
A = A - S[2 * r + 2] & M
for i in range(r, 0, -1):
A, B, C, D = D, A, B, C
t = rotl(w, B * (2 * B + 1) & M, g)
v = rotl(w, D * (2 * D + 1) & M, g)
C = rotr(w, C - S[2 * i + 1] & M, t) ^ v
A = rotr(w, A - S[2 * i + 0] & M, v) ^ t
D = D - S[1] & M
B = B - S[0] & M
return chunks.pack((A, B, C, D), u)
def block_encrypt(self, block) -> BufferType:
u = self._u
w = self._w
g = self._g
r = self._r
M = self._m
S = self._S
A, B, C, D = chunks.unpack(block, u)
B = B + S[0] & M
D = D + S[1] & M
for i in range(1, r + 1):
t = rotl(w, B * (2 * B + 1) & M, g)
v = rotl(w, D * (2 * D + 1) & M, g)
A = rotl(w, A ^ t, v) + S[2 * i + 0] & M
C = rotl(w, C ^ v, t) + S[2 * i + 1] & M
A, B, C, D = B, C, D, A
A = A + S[2 * r + 2] & M
C = C + S[2 * r + 3] & M
return chunks.pack((A, B, C, D), u)
@property
def key(self):
return self._S
@key.setter
def key(self, key):
w = self._w # word size
u = self._u # length of a word in bytes
r = self._r # round count
M = self._m # bit mask
L = list(chunks.unpack(key + (-len(key) % u) * B'\0', u))
c = len(L)
t = 2 * (r + 2)
P, Q = rc5constants(w)
S = [P]
while len(S) < t:
S.append(S[~0] + Q & M)
i = j = 0
A = B = 0
for _ in range(3 * max(t, c)):
A = S[i] = rotl(w, S[i] + A + B & M, 3)
B = L[j] = rotl(w, L[j] + A + B & M, A + B)
i = (i + 1) % t
j = (j + 1) % c
self._S = S
class rc6(StandardBlockCipherUnit, cipher=BlockCipherFactory(RC6)):
"""
RC6 encryption and decryption. The parameter defaults are the RC6 parameters that were chosen
for the AES candidacy. Only key sizes of 128, 192, and 256 bits are used for AES candidates, but
the unit will allow any key size up to 256 bits.
"""
def __init__(
self, key, iv=b'', *, padding=None, mode=None, raw=False, little_endian=False, segment_size=0,
rounds : Arg.Number('-k', help='Number of rounds to use, the default is {default}') = _R,
word_size : Arg.Number('-w', help='The word size in bits, {default} by default.') = _W,
):
super().__init__(
key,
iv,
padding=padding,
mode=mode,
raw=raw,
little_endian=little_endian,
segment_size=segment_size,
rounds=rounds,
word_size=word_size
)
@property
def block_size(self):
return self.args.word_size // 2
def _new_cipher(self, **optionals) -> CipherInterface:
return super()._new_cipher(
rounds=self.args.rounds,
word_size=self.args.word_size,
**optionals
)
Classes
class RC6 (key, mode=None, word_size=32, rounds=20)
-
Abstract base class for refinery's block cipher interface.
Expand source code Browse git
class RC6(BlockCipher): block_size: int key_size = range(256) _S: List[int] _w: int _r: int _u: int _m: int _g: int __slots__ = '_S', '_w', '_r', '_u', '_m', '_g' def __init__(self, key: BufferType, mode: Optional[CipherMode] = None, word_size: int = _W, rounds: int = _R): if word_size < 8 or word_size % 8: raise ValueError(F'Invalid word size: {word_size}') self._w = word_size self._u = word_size // 8 self._r = rounds self._g = int(log2(word_size)) self._m = (1 << word_size) - 1 super().__init__(key, mode) @property def block_size(self): return self._u * 4 def block_decrypt(self, block) -> BufferType: u = self._u w = self._w g = self._g r = self._r M = self._m S = self._S A, B, C, D = chunks.unpack(block, u) C = C - S[2 * r + 3] & M A = A - S[2 * r + 2] & M for i in range(r, 0, -1): A, B, C, D = D, A, B, C t = rotl(w, B * (2 * B + 1) & M, g) v = rotl(w, D * (2 * D + 1) & M, g) C = rotr(w, C - S[2 * i + 1] & M, t) ^ v A = rotr(w, A - S[2 * i + 0] & M, v) ^ t D = D - S[1] & M B = B - S[0] & M return chunks.pack((A, B, C, D), u) def block_encrypt(self, block) -> BufferType: u = self._u w = self._w g = self._g r = self._r M = self._m S = self._S A, B, C, D = chunks.unpack(block, u) B = B + S[0] & M D = D + S[1] & M for i in range(1, r + 1): t = rotl(w, B * (2 * B + 1) & M, g) v = rotl(w, D * (2 * D + 1) & M, g) A = rotl(w, A ^ t, v) + S[2 * i + 0] & M C = rotl(w, C ^ v, t) + S[2 * i + 1] & M A, B, C, D = B, C, D, A A = A + S[2 * r + 2] & M C = C + S[2 * r + 3] & M return chunks.pack((A, B, C, D), u) @property def key(self): return self._S @key.setter def key(self, key): w = self._w # word size u = self._u # length of a word in bytes r = self._r # round count M = self._m # bit mask L = list(chunks.unpack(key + (-len(key) % u) * B'\0', u)) c = len(L) t = 2 * (r + 2) P, Q = rc5constants(w) S = [P] while len(S) < t: S.append(S[~0] + Q & M) i = j = 0 A = B = 0 for _ in range(3 * max(t, c)): A = S[i] = rotl(w, S[i] + A + B & M, 3) B = L[j] = rotl(w, L[j] + A + B & M, A + B) i = (i + 1) % t j = (j + 1) % c self._S = S
Ancestors
- BlockCipher
- CipherInterface
- abc.ABC
Instance variables
var key
-
Expand source code Browse git
@property def key(self): return self._S
Inherited members
class rc6 (key, iv=b'', *, padding=None, mode=None, raw=False, little_endian=False, segment_size=0, rounds=20, word_size=32)
-
RC6 encryption and decryption. The parameter defaults are the RC6 parameters that were chosen for the AES candidacy. Only key sizes of 128, 192, and 256 bits are used for AES candidates, but the unit will allow any key size up to 256 bits.
Expand source code Browse git
class rc6(StandardBlockCipherUnit, cipher=BlockCipherFactory(RC6)): """ RC6 encryption and decryption. The parameter defaults are the RC6 parameters that were chosen for the AES candidacy. Only key sizes of 128, 192, and 256 bits are used for AES candidates, but the unit will allow any key size up to 256 bits. """ def __init__( self, key, iv=b'', *, padding=None, mode=None, raw=False, little_endian=False, segment_size=0, rounds : Arg.Number('-k', help='Number of rounds to use, the default is {default}') = _R, word_size : Arg.Number('-w', help='The word size in bits, {default} by default.') = _W, ): super().__init__( key, iv, padding=padding, mode=mode, raw=raw, little_endian=little_endian, segment_size=segment_size, rounds=rounds, word_size=word_size ) @property def block_size(self): return self.args.word_size // 2 def _new_cipher(self, **optionals) -> CipherInterface: return super()._new_cipher( rounds=self.args.rounds, word_size=self.args.word_size, **optionals )
Ancestors
Class variables
var key_size
Instance variables
var block_size
-
Expand source code Browse git
@property def block_size(self): return self.args.word_size // 2
Inherited members