示例#1
0
 def __transform_cbc(self, data):
     len_data = len(data)
     if len_data % 8:
         raise VCryptoException('Input not aligned to blocksize')
     result = []
     start = 0
     while start < len_data:
         end = start + 8
         block = data[start:end]
         if self.__encrypt:
             if _pyver == 2:
                 indata = b''.join([
                     _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                     for a, b in zip(block, self.__iv)
                 ])
             else:
                 indata = bytes([a ^ b for a, b in zip(block, self.__iv)])
             cipher = self.__cipher.encipher(indata)
             self.__iv = cipher
             result.append(cipher)
         else:
             deciphered = self.__cipher.decipher(block)
             if _pyver == 2:
                 plaintext = b''.join([
                     _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                     for a, b in zip(deciphered, self.__iv)
                 ])
             else:
                 plaintext = bytes(
                     [a ^ b for a, b in zip(deciphered, self.__iv)])
             self.__iv = block
             result.append(plaintext)
         start += 8
     return b''.join(result)
示例#2
0
 def __transform_cbc(self, data):
     len_data = len(data)
     if len_data % self.__in_size:
         raise VCryptoException('Data not block aligned')
     result = []
     start = 0
     while start < len_data:
         end = start + self.__in_size
         block = data[start:end]
         if self.__encrypt:
             if _pyver == 2:
                 indata = b''.join([
                     _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                     for a, b in zip(block, self.__iv)
                 ])
             else:
                 indata = bytes([a ^ b for a, b in zip(block, self.__iv)])
             # Appending random data, similar to RSAES-PKCS1-V1_5-ENCRYPT
             _rand_data = self.__rand(8)
             indata = b''.join((b'\x02', indata, b'\x00', _rand_data))
             cipher = self.__block_transform(indata, self.__in_size + 10,
                                             self.__out_size)
             # Can only take plaintext size bytes as the carry-on mask
             self.__iv = cipher[:(self.__plainsize)]
             result.append(cipher)
         else:
             deciphered = self.__block_transform(block, self.__in_size,
                                                 self.__out_size + 10)
             if _pyver == 2:
                 if deciphered[0] != b'\x02' or deciphered[-9] != b'\x00':
                     raise VCryptoException('Invalid RSA ciphertext')
             else:
                 if deciphered[0] != 0x02 or deciphered[-9] != 0x00:
                     raise VCryptoException('Invalid RSA ciphertext')
             deciphered = deciphered[1:-8]
             if _pyver == 2:
                 plaintext = b''.join([
                     _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                     for a, b in zip(deciphered, self.__iv)
                 ])
             else:
                 plaintext = bytes(
                     [a ^ b for a, b in zip(deciphered, self.__iv)])
             # Can only take plaintext size bytes as the carry-on mask
             self.__iv = block[:(self.__plainsize)]
             result.append(plaintext)
         start += self.__in_size
     return b''.join(result)
示例#3
0
 def data(self, num_bytes):
     l = [0] * num_bytes
     for gen in self.__generators:
         data = [_b_ord(c) for c in gen(num_bytes)]
         for i in xrange(len(l)):
             l[i] ^= data[i]
     return b''.join([_s2b(_b_chr(n)) for n in l])
示例#4
0
    def primedata_to_number(self, prime_data):
        """Returns a candidate prime number associated with byte data.

        :param prime_data: data which may represents a prime
        :type  prime_data: bytes
        :returns:          number associated with prime_data
        :rtype:            int, long

        Sets the two most significant bits and the least significant
        bit of prime_data, before converting to an int or long.

        .. warning::

            This method does not perform any type of primality check,
            and it is the responsibility of the caller to check
            whether the returned number represents a prime.

        """
        bval = [_b_ord(c) for c in prime_data]
        bval[0] |= 0xc0
        bval[-1] |= 0x01
        if _pyver == 2:
            data = b''.join([_s2b(_b_chr(b)) for b in bval])
        else:
            data = bytes(bval)
        return bytes_to_posint(data)
示例#5
0
    def message(self, plaintext):
        """Returns an encrypted message for a provided plaintext.

        :param plaintext: the plaintext to encode and encrypt
        :type  plaintext: bytes
        :returns:         encrypted message-protected plaintext
        :rtype:           bytes
        :raises:          :exc:`versile.crypto.VCryptoException`

        Raises an exception if provided plaintext is longer than
        :attr:`max_plaintext_len`\ , meaning the plaintext is larger
        than what is allowed inside a single message. Empty plaintext
        is also not allowed.

        """
        plaintext_len = len(plaintext)
        if plaintext_len > self._max_plaintext_len:
            raise VCryptoException('Plaintext too long')
        elif not plaintext:
            raise VCryptoException('Empty plaintext not allowed')

        # Generate padding
        msg_len = 2 + plaintext_len + self._hash_len
        _bsize = self._plaintext_blocksize
        pad_len = msg_len % _bsize
        if pad_len:
            pad_len = _bsize - pad_len

        # Create message content
        encode_len = plaintext_len - 1
        if _pyver == 2:
            plain_len = (_s2b(_b_chr((encode_len & 0xff00) >> 8)) +
                         _s2b(_b_chr(encode_len & 0xff)))
        else:
            plain_len = bytes(
                (((encode_len & 0xff00) >> 8), (encode_len & 0xff)))
        padding = self._pad_provider(pad_len)
        _mac_msg = b''.join(
            (posint_to_bytes(self._msg_num), plain_len, plaintext, padding))
        msg_hash = self._hash_cls.hmac(self._mac_secret, _mac_msg)
        msg = b''.join((plain_len, plaintext, padding, msg_hash))

        # Create encrypted message
        enc_msg = self._encrypter(msg)
        self._msg_num += 1
        return enc_msg
示例#6
0
    def hmac(cls, secret, message):
        """Generates and returns a :term:`HMAC`

        :param secret:  secret key
        :type  secret:  bytes
        :param message: message
        :type  message: bytes
        :returns:       message authentication code
        :rtype:         bytes

        Implements :term:`HMAC` algorithm defined by :rfc:`2104`\ .

        """
        blocksize = cls.digest_size()
        if len(secret) > blocksize:
            secret = cls(secret).digest()
        elif len(secret) < blocksize:
            secret += (blocksize - len(secret)) * b'\x00'

        i_pad = blocksize * b'\x36'
        # TODO - TEMPORARY FIX FOR PYTHON 3 CONVERSION PROBLEM
        if _pyver == 3:
            inner = b''.join(
                _b_chr(_b_ord(a) ^ _b_ord(b)) for a, b in zip(secret, i_pad))
        else:
            inner = b''.join(
                _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                for a, b in zip(secret, i_pad))

        i_hash = cls(inner)
        i_hash.update(message)
        i_digest = i_hash.digest()

        o_pad = blocksize * b'\x5c'
        # TODO - TEMPORARY FIX FOR PYTHON 3 CONVERSION PROBLEM
        if _pyver == 3:
            outer = b''.join(
                _b_chr(_b_ord(a) ^ _b_ord(b)) for a, b in zip(secret, o_pad))
        else:
            outer = b''.join(
                _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                for a, b in zip(secret, o_pad))
        o_hash = cls(outer)
        o_hash.update(i_digest)
        return o_hash.digest()
示例#7
0
    def _increment(self, block):
        """Performs an increment of the previously generated block.

        :param block: input block
        :returns:     output block

        Default is interpret the input block as an integer and to
        increment it by '1'. Derived classes can override to implement
        a different incrementation strategy.

        """
        nums = [_b_ord(c) for c in block]
        for i in xrange((len(nums) - 1), -1, -1):
            if nums[i] == 255:
                nums[i] = 0
            else:
                nums[i] += 1
                break
        else:
            nums = [0] * len(nums)
        return b''.join([_s2b(_b_chr(n)) for n in nums])
示例#8
0
 def __transform_ofb(self, data):
     len_data = len(data)
     if len_data % 8:
         raise VCryptoException('Input not aligned to blocksize')
     result = []
     start = 0
     while start < len_data:
         end = start + 8
         block = data[start:end]
         # Same for encryption/decryption
         mask = self.__cipher.encipher(self.__iv)
         self.__iv = mask
         if _pyver == 2:
             cipher = b''.join([
                 _s2b(_b_chr(_b_ord(a) ^ _b_ord(b)))
                 for a, b in zip(block, mask)
             ])
         else:
             cipher = bytes([a ^ b for a, b in zip(block, mask)])
         result.append(cipher)
         start += 8
     return b''.join(result)
示例#9
0
    def _decipher_block(self, block):
        if not isinstance(block, bytes) or len(block) != 8:
            raise VCryptoException('Data block must be bytes of len 8')
        b_l = ((_b_ord(block[0]) << 24) + (_b_ord(block[1]) << 16) +
               (_b_ord(block[2]) << 8) + _b_ord(block[3]))
        b_r = ((_b_ord(block[4]) << 24) + (_b_ord(block[5]) << 16) +
               (_b_ord(block[6]) << 8) + _b_ord(block[7]))
        P, S = self.__P, self.__S

        for i in xrange(17, 1, -1):
            b_l ^= P[i]
            b_r ^= self.__feistel(b_l)
            b_l, b_r = b_r, b_l
        b_l, b_r = b_r, b_l
        b_r ^= P[1]
        b_l ^= P[0]

        bval = [(b_l >> 24), (b_l >> 16), (b_l >> 8), b_l, (b_r >> 24),
                (b_r >> 16), (b_r >> 8), b_r]
        if _pyver == 2:
            return b''.join([_s2b(_b_chr(b & 0xff)) for b in bval])
        else:
            return bytes([b & 0xff for b in bval])