tweecrypto/
lib.rs

1// Copyright [2022] [valkyrie_pilot <valk@randomairborne.dev>]
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15
16//! `TweeCrypto` is a library to do encryption for the [TweeChat](https://tweechat.github.io) message protocol.
17
18#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
19
20use base64::DecodeError;
21use tink_core::{
22    keyset::{Handle, JsonReader},
23    TinkError,
24};
25use wasm_bindgen::prelude::*;
26
27/// Encrypt a message to the `TweeChat` Message Content standard
28///
29/// # Errors
30/// Errors if internal crypto library fails
31#[wasm_bindgen]
32pub fn encrypt(msg: &str, pubkey_str: &str) -> Result<String, CryptError> {
33    let mut pubkey_reader = JsonReader::new(pubkey_str.as_bytes());
34    let pubkey_handle = Handle::read_with_no_secrets(&mut pubkey_reader)?;
35    let pubkey = tink_aead::new(&pubkey_handle)?;
36    Ok(base64::encode(pubkey.encrypt(msg.as_bytes(), &[])?))
37}
38
39/// Encrypt a message to the `TweeChat` Message Content standard
40///
41/// # Errors
42/// Errors if internal crypto library fails or input is not Base64
43#[wasm_bindgen]
44pub fn decrypt(
45    encrypted_msg: String,
46    privkey_str: &str,
47) -> Result<String, CryptError> {
48    let mut privkey_reader = JsonReader::new(privkey_str.as_bytes());
49    let privkey_handle = Handle::read_with_no_secrets(&mut privkey_reader)?;
50    let privkey = tink_aead::new(&privkey_handle)?;
51    Ok(
52        String::from_utf8_lossy(&privkey.decrypt(&base64::decode(encrypted_msg)?, &[])?)
53            .to_string(),
54    )
55}
56
57#[derive(Debug, thiserror::Error)]
58pub enum CryptError {
59    #[error("Crypto library internal error")]
60    Tink(#[from] TinkError),
61    #[error("Base64 is invalid")]
62    Base64(#[from] DecodeError),
63    #[error("Missing keys!")]
64    MissingKey,
65}
66
67impl Into<JsValue> for CryptError {
68    fn into(self) -> JsValue {
69        JsValue::from_str(&self.to_string())
70    }
71}