/** * Sign and post the given Atom entry as a Salmon message. * * Side effects: may generate a keypair on-demand for the given user, * which can be very slow on some systems (like those without php5-gmp). * * @param string $endpoint_uri * @param string $xml string representation of payload * @param User $user local user profile whose keys we sign with * @return boolean success */ public static function post($endpoint_uri, $xml, User $user) { if (empty($endpoint_uri)) { common_debug('No endpoint URI for Salmon post to ' . $user->getUri()); return false; } try { $magic_env = MagicEnvelope::signAsUser($xml, $user); $envxml = $magic_env->toXML(); } catch (Exception $e) { common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage()); return false; } $headers = array('Content-Type: application/magic-envelope+xml'); try { $client = new HTTPClient(); $client->setBody($envxml); $response = $client->post($endpoint_uri, $headers); } catch (HTTP_Request2_Exception $e) { common_log(LOG_ERR, "Salmon post to {$endpoint_uri} failed: " . $e->getMessage()); return false; } // Diaspora wants a slightly different formatting on the POST (other Content-type, so body needs "xml=") if ($response->getStatus() === 422) { common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. Diaspora? Will try again! Body: %s', $user->id, $endpoint_uri, $response->getStatus(), $response->getBody())); $headers = array('Content-Type: application/x-www-form-urlencoded'); $client->setBody('xml=' . Magicsig::base64_url_encode($envxml)); $response = $client->post($endpoint_uri, $headers); } // 200 OK is the best response // 202 Accepted is what we get from Diaspora for example if (!in_array($response->getStatus(), array(200, 202))) { common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', $user->id, $endpoint_uri, $response->getStatus(), $response->getBody())); return false; } // Success! return true; }
/** * Generate base64-encoded signature for the given byte string * using our private key. * * @param string $bytes as raw byte string * @return string base64-encoded signature */ public function sign($bytes) { $sig = $this->privateKey->sign($bytes); return Magicsig::base64_url_encode($sig); }
public function signMessage($text, $mimetype, $keypair) { $signature_alg = Magicsig::fromString($keypair); $armored_text = Magicsig::base64_url_encode($text); return array('data' => $armored_text, 'encoding' => MagicEnvelope::ENCODING, 'data_type' => $mimetype, 'sig' => $signature_alg->sign($armored_text), 'alg' => $signature_alg->getName()); }
/** * * @param <type> $text * @param <type> $mimetype * @param Magicsig $magicsig Magicsig with private key available. * * @return MagicEnvelope object with all properties set * * @throws Exception of various kinds on signing failure */ public function signMessage($text, $mimetype, Magicsig $magicsig) { assert($magicsig->privateKey instanceof Crypt_RSA); // Prepare text and metadata for signing $this->data = Magicsig::base64_url_encode($text); $this->data_type = $mimetype; $this->encoding = self::ENCODING; $this->alg = $magicsig->getName(); // Get the actual signature $this->sig = $magicsig->sign($this->signingText()); }
/** * Generate base64-encoded signature for the given byte string * using our private key. * * @param string $bytes as raw byte string * @return string base64url-encoded signature */ public function sign($bytes) { $sig = $this->privateKey->sign($bytes); if ($sig === false) { throw new ServerException('Could not sign data'); } return Magicsig::base64_url_encode($sig); }
/** * * @param <type> $text * @param <type> $mimetype * @param Magicsig $magicsig Magicsig with private key available. * * @return MagicEnvelope object with all properties set * * @throws Exception of various kinds on signing failure */ public function signMessage($text, $mimetype) { if (!$this->actor instanceof Profile) { throw new ServerException('No profile to sign message with is set.'); } elseif (!$this->actor->isLocal()) { throw new ServerException('Cannot sign magic envelopes with remote users since we have no private key.'); } // Find already stored key $magicsig = Magicsig::getKV('user_id', $this->actor->getID()); if (!$magicsig instanceof Magicsig) { // and if it doesn't exist, it is time to create one! $magicsig = Magicsig::generate($this->actor->getUser()); } assert($magicsig instanceof Magicsig); assert($magicsig->privateKey instanceof Crypt_RSA); // Prepare text and metadata for signing $this->data = Magicsig::base64_url_encode($text); $this->data_type = $mimetype; $this->encoding = self::ENCODING; $this->alg = $magicsig->getName(); // Get the actual signature $this->sig = $magicsig->sign($this->signingText()); }
public function onSalmonSlap($endpoint_uri, MagicEnvelope $magic_env, Profile $target = null) { $envxml = $magic_env->toXML($target, 'diaspora'); // Diaspora wants another POST format (base64url-encoded POST variable 'xml') $headers = array('Content-Type: application/x-www-form-urlencoded'); // Another way to distinguish Diaspora from GNU social is that a POST with // $headers=array('Content-Type: application/magic-envelope+xml') would return // HTTP status code 422 Unprocessable Entity, at least as of 2015-10-04. try { $client = new HTTPClient(); $client->setBody('xml=' . Magicsig::base64_url_encode($envxml)); $response = $client->post($endpoint_uri, $headers); } catch (HTTP_Request2_Exception $e) { common_log(LOG_ERR, "Diaspora-flavoured Salmon post to {$endpoint_uri} failed: " . $e->getMessage()); return false; } // 200 OK is the best response // 202 Accepted is what we get from Diaspora for example if (!in_array($response->getStatus(), array(200, 202))) { common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody())); return true; } // Success! return false; }