1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//! Module dedicated to PGP signing.
//!
//! This module exposes a simple function [`sign`] and its associated
//! [`Error`]s.

use pgp_native::{crypto::hash::HashAlgorithm, Message, SignedSecretKey};
use thiserror::Error;
use tokio::task;

use crate::Result;

/// Errors related to PGP signing.
#[derive(Debug, Error)]
pub enum Error {
    #[error("cannot sign pgp message")]
    SignMessageError(#[source] pgp_native::errors::Error),
    #[error("cannot export signed pgp message as armored string")]
    ExportSignedMessageToArmoredBytesError(#[source] pgp_native::errors::Error),
}

/// Signs given bytes using the given private key and its passphrase.
pub async fn sign(
    skey: SignedSecretKey,
    passphrase: impl ToString,
    plain_bytes: Vec<u8>,
) -> Result<Vec<u8>> {
    let passphrase = passphrase.to_string();

    task::spawn_blocking(move || {
        let msg = Message::new_literal_bytes("", &plain_bytes)
            .sign(&skey, || passphrase, HashAlgorithm::SHA1)
            .map_err(Error::SignMessageError)?;

        let signature_bytes = msg
            .into_signature()
            .to_armored_bytes(None)
            .map_err(Error::ExportSignedMessageToArmoredBytesError)?;

        Ok(signature_bytes)
    })
    .await?
}