Пример #1
0
class RSA_AESTransport(BasePupyTransport):
    """
    Implements a transport that simply apply a RSA_AES to each byte
    """
    password     = None
    iterations   = 1000
    key_size     = 32
    rsa_key_size = 4096
    aes_size     = 256

    __slots__ = (
        'aes_size', 'key_size',
        '_iv_enc', '_iv_dec',
        'enc_cipher', 'dec_cipher',
        'aes_key', 'size_to_read',
        'first_block', 'buffer'
    )

    def __init__(self, *args, **kwargs):
        super(RSA_AESTransport, self).__init__(*args, **kwargs)
        if self.aes_size == 256:
            self.key_size = 32
        elif self.aes_size == 128:
            self.key_size = 16
        else:
            raise TransportError("Only AES 256 and 128 are supported")

        if Random:
            self._iv_enc = Random.new().read(BLOCK_SIZE)
        else:
            self._iv_enc = os.urandom(BLOCK_SIZE)

        self.enc_cipher = None
        self.dec_cipher = None
        self._iv_dec = None
        self.aes_key = None
        self.size_to_read = None
        self.first_block = b""
        self.buffer = Buffer()

    def upstream_recv(self, data):
        try:
            with data:
                lctext = len(data)
                ltotal = lctext + 4
                lremainder = ltotal % BLOCK_SIZE
                if lremainder:
                    ltotal += BLOCK_SIZE - lremainder

                data.insert(struct.pack('<I', lctext))
                data.truncate(ltotal)

                if __debug__:
                    logger.debug('Send: cleartext len = {} padded+header = {}'.format(lctext, len(data)))

                data.write_to(
                    self.downstream,
                    modificator=self.enc_cipher.encrypt,
                    chunk_size=CHUNK_SIZE)

        except Exception as e:
            logger.debug(e)

    def downstream_recv(self, data):
        try:
            if __debug__:
                logger.debug('Recv data len={}'.format(len(data)))

            if not self._iv_dec:
                if __debug__:
                    logger.debug('Read IV')

                if len(data) < BLOCK_SIZE:
                    if __debug__:
                        logger.debug('Read IV: Short read: {} < {}'.format(len(data), BLOCK_SIZE))
                    return

                self._iv_dec = data.read(BLOCK_SIZE)
                self.dec_cipher = NewAESCipher(self.aes_key, self._iv_dec)

            while True:
                if not self.size_to_read:
                    if len(data) < BLOCK_SIZE:
                        if __debug__:
                            logger.debug('Read chunk header: Short read: {} < {}'.format(len(data), BLOCK_SIZE))
                        break

                    self.first_block = self.dec_cipher.decrypt(data.read(BLOCK_SIZE))
                    self.size_to_read = struct.unpack_from('<I', self.first_block)[0]

                    if self.size_to_read == 0:
                        raise ValueError('Zero sized chunk')

                    if __debug__:
                        logger.debug('Read chunk header: expect: {}'.format(self.size_to_read))

                if self.size_to_read <= len(self.first_block) - 4:
                    if __debug__:
                        logger.debug('Read chunk: consume small chunk')
                    # the remaining data is padding, just drop it
                    self.upstream.write(self.first_block[4:4+self.size_to_read])
                    self.size_to_read = 0
                    self.first_block = b''
                    continue

                if self.first_block:
                    if __debug__:
                        logger.debug('Read chunk: start: cleartext len = {}'.format(self.size_to_read))

                    self.upstream.write(self.first_block[4:], notify=False)
                    self.size_to_read -= BLOCK_SIZE - 4
                    self.first_block = b''

                s = self.size_to_read

                if s % BLOCK_SIZE:
                    s += BLOCK_SIZE - (s % BLOCK_SIZE)

                lb = len(data)
                lb -= lb % BLOCK_SIZE

                while s and lb:
                    if __debug__:
                        logger.debug('Read chunk: required: {} available: {}'.format(s, lb))

                    to_read = min(s, CHUNK_SIZE)
                    to_read = min(lb, to_read)

                    cleartext = self.dec_cipher.decrypt(data.read(to_read))
                    s -= to_read
                    lb -= to_read

                    if to_read >= self.size_to_read:
                        self.upstream.write(cleartext[:self.size_to_read])
                        self.size_to_read = 0

                        if __debug__:
                            logger.debug('Read chunk: chunk finished')

                    else:
                        self.upstream.write(cleartext, notify=False)
                        self.size_to_read -= to_read

                if not lb:
                    if __debug__:
                        logger.debug('Read chunk: No more data')

                    break

        except:
            logger.debug(traceback.format_exc())
Пример #2
0
class AESTransport(BasePupyTransport):
    """
    Implements a transport that simply apply a AES to each byte
    """
    password=None
    iterations=1000
    key_size=32

    def __init__(self, *args, **kwargs):
        super(AESTransport, self).__init__(*args, **kwargs)
        if "password" in kwargs:
            self.password=kwargs["password"]
        if self.password is None:
            raise TransportError("A password needs to be supplied for AES")
        self._salt = "__PupY_PBKDF2_S4l7__"
        logging.debug("deriving the key with %s iterations..."%self.iterations)
        if PBKDF2 is not None:
            self._derived_key = PBKDF2(self.password, self._salt, self.key_size, self.iterations, prf=lambda password, salt: HMAC.new(password, salt, SHA256).digest())
        else:
            self._derived_key = pbkdf2_bin(self.password, self._salt, keylen=self.key_size, iterations=self.iterations, hashfunc=hashlib.sha256)
        logging.debug("key derived ...")
        if Random:
            self._iv_enc = Random.new().read(BLOCK_SIZE)
        else:
            self._iv_enc = os.urandom(BLOCK_SIZE)
        self.enc_cipher = NewAESCipher(self._derived_key, self._iv_enc)
        self.dec_cipher = None
        self._iv_dec = None
        self.size_to_read=None
        self.first_block=b""

    def on_connect(self):
        self.downstream.write(self._iv_enc) # send IV

    def upstream_recv(self, data):
        try:
            cleartext=data.peek()
            tosend=b""
            i=0
            packed_size=struct.pack("<I", len(cleartext))
            tosend=packed_size+cleartext
            tosend+=b"\x00"*(BLOCK_SIZE - (len(tosend)%BLOCK_SIZE))
            data.drain(len(cleartext))
            self.downstream.write(self.enc_cipher.encrypt(tosend))
        except Exception as e:
            logging.debug(e)

    def downstream_recv(self, data):
        try:
            enc=data.peek()
            if self._iv_dec is None: #receive IV
                if len(enc)<BLOCK_SIZE:
                    return
                self._iv_dec=enc[0:BLOCK_SIZE]
                self.dec_cipher = NewAESCipher(self._derived_key, self._iv_dec)
                data.drain(BLOCK_SIZE)
                enc=enc[BLOCK_SIZE:]
                if not enc:
                    return
            i=0
            cleartext=b""
            full_block=b""
            while True:
                if self.size_to_read is None:
                    if len(enc)<BLOCK_SIZE:
                        break
                    self.first_block=self.dec_cipher.decrypt(enc[0:BLOCK_SIZE])
                    data.drain(BLOCK_SIZE)
                    self.size_to_read=struct.unpack("<I", self.first_block[0:4])[0]
                    enc=enc[BLOCK_SIZE:]
                if self.size_to_read is None:
                    break
                if self.size_to_read <= len(self.first_block[4:]):
                    cleartext+=self.first_block[4:4+self.size_to_read] # the remaining data is padding, just drop it
                    self.size_to_read=None
                    self.first_block=b""
                    continue
                s=(self.size_to_read-len(self.first_block[4:]))
                blocks_to_read=s+(BLOCK_SIZE-(s%BLOCK_SIZE))
                if len(enc) < blocks_to_read:
                    break
                full_block=self.first_block[4:]+self.dec_cipher.decrypt(enc[:blocks_to_read])
                cleartext+=full_block[0:self.size_to_read] # the remaining data is padding, just drop it
                enc=enc[blocks_to_read:]
                data.drain(blocks_to_read)
                self.size_to_read=None
                self.first_block=b""
            self.upstream.write(cleartext)
        except Exception as e:
            logging.debug(traceback.format_exc())
Пример #3
0
class RSA_AESTransport(BasePupyTransport):
    """
    Implements a transport that simply apply a RSA_AES to each byte
    """
    password=None
    iterations=1000
    key_size=32
    rsa_key_size=4096
    aes_size=256
    def __init__(self, *args, **kwargs):
        super(RSA_AESTransport, self).__init__(*args, **kwargs)
        if self.aes_size==256:
            self.key_size=32
        elif self.aes_size==128:
            self.key_size=16
        else:
            raise TransportError("Only AES 256 and 128 are supported")
        if Random:
            self._iv_enc = Random.new().read(BLOCK_SIZE)
        else:
            self._iv_enc = os.urandom(BLOCK_SIZE)
        self.enc_cipher = None
        self.dec_cipher = None
        self._iv_dec = None
        self.aes_key=None
        self.size_to_read=None
        self.first_block=b""

    def upstream_recv(self, data):
        try:
            cleartext=data.peek()
            tosend=b""
            i=0
            packed_size=struct.pack("<I", len(cleartext))
            tosend=packed_size+cleartext
            tosend+=b"\x00"*(BLOCK_SIZE - (len(tosend)%BLOCK_SIZE))
            data.drain(len(cleartext))
            self.downstream.write(self.enc_cipher.encrypt(tosend))
        except Exception as e:
            logging.debug(e)


    def downstream_recv(self, data):
        try:
            enc=data.peek()
            if self._iv_dec is None: #receive IV
                if len(enc)<BLOCK_SIZE:
                    return
                self._iv_dec=enc[0:BLOCK_SIZE]
                self.dec_cipher = NewAESCipher(self.aes_key, self._iv_dec)
                data.drain(BLOCK_SIZE)
                enc=enc[BLOCK_SIZE:]
                if not enc:
                    return
            i=0
            cleartext=b""
            full_block=b""
            while True:
                if self.size_to_read is None:
                    if len(enc)<BLOCK_SIZE:
                        break
                    self.first_block=self.dec_cipher.decrypt(enc[0:BLOCK_SIZE])
                    data.drain(BLOCK_SIZE)
                    self.size_to_read=struct.unpack("<I", self.first_block[0:4])[0]
                    enc=enc[BLOCK_SIZE:]
                if self.size_to_read is None:
                    break
                if self.size_to_read <= len(self.first_block[4:]):
                    cleartext+=self.first_block[4:4+self.size_to_read] # the remaining data is padding, just drop it
                    self.size_to_read=None
                    self.first_block=b""
                    continue
                s=(self.size_to_read-len(self.first_block[4:]))
                blocks_to_read=s+(BLOCK_SIZE-(s%BLOCK_SIZE))
                if len(enc) < blocks_to_read:
                    break
                full_block=self.first_block[4:]+self.dec_cipher.decrypt(enc[:blocks_to_read])
                cleartext+=full_block[0:self.size_to_read] # the remaining data is padding, just drop it
                enc=enc[blocks_to_read:]
                data.drain(blocks_to_read)
                self.size_to_read=None
                self.first_block=b""
            self.upstream.write(cleartext)
        except Exception as e:
            logging.debug(traceback.format_exc())
Пример #4
0
class RSA_AESTransport(BasePupyTransport):
    """
    Implements a transport that simply apply a RSA_AES to each byte
    """
    password = None
    iterations = 1000
    key_size = 32
    rsa_key_size = 4096
    aes_size = 256

    def __init__(self, *args, **kwargs):
        super(RSA_AESTransport, self).__init__(*args, **kwargs)
        if self.aes_size == 256:
            self.key_size = 32
        elif self.aes_size == 128:
            self.key_size = 16
        else:
            raise TransportError("Only AES 256 and 128 are supported")
        if Random:
            self._iv_enc = Random.new().read(BLOCK_SIZE)
        else:
            self._iv_enc = os.urandom(BLOCK_SIZE)
        self.enc_cipher = None
        self.dec_cipher = None
        self._iv_dec = None
        self.aes_key = None
        self.size_to_read = None
        self.first_block = b""

    def on_connect(self):
        self.downstream.write(self._iv_enc)  # send IV
        logging.debug("IV sent to Client")

    def upstream_recv(self, data):
        try:
            cleartext = data.peek()
            tosend = b""
            i = 0
            packed_size = struct.pack("<I", len(cleartext))
            tosend = packed_size + cleartext
            tosend += b"\x00" * (BLOCK_SIZE - (len(tosend) % BLOCK_SIZE))
            data.drain(len(cleartext))
            self.downstream.write(self.enc_cipher.encrypt(tosend))
        except Exception as e:
            logging.debug(e)

    def downstream_recv(self, data):
        try:
            enc = data.peek()
            if self._iv_dec is None:  #receive IV
                if len(enc) < BLOCK_SIZE:
                    return
                self._iv_dec = enc[0:BLOCK_SIZE]
                self.dec_cipher = NewAESCipher(self.aes_key, self._iv_dec)
                data.drain(BLOCK_SIZE)
                enc = enc[BLOCK_SIZE:]
                if not enc:
                    return
            i = 0
            cleartext = b""
            full_block = b""
            while True:
                if self.size_to_read is None:
                    if len(enc) < BLOCK_SIZE:
                        break
                    self.first_block = self.dec_cipher.decrypt(
                        enc[0:BLOCK_SIZE])
                    data.drain(BLOCK_SIZE)
                    self.size_to_read = struct.unpack("<I",
                                                      self.first_block[0:4])[0]
                    enc = enc[BLOCK_SIZE:]
                if self.size_to_read is None:
                    break
                if self.size_to_read <= len(self.first_block[4:]):
                    cleartext += self.first_block[
                        4:4 + self.
                        size_to_read]  # the remaining data is padding, just drop it
                    self.size_to_read = None
                    self.first_block = b""
                    continue
                s = (self.size_to_read - len(self.first_block[4:]))
                blocks_to_read = s + (BLOCK_SIZE - (s % BLOCK_SIZE))
                if len(enc) < blocks_to_read:
                    break
                full_block = self.first_block[4:] + self.dec_cipher.decrypt(
                    enc[:blocks_to_read])
                cleartext += full_block[
                    0:self.
                    size_to_read]  # the remaining data is padding, just drop it
                enc = enc[blocks_to_read:]
                data.drain(blocks_to_read)
                self.size_to_read = None
                self.first_block = b""
            self.upstream.write(cleartext)
        except Exception as e:
            logging.debug(traceback.format_exc())