Handler for PGP/MIME signed message.
Verifies signature.

@param array  Reference to hook's parameters
@param string Part body (will be set if used internally)
548873
private function parse_pgp_signed(&$p, $body = null)
    {
        if (!$this->rc->config->get('enigma_signatures', true)) {
            return;
        }

        if ($this->rc->action != 'show' && $this->rc->action != 'preview' && $this->rc->action != 'print') {
            return;
        }

        $this->load_pgp_driver();
        $struct = $p['structure'];

        $msg_part = $struct->parts[0];
        $sig_part = $struct->parts[1];

        // Get bodies
        if ($body === null) {
            if (!$struct->body_modified) {
                $body = $this->get_part_body($p['object'], $struct);
            }
        }

        $boundary = $struct->ctype_parameters['boundary'];

        // when it is a signed message forwarded as attachment
        // ctype_parameters property will not be set
        if (!$boundary && $struct->headers['content-type']
            && preg_match('/boundary="?([a-zA-Z0-9\'()+_,-.\/:=?]+)"?/', $struct->headers['content-type'], $m)
        ) {
            $boundary = $m[1];
        }

        // set signed part body
        list($msg_body, $sig_body) = $this->explode_signed_body($body, $boundary);

        // Verify
        if ($sig_body && $msg_body) {
            $sig = $this->pgp_verify($msg_body, $sig_body);

            // Store signature data for display
            $this->signatures[$struct->mime_id] = $sig;
            $this->signatures[$msg_part->mime_id] = $sig;
        }
    }
1162023
function parse_encrypted(&$p)
    {
        $struct = $p['structure'];

        // S/MIME
        if ($p['mimetype'] == 'application/pkcs7-mime') {
            $this->parse_smime_encrypted($p);
        }
        // PGP/MIME: RFC3156
        // The multipart/encrypted MUST consist of exactly two parts. The first
        // MIME body part must have a content type of "application/pgp-encrypted".
        // This body contains the control information.
        // The second MIME body part MUST contain the actual encrypted data.  It
        // must be labeled with a content type of "application/octet-stream".
        else if (count($struct->parts) == 2
            && $struct->parts[0] && $struct->parts[0]->mimetype == 'application/pgp-encrypted'
            && $struct->parts[1] && $struct->parts[1]->mimetype == 'application/octet-stream'
        ) {
            $this->parse_pgp_encrypted($p);
        }
    }
1127593
protected function _sign_aliyun($params = array(),$method=self::METHOD){
    if (isset($params['sign_mode']) && $params['sign_mode'] == 1) {
      unset($params['items']);
    }
    $params = $this->_params_filter($params);
    $query = '';
    $arg = '';
    if(is_array($params) && !empty($params)){
        foreach($params as $key => $val) {
            $arg .= $this->_percentEncode($key) . "=" . $this->_percentEncode($val) . "&";
        }
      $query = substr($arg, 0, strlen($arg) - 2);
    }
    $base_string = strtoupper($method).'&%2F&' .$this->_percentEncode($query);
    return base64_encode(hash_hmac('sha1', $base_string, $this->secret."&", true));
  }
392650
private function decodeBody(Part $part)
    {
        $content = '';

        $contentTransferEncoding = '7-bit';
        $contentCharset = 'auto';
        $headers                 = $part->getHeaders();
        if (!empty($headers)) {
            if ($headers->has('Content-Transfer-Encoding')) {
                $contentTransferEncodingHeader = $headers->get('Content-Transfer-Encoding');
                if (is_a($contentTransferEncodingHeader, 'ArrayIterator')) {
                    /*
                     * Multiple transfer encoding headers don't really make sense and are
                     * indicative of a malformed message. Just choose the first one and hope
                     * it works.
                     */
                    $contentTransferEncodingHeader = $headers->get('Content-Transfer-Encoding')[0];
                }

                $contentTransferEncoding = $contentTransferEncodingHeader->getFieldValue();
            }

            if ($this->hasHeader($part, 'Content-Type')) {
                $newContentCharset = $this
                    ->getContentType($part)
                    ->getParameter('charset');


                if (!empty($newContentCharset)
                    && in_array($this->prepareEncodingName($newContentCharset), $this->knownCharsets)
                ) {
                    $contentCharset = $newContentCharset;
                }
            }
        }

        switch ($contentTransferEncoding) {
            case 'base64':
                $content = base64_decode($part->getContent());
                break;

            case 'quoted-printable':
                $content = quoted_printable_decode($part->getContent());
                break;

            default:
                try {
                    $content = $part->getContent();
                } catch (Exception $e) {
                    /*
                     * do nothing, email has not content, there is not function
                     * to check if the email is empty and $content is already
                     * set to an empty string
                     */
                }

                break;
        }

        /*
         * mb_convert_encoding might produce warnings/error if the $contentCharset is wrong.
         * mb_check_encoding for some reason doesn't fail those cases, so there's no way
         * to check if the encoding is correct.
         *
         * Using a custom error handler allows marking the part as problematic when
         * mb_convert_encoding produces a warning, while preventing a php-internal warning.
         *
         * This way, log files won't get cluttered and there's an easy way to deal with the
         * problematic parts.
         */
        $hasError = false;

        set_error_handler(function($errorLevel, $errorMessage) use (&$hasError) {
            $hasError = true;

            return true;
        }, E_ALL);

        $convertedContent = mb_convert_encoding($content, 'UTF-8', $contentCharset);

        restore_error_handler();

        if ($hasError) {
            throw new UnexpectedValueException('Content: ' . $content, ParsedMail::INVALID_CHARSET_ERROR_CODE);
        }

        return trim($convertedContent);
    }
510344
private function resolveBody(Message $part)
    {
        $body = $part->getBody();
        foreach ($part->getParameters() as $search => $replace) {
            $body = str_replace($search, $replace, $body);
        }

        return $body;
    }
686543
private function verifySignature($body, $signature)
    {
        $expectedSignature = base64_encode(hash_hmac('sha1', $body, $this->secretKey, true));

        if ($signature !== $expectedSignature) {
            throw new InvalidSignatureException('The request signature was invalid');
        }
    }
367952
function sign_message(&$message, $mode = null)
    {
        $mime = new enigma_mime_message($message, enigma_mime_message::PGP_SIGNED);
        $from = $mime->getFromAddress();

        // find private key
        $key = $this->find_key($from, true);

        if (empty($key)) {
            return new enigma_error(enigma_error::KEYNOTFOUND);
        }

        // check if we have password for this key
        $passwords = $this->get_passwords();
        $pass      = $passwords[$key->id];

        if ($pass === null) {
            // ask for password
            $error = array('missing' => array($key->id => $key->name));
            return new enigma_error(enigma_error::BADPASS, '', $error);
        }

        $key->password = $pass;

        // select mode
        switch ($mode) {
        case self::SIGN_MODE_BODY:
            $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR;
            break;

        case self::SIGN_MODE_MIME:
            $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
            break;

        default:
            if ($mime->isMultipart()) {
                $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
            }
            else {
                $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR;
            }
        }

        // get message body
        if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) {
            // in this mode we'll replace text part
            // with the one containing signature
            $body = $message->getTXTBody();

            $text_charset = $message->getParam('text_charset');
            $line_length  = $this->rc->config->get('line_length', 72);

            // We can't use format=flowed for signed messages
            if (strpos($text_charset, 'format=flowed')) {
                list($charset, $params) = explode(';', $text_charset);
                $body = rcube_mime::unfold_flowed($body);
                $body = rcube_mime::wordwrap($body, $line_length, "\r\n", false, $charset);

                $text_charset = str_replace(";\r\n format=flowed", '', $text_charset);
            }
        }
        else {
            // here we'll build PGP/MIME message
            $body = $mime->getOrigBody();
        }

        // sign the body
        $result = $this->pgp_sign($body, $key, $pgp_mode);

        if ($result !== true) {
            if ($result->getCode() == enigma_error::BADPASS) {
                // ask for password
                $error = array('bad' => array($key->id => $key->name));
                return new enigma_error(enigma_error::BADPASS, '', $error);
            }

            return $result;
        }

        // replace message body
        if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) {
            $message->setTXTBody($body);
            $message->setParam('text_charset', $text_charset);
        }
        else {
            $mime->addPGPSignature($body, $this->pgp_driver->signature_algorithm());
            $message = $mime;
        }
    }
1240385
public function call($uri, array $params, $body, $method) {
        $path = "/v" . self::API_VERSION . "/" . self::API_TYPE . "{$uri}";
        $url = $this->host . $path;

        $items = array();
        $items['method'] = $method;
        $items['request_path'] = $path;
        $items['content_type'] = "application/json";
        $items['accept_language'] = "zh-cn";
        $items['date'] = gmdate('Y-m-d\TH:i:s\Z');
        $items['opensearch_headers'] = array();
        $items['content_md5'] = "";
        $items['opensearch_headers']['X-Opensearch-Nonce'] = $this->_nonce();

        if ($method != self::METHOD_GET) {
            if (!empty($body)) {
                $items['content_md5'] = md5($body);
                $items['body_json'] = $body;
            }
        }
        $items['query_params'] = $params;

        $signature = $this->_signature($this->secret, $items);
        $items['authorization'] = "OPENSEARCH {$this->accessKey}:{$signature}";

        return $this->_curl($url, $items);
    }
671903
static function encodeBody ( $files )
    {
    	$headers  	= array();
		$body		= null;

		// 1. Add all the files to the post
		if (!empty($files))
		{
			foreach ($files as $name => $f)
			{
				$data     = false;
				$filename = false;

				if (isset($f['filename']))
				{
					$filename = $f['filename'];
				}

				if (!empty($f['file']))
				{
					$data = @file_get_contents($f['file']);
					if ($data === false)
					{
						throw new OAuthException2(sprintf('Could not read the file "%s" for request body', $f['file']));
					}
					if (empty($filename))
					{
						$filename = basename($f['file']);
					}
				}
				else if (isset($f['data']))
				{
					$data = $f['data'];
				}
				
				// When there is data, add it as a request body, otherwise silently skip the upload
				if ($data !== false)
				{
					if (isset($headers['Content-Disposition']))
					{
						throw new OAuthException2('Only a single file (or data) allowed in a signed PUT/POST request body.');
					}

					if (empty($filename))
					{
						$filename = 'untitled';
					}
					$mime  = !empty($f['mime']) ? $f['mime'] : 'application/octet-stream';
					
					$headers['Content-Disposition'] = 'attachment; filename="'.OAuthBodyContentDisposition::encodeParameterName($filename).'"';
					$headers['Content-Type']		= $mime;

					$body = $data;
				}
				
			}

			// When we have a body, add the content-length
			if (!is_null($body))
			{
				$headers['Content-Length'] = strlen($body);
			}
		}
		return array($headers, $body);
	}
1297468
def sign(post_body)
      custom_escape(Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @secret_key, post_body)))
    end
958122
private function fromCompactSerializationSignatureToSerialization(array $parts)
    {
        $temp = [];

        if (!empty($parts[1])) {
            $temp['payload'] = $parts[1];
        }
        $temp['signatures'] = [[
            'protected' => $parts[0],
            'signature' => $parts[2],
        ]];

        return $temp;
    }
469150
function signature ( $request, $base_string, $consumer_secret, $token_secret )
	{
		return $request->urlencode($request->urlencode($consumer_secret).'&'.$request->urlencode($token_secret));
	}
1352053
private BodyPart handleMultiPart(Multipart body) throws IOException, MessagingException {
        BodyPart bodyPart = null;
        for (int i = 0; i < body.getCount(); i++) {
            MimePart entity = (MimePart) body.getBodyPart(i);

            if (bodyPart == null) {
                bodyPart = handlePart(entity);
            } else {
                BodyPart attachment = handlePart(entity);
                bodyPart.addPart(new AttachmentPart(attachment.getContent(), parseContentType(attachment.getContentType()), entity.getFileName()));
            }
        }

        return bodyPart;
    }
955387
private function parseSignature(DOMElement $xml) : void
    {
        /** @var \DOMAttr[] $signatureMethod */
        $signatureMethod = Utils::xpQuery($xml, './ds:Signature/ds:SignedInfo/ds:SignatureMethod/@Algorithm');

        /* Validate the signature element of the message. */
        $sig = Utils::validateElement($xml);
        if ($sig !== false) {
            $this->wasSignedAtConstruction = true;
            $this->setCertificates($sig['Certificates']);
            $this->setSignatureData($sig);
            $this->setSignatureMethod($signatureMethod[0]->value);
        }
    }
1081379
public static function authenticateThenDecrypt($secret, $body, $signature) {
    $keys = self::deriveAesKeys($secret);

    $localHmac = hash_hmac('sha256', $body, $keys['auth']);
    if (!self::hash_compare($signature, $localHmac)) {
      throw new InvalidMessageException("Incorrect hash");
    }

    list ($jsonEnvelope, $jsonEncrypted) = explode(Constants::PROTOCOL_DELIM, $body, 2);
    if (strlen($jsonEnvelope) > Constants::MAX_ENVELOPE_BYTES) {
      throw new InvalidMessageException("Oversized envelope");
    }

    $envelope = json_decode($jsonEnvelope, TRUE);
    if (!$envelope) {
      throw new InvalidMessageException("Malformed envelope");
    }

    if (!is_numeric($envelope['ttl']) || Time::getTime() > $envelope['ttl']) {
      throw new InvalidMessageException("Invalid TTL");
    }

    if (!is_string($envelope['iv']) || strlen($envelope['iv']) !== Constants::AES_BYTES * 2 || !preg_match('/^[a-f0-9]+$/', $envelope['iv'])) {
      // AES_BYTES (32) ==> bin2hex ==> 2 hex digits (4-bit) per byte (8-bit)
      throw new InvalidMessageException("Malformed initialization vector");
    }

    $jsonPlaintext = UserError::adapt('Civi\Cxn\Rpc\Exception\InvalidMessageException', function () use ($jsonEncrypted, $envelope, $keys) {
      $cipher = new \Crypt_AES(CRYPT_AES_MODE_CBC);
      $cipher->setKeyLength(Constants::AES_BYTES);
      $cipher->setKey($keys['enc']);
      $cipher->setIV(BinHex::hex2bin($envelope['iv']));
      return $cipher->decrypt($jsonEncrypted);
    });
    return $jsonPlaintext;
  }
558590
private function failsHeaderPartFilter(MessagePart $part)
    {
        foreach ($this->headers as $type => $values) {
            foreach ($values as $name => $header) {
                if ($this->failsHeaderFor($part, $type, $name, $header)) {
                    return true;
                }
            }
        }
        return false;
    }
323519
public function validateRequest($path, array $params)
    {
        if (!isset($params['s'])) {
            throw new SignatureException('Signature is missing.');
        }

        if ($params['s'] !== $this->generateSignature($path, $params)) {
            throw new SignatureException('Signature is not valid.');
        }
    }