Module refinery.units.crypto.cipher.speck

Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
from typing import List, Optional, ClassVar, Dict

from refinery.lib.speck import (
    speck_encrypt32,
    speck_encrypt64,
    speck_decrypt32,
    speck_decrypt64,
    Speck6496KeySchedule,
    Speck64128KeySchedule,
    Speck128128KeySchedule,
    Speck128192KeySchedule,
    Speck128256KeySchedule,
)

from refinery.units.crypto.cipher import (
    Arg,
    StandardBlockCipherUnit,
)
from refinery.lib.crypto import (
    BlockCipher,
    BlockCipherFactory,
    BufferType,
    CipherInterface,
    CipherMode,
)


class Speck(BlockCipher):

    block_size: int
    key_size = frozenset((12, 16, 24, 32))

    _round_keys: List[int]
    _rounds: int

    _ROUND_BY_BLOCK_AND_KEY_SIZE: ClassVar[Dict[int, Dict[int, int]]] = {
        8: {12: 26, 16: 27},
        16: {16: 32, 24: 33, 32: 34}
    }

    @property
    def key(self):
        return self._key

    @key.setter
    def key(self, key: bytes):
        self._key = key
        block_size = self.block_size
        key_length = len(key)
        rounds = self._ROUND_BY_BLOCK_AND_KEY_SIZE[block_size][key_length]
        self._rounds = rounds
        if block_size == 16:
            if key_length == 16:
                self._round_keys = Speck128128KeySchedule(key)
            elif key_length == 24:
                self._round_keys = Speck128192KeySchedule(key)
            elif key_length == 32:
                self._round_keys = Speck128256KeySchedule(key)
        elif block_size == 8:
            if key_length == 12:
                self._round_keys = Speck6496KeySchedule(key)
            elif key_length == 16:
                self._round_keys = Speck64128KeySchedule(key)

    def __init__(self, key: BufferType, mode: Optional[CipherMode], block_size: int = 16):
        self.block_size = block_size
        super().__init__(key, mode)

    def block_decrypt(self, block) -> BufferType:
        block_size = self.block_size
        if block_size == 16:
            return speck_decrypt64(block, self._round_keys, self._rounds)
        else:
            return speck_decrypt32(block, self._round_keys, self._rounds)

    def block_encrypt(self, block) -> BufferType:
        block_size = self.block_size
        if block_size == 16:
            return speck_encrypt64(block, self._round_keys, self._rounds)
        else:
            return speck_encrypt32(block, self._round_keys, self._rounds)


class speck(StandardBlockCipherUnit, cipher=BlockCipherFactory(Speck)):
    """
    SPECK encryption and decryption. It supports block sizes of 8 and 16 bytes.
    """
    def __init__(
        self, key, iv=b'', padding=None, mode=None, raw=False,
        block_size: Arg.Number('-b', help='Cipher block size, default is {default}. Valid choices are 8 and 16.') = 16,
        **more
    ):
        return super().__init__(key, iv, padding=padding, mode=mode, raw=raw, block_size=block_size, **more)

    @property
    def block_size(self):
        return self.args.block_size

    def _new_cipher(self, **optionals) -> CipherInterface:
        return super()._new_cipher(block_size=self.args.block_size, **optionals)

Classes

class Speck (key, mode, block_size=16)

Abstract base class for refinery's block cipher interface.

Expand source code Browse git
class Speck(BlockCipher):

    block_size: int
    key_size = frozenset((12, 16, 24, 32))

    _round_keys: List[int]
    _rounds: int

    _ROUND_BY_BLOCK_AND_KEY_SIZE: ClassVar[Dict[int, Dict[int, int]]] = {
        8: {12: 26, 16: 27},
        16: {16: 32, 24: 33, 32: 34}
    }

    @property
    def key(self):
        return self._key

    @key.setter
    def key(self, key: bytes):
        self._key = key
        block_size = self.block_size
        key_length = len(key)
        rounds = self._ROUND_BY_BLOCK_AND_KEY_SIZE[block_size][key_length]
        self._rounds = rounds
        if block_size == 16:
            if key_length == 16:
                self._round_keys = Speck128128KeySchedule(key)
            elif key_length == 24:
                self._round_keys = Speck128192KeySchedule(key)
            elif key_length == 32:
                self._round_keys = Speck128256KeySchedule(key)
        elif block_size == 8:
            if key_length == 12:
                self._round_keys = Speck6496KeySchedule(key)
            elif key_length == 16:
                self._round_keys = Speck64128KeySchedule(key)

    def __init__(self, key: BufferType, mode: Optional[CipherMode], block_size: int = 16):
        self.block_size = block_size
        super().__init__(key, mode)

    def block_decrypt(self, block) -> BufferType:
        block_size = self.block_size
        if block_size == 16:
            return speck_decrypt64(block, self._round_keys, self._rounds)
        else:
            return speck_decrypt32(block, self._round_keys, self._rounds)

    def block_encrypt(self, block) -> BufferType:
        block_size = self.block_size
        if block_size == 16:
            return speck_encrypt64(block, self._round_keys, self._rounds)
        else:
            return speck_encrypt32(block, self._round_keys, self._rounds)

Ancestors

Instance variables

var key
Expand source code Browse git
@property
def key(self):
    return self._key

Inherited members

class speck (key, iv=b'', padding=None, mode=None, raw=False, block_size=16, *, assoc_len=0, mac_len=0, segment_size=0, little_endian=False)

SPECK encryption and decryption. It supports block sizes of 8 and 16 bytes.

Expand source code Browse git
class speck(StandardBlockCipherUnit, cipher=BlockCipherFactory(Speck)):
    """
    SPECK encryption and decryption. It supports block sizes of 8 and 16 bytes.
    """
    def __init__(
        self, key, iv=b'', padding=None, mode=None, raw=False,
        block_size: Arg.Number('-b', help='Cipher block size, default is {default}. Valid choices are 8 and 16.') = 16,
        **more
    ):
        return super().__init__(key, iv, padding=padding, mode=mode, raw=raw, block_size=block_size, **more)

    @property
    def block_size(self):
        return self.args.block_size

    def _new_cipher(self, **optionals) -> CipherInterface:
        return super()._new_cipher(block_size=self.args.block_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.block_size

Inherited members