Replace message encrypted structure with decrypted message structure

@param array              Hook arguments
@param rcube_message_part Part structure
@param int                Part size
974278
private function modify_structure(&$p, $struct, $size = 0)
    {
        // modify mime_parts property of the message object
        $old_id = $p['structure']->mime_id;

        foreach (array_keys($p['object']->mime_parts) as $idx) {
            if (!$old_id || $idx == $old_id || strpos($idx, $old_id . '.') === 0) {
                unset($p['object']->mime_parts[$idx]);
            }
        }

        // set some part params used by Roundcube core
        $struct->headers  = array_merge($p['structure']->headers, $struct->headers);
        $struct->size     = $size;
        $struct->filename = $p['structure']->filename;

        // modify the new structure to be correctly handled by Roundcube
        $this->modify_structure_part($struct, $p['object'], $old_id);

        // replace old structure with the new one
        $p['structure'] = $struct;
        $p['mimetype']  = $struct->mimetype;
    }
332893
private function get_part_body($msg, $part)
    {
        // @TODO: Handle big bodies using file handles

        // This is a special case when we want to get the whole body
        // using direct IMAP access, in other cases we prefer
        // rcube_message::get_part_body() as the body may be already in memory
        if (!$part->mime_id) {
            // fake the size which may be empty for multipart/* parts
            // otherwise get_message_part() below will fail
            if (!$part->size) {
                $reset = true;
                $part->size = 1;
            }

            $storage = $this->rc->get_storage();
            $body    = $storage->get_message_part($msg->uid, $part->mime_id, $part,
                null, null, true, 0, false);

            if ($reset) {
                $part->size = 0;
            }
        }
        else {
            $body = $msg->get_part_body($part->mime_id, false);

            // Convert charset to get rid of possible non-ascii characters (#5962)
            if ($part->charset && stripos($part->charset, 'ASCII') === false) {
                $body = rcube_charset::convert($body, $part->charset, 'US-ASCII');
            }
        }

        return $body;
    }
1289731
@Override
  public void part(int start, int end) {
    blockNumbers[count][0] = start;
    blockNumbers[count][1] = end - 1;
    count++;
  }
669378
private static byte[] secureRandom(int size) {
        if (size <= 0)
            throw new IllegalArgumentException("Size cannot be zero or less than zero.");

        SecureRandom secureRandom = new SecureRandom();
        byte[] bytes = new byte[size];
        secureRandom.nextBytes(bytes);
        return bytes;
    }
1213254
function decrypt_aes_cbc_sha1_padding(blockSize, output, decrypt) {
  var rval = true;
  if(decrypt) {
    /* The last byte in the output specifies the number of padding bytes not
      including itself. Each of the padding bytes has the same value as that
      last byte (known as the padding_length). Here we check all padding
      bytes to ensure they have the value of padding_length even if one of
      them is bad in order to ward-off timing attacks. */
    var len = output.length();
    var paddingLength = output.last();
    for(var i = len - 1 - paddingLength; i < len - 1; ++i) {
      rval = rval && (output.at(i) == paddingLength);
    }
    if(rval) {
      // trim off padding bytes and last padding length byte
      output.truncate(paddingLength + 1);
    }
  }
  return rval;
}
74620
protected function _putencryption()
    {
        $this->_put('/Filter /Standard');
        $this->_put('/V ' . ($this->revision === 3 ? '2' : '1'));
        $this->_put('/R ' . ($this->revision === 3 ? '3' : '2'));
        if ($this->revision === 3) {
            $this->_put('/Length 128');
        }
        $this->_put('/O (' . $this->_escape($this->oValue) . ')');
        $this->_put('/U (' . $this->_escape($this->uValue) . ')');
        $this->_put('/P ' . $this->pValue);
    }
1083892
function message_ready($p)
    {
        $savedraft      = !empty($_POST['_draft']) && empty($_GET['_saveonly']);
        $sign_enable    = (bool) rcube_utils::get_input_value('_enigma_sign', rcube_utils::INPUT_POST);
        $encrypt_enable = (bool) rcube_utils::get_input_value('_enigma_encrypt', rcube_utils::INPUT_POST);
        $pubkey_enable  = (bool) rcube_utils::get_input_value('_enigma_attachpubkey', rcube_utils::INPUT_POST);
        $locks          = (array) $this->rc->config->get('enigma_options_lock');

        if (in_array('sign', $locks)) {
            $sign_enable = (bool) $this->rc->config->get('enigma_sign_all');
        }
        if (in_array('encrypt', $locks)) {
            $encrypt_enable = (bool) $this->rc->config->get('enigma_encrypt_all');
        }
        if (in_array('pubkey', $locks)) {
            $pubkey_enable = (bool) $this->rc->config->get('enigma_attach_pubkey');
        }

        if (!$savedraft && $pubkey_enable) {
            $engine = $this->enigma->load_engine();
            $engine->attach_public_key($p['message']);
        }

        if ($encrypt_enable) {
            $engine = $this->enigma->load_engine();
            $mode   = !$savedraft && $sign_enable ? enigma_engine::ENCRYPT_MODE_SIGN : null;
            $status = $engine->encrypt_message($p['message'], $mode, $savedraft);
            $mode   = 'encrypt';
        }
        else if (!$savedraft && $sign_enable) {
            $engine = $this->enigma->load_engine();
            $status = $engine->sign_message($p['message'], enigma_engine::SIGN_MODE_MIME);
            $mode   = 'sign';
        }

        if ($mode && ($status instanceof enigma_error)) {
            $code = $status->getCode();

            if ($code == enigma_error::KEYNOTFOUND) {
                $vars = array('email' => $status->getData('missing'));
                $msg  = 'enigma.' . $mode . 'nokey';
            }
            else if ($code == enigma_error::BADPASS) {
                $this->password_prompt($status);
            }
            else {
                $msg = 'enigma.' . $mode . 'error';
            }

            if ($msg) {
                if ($vars && $vars['email']) {
                    $this->rc->output->command('enigma_key_not_found', array(
                            'email'  => $vars['email'],
                            'text'   => $this->rc->gettext(array('name' => $msg, 'vars' => $vars)),
                            'title'  => $this->enigma->gettext('keynotfound'),
                            'button' => $this->enigma->gettext('findkey'),
                    ));
                }
                else {
                    $this->rc->output->show_message($msg, 'error', $vars);
                }
            }

            $this->rc->output->send('iframe');
        }

        return $p;
    }
541944
function part_structure($p, $body = null)
    {
        if ($p['mimetype'] == 'text/plain' || $p['mimetype'] == 'application/pgp') {
            $this->parse_plain($p, $body);
        }
        else if ($p['mimetype'] == 'multipart/signed') {
            $this->parse_signed($p, $body);
        }
        else if ($p['mimetype'] == 'multipart/encrypted') {
            $this->parse_encrypted($p);
        }
        else if ($p['mimetype'] == 'application/pkcs7-mime') {
            $this->parse_encrypted($p);
        }

        return $p;
    }
289903
function decrypt(message) {
  if (this.secure && this.cipher && this.secret) {
    if (this.secret === 'secret') {
      console.warn('PLEASE change default secret password!');
    }
    debug('%s decrypt message with %s', this.name, this.cipher);
    var decipher = crypto.createDecipher(this.cipher, this.secret);
    return Buffer.concat([decipher.update(message), decipher.final()]);
  }
  return message;
}
788219
public void update(byte buffer[], int offset, int length)
	{
		int index, partlen, i, start;

		/* Length can be told to be shorter, but not inter */
		if ((length - offset) > buffer.length)
			length = buffer.length - offset;

		/* compute number of bytes mod 64 */
		index = (int) (state.count & 0x3f);
		state.count += length;

		partlen = 64 - index;

		if (length >= partlen)
		{
			int[] decode_buf = new int[16];
			if (partlen == 64)
			{
				partlen = 0;
			}
			else
			{
				for (i = 0; i < partlen; i++)
					state.buffer[i + index] = buffer[i + offset];
				transform(state, state.buffer, 0, decode_buf);
			}
			
			for (i = partlen; (i + 63) < length; i += 64)
			{
				transform(state, buffer, i + offset, decode_buf);
			}

			index = 0;
		}
		else
			i = 0;

		/* buffer remaining input */
		if (i < length)
		{
			start = i;
			for (; i < length; i++)
				state.buffer[index + i - start] = buffer[i + offset];
		}
	}
354232
function decryptCBC(userKey, chiperText) {
        if (utils.isAnArray(userKey) &&
          utils.isAnArray(chiperText)) {

          userKey = new Uint8Array(userKey);
          chiperText = new Uint8Array(chiperText);
        } else {

          throw 'Inputs must be an array';
        }
        userKey = makeKey(userKey);

        var result = []
          , loops = chiperText.length / BLOCK_SIZE
          , pos = 0
          , cBuffer = []
          , buffer1 = []
          , plain = []
          , vector = initializingVector
          , index = 0
          , secondIndex = 0
          , tmpCBuffer
          , nVal
          , position;

        for (; index < loops; index += 1) {

          cBuffer = chiperText.subarray(pos, pos + BLOCK_SIZE);
          if (cBuffer.length < BLOCK_SIZE) {

            tmpCBuffer = [];
            for (paddingIndex = 0; paddingIndex < BLOCK_SIZE; paddingIndex += 1) {

              nVal = cBuffer[paddingIndex];
              if (nVal !== undefined) {

                tmpCBuffer.push(nVal);
              } else {

                tmpCBuffer.push(0x00);
              }
            }
            cBuffer = tmpCBuffer;
          }
          buffer1 = blockDecrypt(cBuffer, 0, userKey);
          plain = xorBuffers(buffer1, vector);

          for (secondIndex = pos; secondIndex < plain.length + pos; secondIndex += 1) {

            position = secondIndex - pos;
            if (plain[position] !== undefined) {

              result.splice(secondIndex, 0, plain[position]);
            }
          }
          plain = [];
          vector = cBuffer;

          pos += BLOCK_SIZE;
        }

        return result;
      }
991017
def user_data_header parts_count, part_number
      return '' if parts_count == 1
      @concatenated_message_reference ||= rand((2**16)-1)
      udh =  '06' # Length of User Data Header
      udh << '08' # Concatenated short messages, 16-bit reference number
      udh << '04' # Length of the header, excluding the first two fields
      udh << "%04X" % @concatenated_message_reference
      udh << "%02X" % parts_count
      udh << "%02X" % part_number
      udh
    end
1263185
public function encrypt($message, $userPublicKey, $userAuthToken, $regenerateKeys = false)
    {
        if (self::MAX_MESSAGE_LENGTH < strlen($message)) {
            throw new \RuntimeException(sprintf(
                'Length of message must not be greater than %d octets.', self::MAX_MESSAGE_LENGTH
            ));
        }

        // pad the message
        $message = self::padMessage($message);

        if ($regenerateKeys) {
            $this->initialize();
        }

        $userPublicKey = Base64Url::decode($userPublicKey);
        $userAuthToken = Base64Url::decode($userAuthToken);

        // get the shared secret
        $sharedSecret = $this->getSharedSecret($userPublicKey);

        $ikm = !empty($userAuthToken) ?
            self::hkdf($userAuthToken, $sharedSecret, 'Content-Encoding: auth'.chr(0), 32) :
            $sharedSecret;

        $context = $this->createContext($userPublicKey);

        // derive the Content Encryption Key
        $contentEncryptionKey = self::hkdf($this->salt, $ikm, self::createInfo('aesgcm', $context), 16);

        // derive the nonce
        $nonce = self::hkdf($this->salt, $ikm, self::createInfo('nonce', $context), 12);

        if (version_compare(PHP_VERSION, '7.1') >= 0) {
            $encryptedText = openssl_encrypt($message, 'aes-128-gcm', $contentEncryptionKey, OPENSSL_RAW_DATA, $nonce, $tag);
        } else {
            list($encryptedText, $tag) = \AESGCM\AESGCM::encrypt($contentEncryptionKey, $nonce, $message, '');
        }

        return $encryptedText.$tag;
    }
497560
protected function normalizeParts(array $parts)
    {
        $blockSize = $this->getPartSize();
        $callback  = function ($value) {
            return Util::safeStrlen($value);
        };
        $maxSize = max(array_map($callback, $parts));
        if ($maxSize % $blockSize != 0) {
            $maxSize += $blockSize - ($maxSize % $blockSize);
        }
        foreach ($parts as &$part) {
            $part = $this->str_pad($part, $maxSize, chr(0));
            $part = str_split($part, $blockSize);
        }

        return $parts;
    }
438825
private DiffPart decodePaste(final int blockSize_S, final int blockSize_B,
			final BitReader r)
		throws DecodingException
	{

		if (blockSize_S < 1 || blockSize_B < 1) {
			throw new DecodingException("Invalid value for blockSize_S: "
					+ blockSize_S + " or blockSize_B: " + blockSize_B);
		}

		int s = r.read(blockSize_S);
		int b = r.read(blockSize_B);

		DiffPart part = new DiffPart(DiffAction.PASTE);
		part.setStart(s);
		part.setText(Integer.toString(b));

		r.skip();

		return part;
	}
1183675
private static function decryptBlock($input, $key, $size){
		$output = array();
		$block = array(); /* the 128 bit block to decode */
		$nbrRounds = self::numberOfRounds($size);
		/* Set the block values, for the block:
		 * a0,0 a0,1 a0,2 a0,3
		 * a1,0 a1,1 a1,2 a1,3
		 * a2,0 a2,1 a2,2 a2,3
		 * a3,0 a3,1 a3,2 a3,3
		 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
		 */
		for ($i = 0; $i < 4; $i++) /* iterate over the columns */
			for ($j = 0; $j < 4; $j++) /* iterate over the rows */
				$block[($i+($j*4))] = $input[($i*4)+$j];
		/* expand the key into an 176, 208, 240 bytes key */
		$expandedKey = self::expandKey($key, $size);
		/* decrypt the block using the expandedKey */
		$block = self::invMain($block, $expandedKey, $nbrRounds);
		for ($k = 0; $k < 4; $k++)/* unmap the block again into the output */
			for ($l = 0; $l < 4; $l++)/* iterate over the rows */
				$output[($k*4)+$l] = $block[($k+($l*4))];
		return $output;
	}
610753
private void encodeDelete(final DiffPart part)
		throws EncodingException
	{

		// C
		data.writeBit(0);
		data.writeBit(1);
		data.writeBit(1);

		// S
		data.writeValue(codecData.getBlocksizeS(), part.getStart());

		// E
		data.writeValue(codecData.getBlocksizeE(), part.getLength());

		data.writeFillBits();
	}