Exemplo n.º 1
0
    def decrypt(self,
                nonce: bytes,
                authed_ciphertext: bytes,
                data: bytes = b'') -> Bytes:
        """
        Decrypts `ciphertext`.

        Parameters:
            nonce             (bytes): Bytes-like nonce.
            authed_ciphertext (bytes): Bytes-like object to be decrypted.
            data              (bytes): Bytes-like additional data to be authenticated.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        from samson.utilities.runtime import RUNTIME

        authed_ciphertext = Bytes.wrap(authed_ciphertext)
        ciphertext, orig_tag = authed_ciphertext[:-16], authed_ciphertext[-16:]

        tag_mask = self.clock_ctr(nonce)
        data = Bytes.wrap(data)
        tag = self.auth(ciphertext, data, tag_mask)

        if not RUNTIME.compare_bytes(tag, orig_tag):
            raise Exception('Tag mismatch: authentication failed!')

        return self.ctr.decrypt(ciphertext)
Exemplo n.º 2
0
    def decrypt(self, ciphertext: bytes, unpad: bool=True) -> Bytes:
        """
        Decrypts `ciphertext`.
        
        Parameters:
            ciphertext (bytes): Bytes-like object to be decrypted.
            unpad       (bool): Unpads the plaintext with PKCS7.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        plaintext = b''
        ciphertext = Bytes.wrap(ciphertext)

        if len(ciphertext) % self.cipher.block_size != 0:
            raise Exception("Ciphertext is not a multiple of the block size")

        last_block = self.iv
        for block in get_blocks(ciphertext, self.cipher.block_size):
            enc_block = last_block ^ Bytes.wrap(self.cipher.decrypt(block))
            plaintext += enc_block
            last_block = block

        if unpad:
            plaintext = self.padder.unpad(plaintext)

        return plaintext
Exemplo n.º 3
0
    def derive(self, password: bytes, salt: bytes=None, format_output: bool=True) -> Bytes:
        """
        Derives the bcrypt hash.

        Parameters:
            password     (bytes): Password.
            salt         (bytes): Salt.
            format_output (bool): Whether or not to use bcrypt formatting or just output the hash.
        
        Returns:
            Bytes: Derived key/hash.
        """
        if not salt:
            salt = Bytes.random(16)

        salt = Bytes.wrap(salt)
        password = Bytes.wrap(password)
        bf = self.eks_blowfish_setup(salt, password)

        ciphertext = self.constant
        ecb = ECB(bf)

        for _ in range(64):
            ciphertext = ecb.encrypt(ciphertext)

        to_return = ciphertext[:self.output_size]
        if format_output:
            to_return = Bytes(f'${self.version}$'.encode('utf-8') + str(self.cost).zfill(2).encode('utf-8') + b'$' + bcrypt_b64_encode(salt) + bcrypt_b64_encode(ciphertext[:self.output_size]))

        return to_return
Exemplo n.º 4
0
    def verify(self, plaintext: bytes, signature: bytes) -> bool:
        """
        Verifies the `plaintext` against the `signature`.

        Parameters:
            plaintext (bytes): Plaintext to verify.
            signature (bytes): Signature to verify against plaintext.
        
        Returns:
            bool: Whether or not the plaintext is verified.
        """
        from samson.utilities.runtime import RUNTIME

        plaintext = Bytes.wrap(plaintext)
        signature = Bytes.wrap(signature).zfill((self.modulus_len + 7) // 8)
        mHash     = self.hash_obj.hash(plaintext)

        em_bits = self.modulus_len - 1
        em_len  = (em_bits + 7) // 8

        if em_len < (self.hash_obj.digest_size + self.salt_len + 2):
            return False

        if bytes([signature[-1]]) != b'\xbc':
            return False


        # Let maskedDB be the leftmost emLen - hLen - 1 octets of EM,
        #    and let H be the next hLen octets.
        mask_len  = em_len - self.hash_obj.digest_size - 1
        masked_db = signature[:mask_len]
        H         = signature[mask_len:mask_len + self.hash_obj.digest_size]

        # If the leftmost 8emLen - emBits bits of the leftmost octet in
        #    maskedDB are not all equal to zero, output "inconsistent" and
        #    stop.
        left_mask = (2**(len(masked_db) * 8) - 1) >> ((8 * em_len) - em_bits)
        if masked_db & left_mask != masked_db:
            return False

        db_mask = self.mgf(H, mask_len)
        DB      = masked_db ^ db_mask
        DB     &= left_mask

        # If the emLen - hLen - sLen - 2 leftmost octets of DB are not
        #    zero or if the octet at position emLen - hLen - sLen - 1 (the
        #    leftmost position is "position 1") does not have hexadecimal
        #    value 0x01, output "inconsistent" and stop.
        if DB[:em_len - self.hash_obj.digest_size - self.salt_len - 1].int() != 1:
            return False

        salt    = DB[-self.salt_len:] if self.salt_len else b''
        m_prime = b'\x00' * 8 + mHash + salt
        h_prime = self.hash_obj.hash(m_prime)

        return RUNTIME.compare_bytes(h_prime, H)
Exemplo n.º 5
0
    def test_vec1(self):
        key = Bytes.wrap(0x0001020304050607).zfill(8)
        plaintext = Bytes(0x00010203).zfill(4)[::-1]
        test_vector = Bytes.wrap(0x23A8D72E).zfill(4)

        self._run_test(key=key,
                       plaintext=plaintext,
                       test_vector=test_vector,
                       block_size=32,
                       num_rounds=16)
Exemplo n.º 6
0
    def test_vec2(self):
        key = Bytes.wrap(0x000102030405060708090A0B0C0D0E0F, 'big').zfill(16)
        plaintext = int.to_bytes(0x0001020304050607, 8, 'little')
        test_vector = Bytes.wrap(0x2A0EDC0E9431FF73).zfill(8)

        self._run_test(key=key,
                       plaintext=plaintext,
                       test_vector=test_vector,
                       block_size=64,
                       num_rounds=20)
Exemplo n.º 7
0
 def __init__(self, F: FunctionType, K1: bytes, K2: bytes = None):
     """
     Parameters:
         F   (func): Unkeyed pseudorandom permutation.
         K1 (bytes): Bytes-like object to key the cipher.
         K2 (bytes): (Optional) Bytes-like object to key the cipher.
     """
     self.F = F
     self.K1 = Bytes.wrap(K1)
     self.K2 = Bytes.wrap(K2 or K1)
     self.block_size = len(self.K1)
Exemplo n.º 8
0
    def test_vec3(self):
        key = Bytes.wrap(0x000102030405060708090A0B0C0D0E0F1011121314151617,
                         'big').zfill(24)
        plaintext = int.to_bytes(0x000102030405060708090A0B0C0D0E0F, 16,
                                 'little')
        test_vector = Bytes.wrap(0xA46772820EDBCE0235ABEA32AE7178DA).zfill(16)

        self._run_test(key=key,
                       plaintext=plaintext,
                       test_vector=test_vector,
                       block_size=128,
                       num_rounds=24)
    def execute(self, ciphertexts: list, iterations: int=3) -> list:
        """
        Executes the attack.
        
        Parameters:
            ciphertexts (list): List of bytes-like ciphertexts using the same keystream.
            iterations   (int): Number of iterations of the full-text analysis phase. Accuracy-time trade-off.

        Returns:
            list: List of recovered plaintexts.
        """
        min_size = min([len(ciphertext) for ciphertext in ciphertexts])

        same_size_ciphers = [ciphertext[:min_size] for ciphertext in ciphertexts]
        transposed_ciphers = [bytearray(transposed) for transposed in zip(*same_size_ciphers)]
        assert [bytearray(transposed) for transposed in zip(*transposed_ciphers)] == same_size_ciphers

        log.debug("Starting initial transposition analysis")

        # Transposition analysis first (transposition)
        transposed_plaintexts = []
        for cipher in RUNTIME.report_progress(transposed_ciphers, desc='Transposition analysis', unit='ciphers'):
            all_chars = {}
            for char in range(256):
                plaintext = Bytes(struct.pack('B', char)).stretch(len(cipher)) ^ cipher

                all_chars[char] = (self.analyzer.analyze(plaintext), plaintext)

            transposed_plaintexts.append(sorted(all_chars.items(), key=lambda kv: kv[1][0], reverse=True)[0][1][1])


        retransposed_plaintexts = [bytearray(transposed) for transposed in zip(*transposed_plaintexts)]

        log.debug("Starting full-text analysis on retransposed text")

        # Clean up with a character-by-character, higher-context analysis (retransposed)
        for j in RUNTIME.report_progress(range(iterations), desc='Higher-context analysis'):
            log.debug("Starting iteration {}/{}".format(j + 1, iterations))
            differential_mask = bytearray()

            for i in RUNTIME.report_progress(range(min_size), desc='Building differential mask', unit='bytes'):
                all_chars = {}

                for char in range(256):
                    full_text_analyses = []

                    for curr_cipher in retransposed_plaintexts:
                        cipher_copy = bytearray([_ for _ in curr_cipher])
                        cipher_copy[i] = ord(Bytes(struct.pack('B', char)) ^ struct.pack('B', curr_cipher[i]))

                        full_text_analyses.append(self.analyzer.analyze(cipher_copy))

                    all_chars[char] = (sum(full_text_analyses), char)

                best_char = sorted(all_chars.items(), key=lambda kv: kv[1][0], reverse=True)[0][1][1]
                differential_mask += struct.pack('B', best_char)

            retransposed_plaintexts = [Bytes.wrap(cipher) ^ differential_mask for cipher in retransposed_plaintexts]

        return retransposed_plaintexts
Exemplo n.º 10
0
    def __init__(self,
                 curve: TwistedEdwardsCurve = EdwardsCurve25519,
                 hash_obj: object = SHA512(),
                 d: int = None,
                 A: TwistedEdwardsPoint = None,
                 a: int = None,
                 h: bytes = None,
                 clamp: bool = True):
        """
        Parameters:
            curve (TwistedEdwardsCurve): Curve used for calculations.
            hash_obj           (object): Instantiated object with compatible hash interface.
            d                     (int): Private key.
            A     (TwistedEdwardsPoint): (Optional) Public point.
            a                     (int): (Optional) Public scalar.
            h                   (bytes): (Optional) Hashed private key.
            clamp                (bool): Whether or not to clamp the public scalar.
        """
        Primitive.__init__(self)

        self.B = curve.B
        self.curve = curve
        self.d = Bytes.wrap(d or max(1,
                                     Bytes.random(hash_obj.digest_size).int()))
        self.H = hash_obj

        self.h = h or hash_obj.hash(self.d)

        a = a or self.h[:self.curve.b // 8].int()
        self.a = curve.clamp_to_curve(a, True) if clamp else a

        self.A = A or self.B * self.a
Exemplo n.º 11
0
    def encrypt(self, plaintext: bytes) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        plaintext = Bytes.wrap(plaintext)
        block_size = self.underlying_mode.cipher.block_size
        pt_len = len(plaintext)

        assert pt_len > block_size
        pt_chunks = plaintext.chunk(block_size, allow_partials=True)

        padding_len = (block_size - (pt_len % block_size)) % block_size
        ciphertext_chunks = self.underlying_mode.encrypt(
            sum(pt_chunks[:-1]), pad=False).chunk(block_size)
        padding = ciphertext_chunks[-1][-padding_len:][:padding_len]

        last_block = self.underlying_mode.encrypt(pt_chunks[-1] + padding,
                                                  pad=False)

        return (sum(ciphertext_chunks[:-1]) + last_block +
                ciphertext_chunks[-1])[:pt_len]
Exemplo n.º 12
0
    def generate(self, message: bytes) -> Bytes:
        """
        Generates a keyed MAC for `message`.

        Parameters:
            message (bytes): Message to generate a MAC for.
        
        Returns:
            Bytes: The MAC.
        """
        message = Bytes.wrap(message)

        incomplete_block = len(message) % self.cipher.block_size
        message_chunks = message.chunk(self.cipher.block_size,
                                       allow_partials=True)

        if len(message_chunks) == 0:
            message_chunks = [Bytes(b'')]

        M_last = message_chunks[-1]

        if incomplete_block or not len(message):
            M_last += b'\x80'
            M_last = (M_last +
                      (b'\x00' *
                       (self.cipher.block_size - len(M_last)))) ^ self.k2
        else:
            M_last ^= self.k1

        return self.cbc_mac.generate(b''.join(message_chunks[:-1]) + M_last,
                                     pad=False)
Exemplo n.º 13
0
    def unpack(encoded_bytes: bytes, decryptor: FunctionType=None, already_unpacked: bool=False) -> (object, bytes):
        """
        Unpacks bytes into an DSAPrivateKey object.

        Parameters:
            encoded_bytes   (bytes): Bytes to be (partially?) decoded.
            already_unpacked (bool): Whether or not to do the initial length-decoding.
        
        Returns:
            (DSAPrivateKey, bytes): The decoded object and unused bytes.
        """
        encoded_bytes = Bytes.wrap(encoded_bytes)

        if already_unpacked:
            params, encoded_bytes = encoded_bytes, None
        else:
            params, encoded_bytes = PackedBytes('private_key').unpack(encoded_bytes)

        check_bytes, params = check_decrypt(params, decryptor)

        _header, params = PackedBytes('dsa-header').unpack(params)
        p, params = PackedBytes('p').unpack(params)
        q, params = PackedBytes('q').unpack(params)
        g, params = PackedBytes('g').unpack(params)
        y, params = PackedBytes('y').unpack(params)
        x, params = PackedBytes('x').unpack(params)
        host, params = PackedBytes('host').unpack(params)
        return DSAPrivateKey('private_key', check_bytes=check_bytes, p=p.int(), q=q.int(), g=g.int(), y=y.int(), x=x.int(), host=host), encoded_bytes
Exemplo n.º 14
0
    def decrypt(self, ciphertext: bytes) -> Bytes:
        """
        Decrypts `ciphertext`.

        Parameters:
            ciphertext (bytes): Bytes-like object to be decrypted.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        ciphertext = Bytes.wrap(ciphertext).zfill(self.block_size // 4)

        A = ciphertext[:self.block_size // 8].int()
        B = ciphertext[self.block_size // 8:].int()

        for i in range(self.num_rounds, 0, -1):
            B = right_rotate((B - self.S[2 * i + 1]) % self.mod,
                             A % self.block_size,
                             bits=self.block_size) ^ A
            A = right_rotate((A - self.S[2 * i]) % self.mod,
                             B % self.block_size,
                             bits=self.block_size) ^ B

        A = (A - self.S[0]) % self.mod
        B = (B - self.S[1]) % self.mod

        return Bytes(
            (Bytes(A, 'little').zfill(self.block_size // 8) +
             Bytes(B, 'little').zfill(self.block_size // 8)).int()).zfill(
                 self.block_size // 4)
Exemplo n.º 15
0
    def encrypt(self, plaintext: bytes) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        plaintext = Bytes.wrap(plaintext)
        M = plaintext.int()

        D1 = M >> 64
        D2 = M & MASK64

        D1 = D1 ^ self.kw[0]
        D2 = D2 ^ self.kw[1]

        num_super_rounds = 3 if len(self.key) == 16 else 4

        for i in range(num_super_rounds):
            if i > 0:
                D1 = FL   (D1, self.ke[(i-1) * 2])
                D2 = FLINV(D2, self.ke[(i-1) * 2 + 1])
            for j in range(0, 6, 2):
                D2 ^= self.F(D1, self.k[i*6 + j])
                D1 ^= self.F(D2, self.k[i*6 + j +1])


        D2 = D2 ^ self.kw[2]
        D1 = D1 ^ self.kw[3]

        return Bytes(((D2  & MASK64) << 64) | (D1 & MASK64)).zfill(16)
Exemplo n.º 16
0
    def internal_pmac(self, data):
        data = Bytes.wrap(data)

        data_chunks = data.chunk(self.cipher.block_size, allow_partials=True)

        offset = self.cipher.encrypt(Bytes(b'').zfill(self.cipher.block_size))
        offset = triple(offset)
        offset = triple(offset)

        checksum = Bytes(b'').zfill(self.cipher.block_size)

        for i in range(len(data_chunks) - 1):
            offset = dbl(offset)
            checksum ^= self.cipher.encrypt(offset ^ data_chunks[i])

        offset = dbl(offset)

        M_last = data_chunks[-1]

        if len(M_last) % self.cipher.block_size == 0:
            offset = triple(offset)
            checksum ^= M_last
        else:
            M_last += b'\x80'
            M_last  = (M_last + (b'\x00' * (self.cipher.block_size - len(M_last))))

            checksum ^= M_last
            offset = triple(offset)
            offset = triple(offset)

        return self.cipher.encrypt(offset ^ checksum)
Exemplo n.º 17
0
    def encrypt(self, plaintext: bytes) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        plaintext = Bytes.wrap(plaintext)[::-1]
        pt_chunks = [chunk.zfill(4).int() for chunk in plaintext.chunk(4)]

        # Whitening
        R = [pt_chunks[i] ^ self.K[i] for i in range(len(pt_chunks))]

        for i in range(ROUNDS):
            FR_0, FR_1 = self.F(R[0], R[1], i)
            R = [
                R[0], R[1],
                right_rotate(R[2] ^ FR_0, 1),
                left_rotate(R[3], 1) ^ FR_1
            ]

            R[0], R[2] = R[2], R[0]
            R[1], R[3] = R[3], R[1]

        R = [R[(i + 2) % 4] ^ self.K[i + 4] for i in range(len(pt_chunks))]

        return Bytes(b''.join([int.to_bytes(r, 4, 'little') for r in R]))
Exemplo n.º 18
0
    def encrypt(self, plaintext: bytes, pad: bool=True) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
            pad        (bool): Pads the plaintext with PKCS7.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        plaintext = Bytes.wrap(plaintext)

        if pad:
            plaintext = self.padder.pad(plaintext)


        if len(plaintext) % self.cipher.block_size != 0:
            raise Exception("Plaintext is not a multiple of the block size")

        ciphertext = Bytes(b'')
        last_block = self.iv

        for block in get_blocks(plaintext, self.cipher.block_size):
            enc_block = self.cipher.encrypt(bytes(last_block ^ block))
            ciphertext += enc_block
            last_block = enc_block

        return ciphertext
Exemplo n.º 19
0
    def execute(self, auth_data_a: bytes, ciphertext_a: bytes, tag_a: bytes,
                auth_data_b: bytes, ciphertext_b: bytes,
                tag_b: bytes) -> Bytes:
        """
        Executes the attack.
        
        Parameters:
            ciphertext (bytes): Bytes-like ciphertext generated by the system.

        Returns:
            Bytes: The key to the cipher.
        """
        auth_data_a, ciphertext_a, tag_a, auth_data_b, ciphertext_b, tag_b = [
            Bytes.wrap(item) for item in [
                auth_data_a, ciphertext_a, tag_a, auth_data_b, ciphertext_b,
                tag_b
            ]
        ]
        poly_a = gcm_to_poly(auth_data_a, ciphertext_a, tag_a)
        poly_b = gcm_to_poly(auth_data_b, ciphertext_b, tag_b)

        # 3 is the smallest factor of (2**128) - 1
        factors = (poly_a + poly_b).factor(subgroup_divisor=3)

        return [
            elem_to_int(candidate.coeffs[0]) for candidate in factors
            if candidate.degree() == 1
        ]
Exemplo n.º 20
0
    def unpack(encoded_bytes: bytes,
               already_unpacked: bool = False) -> (object, bytes):
        """
        Unpacks bytes into an ECDSAPublicKey object.

        Parameters:
            encoded_bytes   (bytes): Bytes to be (partially?) decoded.
            already_unpacked (bool): Whether or not to do the initial length-decoding.
        
        Returns:
            (ECDSAPublicKey, bytes): The decoded object and unused bytes.
        """
        encoded_bytes = Bytes.wrap(encoded_bytes)

        if already_unpacked:
            params, encoded_bytes = encoded_bytes, None
        else:
            params, encoded_bytes = PackedBytes('public_key').unpack(
                encoded_bytes)

        _header, params = PackedBytes('ecdsa-header').unpack(params)
        curve, params = PackedBytes('curve').unpack(params)
        x_y_bytes, params = PackedBytes('x_y_bytes').unpack(params)

        return ECDSAPublicKey('public_key', curve=curve,
                              x_y_bytes=x_y_bytes), encoded_bytes
Exemplo n.º 21
0
    def decrypt(self, ciphertext: bytes) -> Bytes:
        """
        Decrypts `ciphertext`.

        Parameters:
            ciphertext (bytes): Bytes-like object to be decrypted.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        ciphertext = Bytes.wrap(ciphertext)

        half = len(ciphertext) // 2
        L_i, R_i = ciphertext[:half].to_int(), ciphertext[half:].to_int()

        L_i ^= self.P[17]
        R_i ^= self.P[16]

        R_i, L_i = L_i, R_i

        for i in range(15, -1, -1):
            R_i, L_i = L_i, R_i

            R_i ^= round_func(
                    self.S[0][(L_i >> 24) & 0xFF],
                    self.S[1][(L_i >> 16) & 0xFF],
                    self.S[2][(L_i >> 8) & 0xFF],
                    self.S[3][L_i & 0xFF]
                ) & 0xFFFFFFFF

            L_i ^= self.P[i]
            L_i &= 0xFFFFFFFF

        return Bytes(L_i).zfill(4) + Bytes(R_i).zfill(4)
Exemplo n.º 22
0
    def unpad(self, plaintext: bytes, allow_mangers: bool=False, skip_label_check: bool=False) -> Bytes:
        """
        Unpads the `plaintext`.

        Parameters:
            plaintext       (bytes): Plaintext to pad.
            allow_mangers    (bool): Whether or not to explicitly help Manger's attack.
            skip_label_check (bool): Whether or not to skip checking the label.
        
        Returns:
            Bytes: Unpadded plaintext.
        """
        k = (self.modulus_len + 7) // 8
        h_len = self.hash_obj.digest_size
        plaintext = Bytes.wrap(plaintext).zfill(k)

        if allow_mangers:
            if plaintext[0] != 0:
                raise ValueError("First byte is not zero! ;)")

        masked_seed, masked_db = plaintext[1:(h_len + 1)], plaintext[(h_len + 1):]

        seed_mask = self.mgf(masked_db, h_len)
        seed = masked_seed ^ seed_mask

        db_mask = self.mgf(seed, k - h_len - 1)
        db = masked_db ^ db_mask

        l_hash, m = db[:h_len], db[h_len + db[h_len:].index(b'\x01') + 1:]
        if not skip_label_check and l_hash != self.hash_obj.hash(self.label):
            raise ValueError("Label hashes do not match")

        return m
Exemplo n.º 23
0
    def encrypt(self, plaintext: bytes) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        plaintext = Bytes.wrap(plaintext).zfill(self.block_size // 4)

        A = plaintext[self.block_size // 8:].int()
        B = plaintext[:self.block_size // 8].int()

        A = (A + self.S[0]) % self.mod
        B = (B + self.S[1]) % self.mod

        for i in range(1, self.num_rounds + 1):
            A = (left_rotate(A ^ B, B % self.block_size, bits=self.block_size)
                 + self.S[2 * i]) % self.mod
            B = (left_rotate(B ^ A, A % self.block_size, bits=self.block_size)
                 + self.S[2 * i + 1]) % self.mod

        return (Bytes(A, 'little').zfill(self.block_size // 8) +
                Bytes(B, 'little').zfill(self.block_size // 8))
Exemplo n.º 24
0
    def encrypt(self, plaintext: bytes, pad: bool=False) -> Bytes:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Bytes-like object to be encrypted.
            pad        (bool): Whether or not to use RFC5649 padding.
        
        Returns:
            Bytes: Resulting ciphertext.
        """
        iv = self.iv
        length = len(plaintext)
        plaintext = Bytes.wrap(plaintext)

        if pad:
            r = ((length) + 7) // 8
            plaintext = plaintext + ((r * 8) - length) * b'\x00'
            iv = self.iv + Bytes(length).zfill(4)

        A = iv
        R = plaintext.chunk(8)
        n = len(R)

        # RFC5649 specific
        if n == 1:
            return self.cipher.encrypt(iv + plaintext)

        for j in range(6):
            for i in range(n):
                ct = self.cipher.encrypt(A + R[i])
                A, R[i] = ct[:8], ct[8:]
                A ^= Bytes(n * j + i + 1).zfill(len(A))

        return A + b''.join(R)
Exemplo n.º 25
0
    def __init__(self,
                 h: int = 2,
                 p: int = DiffieHellman.MODP_1536,
                 key: bytes = None,
                 exp1: int = None,
                 exp2: int = None,
                 validate: bool = True):
        """
        Parameters:
            h         (int): Generator.
            p         (int): Prime modulus.
            key     (bytes): Secret.
            exp1      (int): First random exponent.
            exp2      (int): Second random exponent.
            validate (bool): Whether or not to validate challenges to prevent exploits.
        """
        self.h = h
        self.p = p
        self.key = Bytes.wrap(key).int() or Bytes.random(16).int()
        self.validate = validate

        # We do this explicitly with None so users can easily set these values to zero :)
        if exp1 is None:
            exp1 = Bytes.random(16).int()

        if exp2 is None:
            exp2 = Bytes.random(16).int()

        self.exp1 = exp1
        self.exp2 = exp2

        self.P_b = None

        self.P = None
        self.Q = None
Exemplo n.º 26
0
    def decrypt(self, ciphertext: bytes) -> Bytes:
        """
        Decrypts `ciphertext`.

        Parameters:
            ciphertext (bytes): Bytes-like object to be decrypted.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        plaintext = FeistelNetwork.decrypt(self, self.key, Bytes.wrap(ciphertext))

        half = len(plaintext) // 2
        plaintext = Bytes.wrap(plaintext)
        L_i, R_i = plaintext[:half], plaintext[half:]
        return R_i + L_i
Exemplo n.º 27
0
    def unpack(encoded_bytes: bytes,
               decryptor: FunctionType = None,
               already_unpacked: bool = False) -> (object, bytes):
        """
        Unpacks bytes into an ECDSAPrivateKey object.

        Parameters:
            encoded_bytes   (bytes): Bytes to be (partially?) decoded.
            already_unpacked (bool): Whether or not to do the initial length-decoding.
        
        Returns:
            (ECDSAPrivateKey, bytes): The decoded object and unused bytes.
        """
        encoded_bytes = Bytes.wrap(encoded_bytes)

        if already_unpacked:
            params, encoded_bytes = encoded_bytes, None
        else:
            params, encoded_bytes = PackedBytes('private_key').unpack(
                encoded_bytes)

        check_bytes, params = check_decrypt(params, decryptor)

        _header, params = PackedBytes('ecdsa-header').unpack(params)
        curve, params = PackedBytes('curve').unpack(params)
        x_y_bytes, params = PackedBytes('x_y_bytes').unpack(params)
        d, params = PackedBytes('d').unpack(params)
        host, params = PackedBytes('host').unpack(params)

        return ECDSAPrivateKey('private_key',
                               check_bytes=check_bytes,
                               curve=curve,
                               x_y_bytes=x_y_bytes,
                               d=d.int(),
                               host=host), encoded_bytes
Exemplo n.º 28
0
    def decrypt(self, ciphertext: bytes) -> Bytes:
        """
        Decrypts `ciphertext`.

        Parameters:
            ciphertext (bytes): Bytes-like object to be decrypted.
        
        Returns:
            Bytes: Resulting plaintext.
        """
        ciphertext = Bytes.wrap(ciphertext)
        ct_chunks = [
            chunk.zfill(4)[::-1].int() for chunk in ciphertext.chunk(4)
        ]

        # Dewhitening
        R = [ct_chunks[i] ^ self.K[i + 4] for i in range(len(ct_chunks))]

        for i in range(ROUNDS - 1, -1, -1):
            FR_0, FR_1 = self.F(R[0], R[1], i)
            R = [
                R[0], R[1],
                left_rotate(R[2], 1) ^ FR_0,
                right_rotate(R[3] ^ FR_1, 1)
            ]

            R[0], R[2] = R[2], R[0]
            R[1], R[3] = R[3], R[1]

        R = [R[(i + 2) % 4] ^ self.K[i] for i in range(len(ct_chunks))]

        return Bytes(b''.join([int.to_bytes(r, 4, 'little') for r in R]),
                     'little')[::-1]
Exemplo n.º 29
0
    def unpack(encoded_bytes: bytes,
               already_unpacked: bool = False) -> (object, bytes):
        """
        Unpacks bytes into an DSAPublicKey object.

        Parameters:
            encoded_bytes   (bytes): Bytes to be (partially?) decoded.
            already_unpacked (bool): Whether or not to do the initial length-decoding.
        
        Returns:
            (DSAPublicKey, bytes): The decoded object and unused bytes.
        """
        encoded_bytes = Bytes.wrap(encoded_bytes)

        if already_unpacked:
            params, encoded_bytes = encoded_bytes, None
        else:
            params, encoded_bytes = PackedBytes('public_key').unpack(
                encoded_bytes)

        _header, params = PackedBytes('dsa-header').unpack(params)
        p, params = PackedBytes('p').unpack(params)
        q, params = PackedBytes('q').unpack(params)
        g, params = PackedBytes('g').unpack(params)
        y, params = PackedBytes('y').unpack(params)

        if already_unpacked:
            encoded_bytes = params

        return DSAPublicKey('public_key',
                            p=p.int(),
                            q=q.int(),
                            g=g.int(),
                            y=y.int()), encoded_bytes
Exemplo n.º 30
0
 def __init__(self, key: bytes):
     """
     Parameters:
         key (bytes): Bytes-like object to key the cipher.
     """
     Primitive.__init__(self)
     self.key = Bytes.wrap(key)
     self.key_schedule = key_schedule
     self.round_func = round_func