2018-10-02 22:25:40 +02:00
|
|
|
<?php
|
2019-02-24 12:07:41 +01:00
|
|
|
namespace Activitypub;
|
2018-10-02 22:25:40 +02:00
|
|
|
|
2019-02-24 13:01:28 +01:00
|
|
|
/**
|
|
|
|
* ActivityPub Signature Class
|
|
|
|
*
|
|
|
|
* @author Matthias Pfefferle
|
|
|
|
*/
|
2019-02-24 12:07:41 +01:00
|
|
|
class Signature {
|
2018-12-08 00:02:18 +01:00
|
|
|
|
2018-10-02 22:25:40 +02:00
|
|
|
/**
|
2018-12-20 11:33:08 +01:00
|
|
|
* @param int $user_id
|
2018-10-02 22:25:40 +02:00
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2018-12-20 11:33:08 +01:00
|
|
|
public static function get_public_key( $user_id, $force = false ) {
|
2019-09-27 10:12:59 +02:00
|
|
|
$key = \get_user_meta( $user_id, 'magic_sig_public_key' );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
if ( $key && ! $force ) {
|
|
|
|
return $key[0];
|
|
|
|
}
|
|
|
|
|
2018-12-20 11:33:08 +01:00
|
|
|
self::generate_key_pair( $user_id );
|
2019-09-27 10:12:59 +02:00
|
|
|
$key = \get_user_meta( $user_id, 'magic_sig_public_key' );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
return $key[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-12-20 11:33:08 +01:00
|
|
|
* @param int $user_id
|
2018-10-02 22:25:40 +02:00
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2018-12-20 11:33:08 +01:00
|
|
|
public static function get_private_key( $user_id, $force = false ) {
|
2019-09-27 10:12:59 +02:00
|
|
|
$key = \get_user_meta( $user_id, 'magic_sig_private_key' );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
if ( $key && ! $force ) {
|
|
|
|
return $key[0];
|
|
|
|
}
|
|
|
|
|
2018-12-20 11:33:08 +01:00
|
|
|
self::generate_key_pair( $user_id );
|
2019-09-27 10:12:59 +02:00
|
|
|
$key = \get_user_meta( $user_id, 'magic_sig_private_key' );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
return $key[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates the pair keys
|
|
|
|
*
|
2018-12-20 11:33:08 +01:00
|
|
|
* @param int $user_id
|
2018-10-02 22:25:40 +02:00
|
|
|
*/
|
2018-12-20 11:33:08 +01:00
|
|
|
public static function generate_key_pair( $user_id ) {
|
2018-10-02 22:25:40 +02:00
|
|
|
$config = array(
|
|
|
|
'digest_alg' => 'sha512',
|
|
|
|
'private_key_bits' => 2048,
|
2020-05-12 19:42:09 +02:00
|
|
|
'private_key_type' => \OPENSSL_KEYTYPE_RSA,
|
2018-10-02 22:25:40 +02:00
|
|
|
);
|
|
|
|
|
2019-09-27 10:12:59 +02:00
|
|
|
$key = \openssl_pkey_new( $config );
|
2018-10-02 22:25:40 +02:00
|
|
|
$priv_key = null;
|
|
|
|
|
2019-09-27 10:12:59 +02:00
|
|
|
\openssl_pkey_export( $key, $priv_key );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
// private key
|
2019-09-27 10:12:59 +02:00
|
|
|
\update_user_meta( $user_id, 'magic_sig_private_key', $priv_key );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
2019-09-27 10:12:59 +02:00
|
|
|
$detail = \openssl_pkey_get_details( $key );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
// public key
|
2019-09-27 10:12:59 +02:00
|
|
|
\update_user_meta( $user_id, 'magic_sig_public_key', $detail['key'] );
|
2018-10-02 22:25:40 +02:00
|
|
|
}
|
|
|
|
|
2020-12-10 04:23:05 +01:00
|
|
|
public static function generate_signature( $user_id, $url, $date, $digest = null ) {
|
2018-12-20 11:33:08 +01:00
|
|
|
$key = self::get_private_key( $user_id );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
2019-09-27 10:12:59 +02:00
|
|
|
$url_parts = \wp_parse_url( $url );
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
$host = $url_parts['host'];
|
|
|
|
$path = '/';
|
|
|
|
|
|
|
|
// add path
|
|
|
|
if ( ! empty( $url_parts['path'] ) ) {
|
2018-12-08 00:02:18 +01:00
|
|
|
$path = $url_parts['path'];
|
2018-10-02 22:25:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// add query
|
|
|
|
if ( ! empty( $url_parts['query'] ) ) {
|
|
|
|
$path .= '?' . $url_parts['query'];
|
|
|
|
}
|
|
|
|
|
2020-12-10 04:23:05 +01:00
|
|
|
if ( ! empty( $digest ) ) {
|
|
|
|
$signed_string = "(request-target): post $path\nhost: $host\ndate: $date\ndigest: SHA-256=$digest";
|
|
|
|
} else {
|
|
|
|
$signed_string = "(request-target): post $path\nhost: $host\ndate: $date";
|
|
|
|
}
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
$signature = null;
|
2020-05-12 19:42:09 +02:00
|
|
|
\openssl_sign( $signed_string, $signature, $key, \OPENSSL_ALGO_SHA256 );
|
2019-09-27 10:12:59 +02:00
|
|
|
$signature = \base64_encode( $signature ); // phpcs:ignore
|
2018-10-02 22:25:40 +02:00
|
|
|
|
2019-09-27 10:12:59 +02:00
|
|
|
$key_id = \get_author_posts_url( $user_id ) . '#main-key';
|
2018-10-02 22:25:40 +02:00
|
|
|
|
2020-12-10 04:23:05 +01:00
|
|
|
if ( ! empty( $digest ) ) {
|
|
|
|
return \sprintf( 'keyId="%s",algorithm="rsa-sha256",headers="(request-target) host date digest",signature="%s"', $key_id, $signature );
|
|
|
|
} else {
|
|
|
|
return \sprintf( 'keyId="%s",algorithm="rsa-sha256",headers="(request-target) host date",signature="%s"', $key_id, $signature );
|
|
|
|
}
|
2018-10-02 22:25:40 +02:00
|
|
|
}
|
|
|
|
|
2018-12-20 11:33:08 +01:00
|
|
|
public static function verify_signature( $headers, $signature ) {
|
2018-10-02 22:25:40 +02:00
|
|
|
|
|
|
|
}
|
2020-12-10 04:23:05 +01:00
|
|
|
|
|
|
|
public static function generate_digest( $body ) {
|
|
|
|
$digest = \base64_encode( \hash('sha256', $body, true ) ); // phpcs:ignore
|
|
|
|
return "$digest";
|
|
|
|
}
|
2018-10-02 22:25:40 +02:00
|
|
|
}
|