}
// When you create a community, make sure the user becomes a moderator and a follower
- let keypair = generate_actor_keypair();
+ let keypair = generate_actor_keypair()?;
let community_form = CommunityForm {
name: data.name.to_owned(),
return Err(APIError::err("admin_already_created").into());
}
- let keypair = generate_actor_keypair();
+ let keypair = generate_actor_keypair()?;
// Register the new user
let user_form = UserForm {
}
};
- let keypair = generate_actor_keypair();
+ let keypair = generate_actor_keypair()?;
// Create the main community if it doesn't exist
let main_community: Community = match Community::read(&conn, 2) {
use crate::apub::is_apub_id_valid;
-use crate::apub::signatures::{sign, Keypair};
+use crate::apub::signatures::sign;
use crate::db::community::Community;
use crate::db::community_view::CommunityFollowerView;
use crate::db::post::Post;
/// Send an activity to a list of recipients, using the correct headers etc.
fn send_activity<A>(
activity: &A,
- keypair: &Keypair,
+ private_key: &str,
sender_id: &str,
to: Vec<String>,
) -> Result<(), Error>
continue;
}
let request = Request::post(t).header("Host", to_url.domain().unwrap());
- let signature = sign(&request, keypair, sender_id)?;
+ let signature = sign(&request, private_key, sender_id)?;
let res = request
.header("Signature", signature)
.header("Content-Type", "application/json")
.set_object_base_box(page)?;
send_activity(
&create,
- &creator.get_keypair().unwrap(),
+ &creator.private_key.as_ref().unwrap(),
&creator.actor_id,
get_follower_inboxes(conn, &community)?,
)?;
.set_object_base_box(page)?;
send_activity(
&update,
- &creator.get_keypair().unwrap(),
+ &creator.private_key.as_ref().unwrap(),
&creator.actor_id,
get_follower_inboxes(conn, &community)?,
)?;
let to = format!("{}/inbox", community.actor_id);
send_activity(
&follow,
- &community.get_keypair().unwrap(),
+ &community.private_key.as_ref().unwrap(),
&community.actor_id,
vec![to],
)?;
let to = format!("{}/inbox", community_uri);
send_activity(
&accept,
- &community.get_keypair().unwrap(),
+ &community.private_key.unwrap(),
&community.actor_id,
vec![to],
)?;
}
/// Generate the asymmetric keypair for ActivityPub HTTP signatures.
-pub fn generate_actor_keypair() -> Keypair {
- let rsa = Rsa::generate(2048).expect("sign::gen_keypair: key generation error");
- let pkey = PKey::from_rsa(rsa).expect("sign::gen_keypair: parsing error");
- let public_key = pkey
- .public_key_to_pem()
- .expect("sign::gen_keypair: public key encoding error");
- let private_key = pkey
- .private_key_to_pem_pkcs8()
- .expect("sign::gen_keypair: private key encoding error");
- Keypair {
- private_key: String::from_utf8_lossy(&private_key).into_owned(),
- public_key: String::from_utf8_lossy(&public_key).into_owned(),
- }
+pub fn generate_actor_keypair() -> Result<Keypair, Error> {
+ let rsa = Rsa::generate(2048)?;
+ let pkey = PKey::from_rsa(rsa)?;
+ let public_key = pkey.public_key_to_pem()?;
+ let private_key = pkey.private_key_to_pem_pkcs8()?;
+ Ok(Keypair {
+ private_key: String::from_utf8(private_key)?,
+ public_key: String::from_utf8(public_key)?,
+ })
}
/// Signs request headers with the given keypair.
-pub fn sign(request: &Builder, keypair: &Keypair, sender_id: &str) -> Result<String, Error> {
+/// TODO: would be nice to pass the sending actor in, instead of raw privatekey/id strings
+pub fn sign(request: &Builder, private_key: &str, sender_id: &str) -> Result<String, Error> {
let signing_key_id = format!("{}#main-key", sender_id);
let config = Config::new();
headers,
)
.sign(signing_key_id, |signing_string| {
- let private_key = PKey::private_key_from_pem(keypair.private_key.as_bytes())?;
+ let private_key = PKey::private_key_from_pem(private_key.as_bytes())?;
let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap();
signer.update(signing_string.as_bytes()).unwrap();
Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, Error>
use crate::apub::signatures::generate_actor_keypair;
use crate::apub::{make_apub_endpoint, EndpointType};
use crate::naive_now;
+use failure::Error;
use log::info;
pub fn run_advanced_migrations(conn: &PgConnection) -> Result<(), Error> {
.load::<User_>(conn)?;
for cuser in &incorrect_users {
- let keypair = generate_actor_keypair();
+ let keypair = generate_actor_keypair()?;
let form = UserForm {
name: cuser.name.to_owned(),
.load::<Community>(conn)?;
for ccommunity in &incorrect_communities {
- let keypair = generate_actor_keypair();
+ let keypair = generate_actor_keypair()?;
let form = CommunityForm {
name: ccommunity.name.to_owned(),
use super::*;
-use crate::apub::signatures::Keypair;
use crate::schema::{community, community_follower, community_moderator, community_user_ban};
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
pub fn get_url(&self) -> String {
format!("https://{}/c/{}", Settings::get().hostname, self.name)
}
-
- pub fn get_keypair(&self) -> Option<Keypair> {
- if let Some(private) = self.private_key.to_owned() {
- if let Some(public) = self.public_key.to_owned() {
- Some(Keypair {
- private_key: private,
- public_key: public,
- })
- } else {
- None
- }
- } else {
- None
- }
- }
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
use super::*;
-use crate::apub::signatures::Keypair;
use crate::schema::user_;
use crate::schema::user_::dsl::*;
use crate::{is_email_regex, naive_now, Settings};
use crate::schema::user_::dsl::*;
user_.filter(actor_id.eq(object_id)).first::<Self>(conn)
}
-
- pub fn get_keypair(&self) -> Option<Keypair> {
- if let Some(private) = self.private_key.to_owned() {
- if let Some(public) = self.public_key.to_owned() {
- Some(Keypair {
- private_key: private,
- public_key: public,
- })
- } else {
- None
- }
- } else {
- None
- }
- }
}
#[derive(Debug, Serialize, Deserialize)]