Skip to main content

ordinary_obfuscation/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(clippy::all, clippy::pedantic)]
3#![allow(clippy::missing_errors_doc, clippy::needless_pass_by_value)]
4
5// Copyright (C) 2026 Ordinary Labs, LLC.
6//
7// SPDX-License-Identifier: AGPL-3.0-only
8
9use wasm_bindgen::prelude::*;
10
11#[wasm_bindgen]
12pub struct FingerprintResult {
13    fingerprint: Vec<u8>,
14    verifier: Vec<u8>,
15}
16
17#[wasm_bindgen]
18impl FingerprintResult {
19    #[wasm_bindgen(getter)]
20    #[must_use]
21    pub fn fingerprint(&self) -> Vec<u8> {
22        self.fingerprint.clone()
23    }
24    #[wasm_bindgen(getter)]
25    #[must_use]
26    pub fn verifier(&self) -> Vec<u8> {
27        self.verifier.clone()
28    }
29}
30
31#[wasm_bindgen]
32#[must_use]
33pub fn generate_fingerprint() -> FingerprintResult {
34    let (fingerprint, verifier) = rgp::generate_fingerprint();
35
36    FingerprintResult {
37        fingerprint: fingerprint.into(),
38        verifier: verifier.into(),
39    }
40}
41
42#[wasm_bindgen]
43pub struct DhKeysResult {
44    private: Vec<u8>,
45    public: Vec<u8>,
46}
47
48#[wasm_bindgen]
49impl DhKeysResult {
50    #[wasm_bindgen(getter)]
51    #[must_use]
52    pub fn private(&self) -> Vec<u8> {
53        self.private.clone()
54    }
55    #[wasm_bindgen(getter)]
56    #[must_use]
57    pub fn public(&self) -> Vec<u8> {
58        self.public.clone()
59    }
60}
61
62#[wasm_bindgen]
63#[must_use]
64pub fn generate_dh_keys() -> DhKeysResult {
65    let (private, public) = rgp::generate_dh_keys();
66
67    DhKeysResult {
68        private: private.into(),
69        public: public.into(),
70    }
71}
72
73#[wasm_bindgen]
74pub fn encrypt_dh(
75    fingerprint: Vec<u8>,
76    content: Vec<u8>,
77    private_key: Vec<u8>,
78    public_keys: Vec<u8>,
79) -> Result<Vec<u8>, String> {
80    let fixed_fingerprint: [u8; 32] = match fingerprint.try_into() {
81        Ok(f) => f,
82        Err(_) => return Err("failed to convert fingerprint to 32 len array".into()),
83    };
84
85    let fixed_private_key: [u8; 32] = match private_key.try_into() {
86        Ok(f) => f,
87        Err(_) => return Err("failed to convert private_key to 32 len array".into()),
88    };
89
90    let mut fixed_public_keys = vec![];
91
92    for public_key in public_keys.chunks_exact(32) {
93        let fixed_public_key: [u8; 32] = match public_key.try_into() {
94            Ok(f) => f,
95            Err(_) => return Err("failed to convert public_key to 32 len array".into()),
96        };
97
98        fixed_public_keys.push(fixed_public_key);
99    }
100
101    let encrypted_content = match rgp::encrypt(
102        fixed_fingerprint,
103        content.clone(),
104        rgp::Encrypt::Dh(fixed_private_key, &fixed_public_keys, None),
105    ) {
106        Ok((encrypted_content, _)) => encrypted_content,
107        Err(err) => return Ok(err.into()),
108    };
109
110    Ok(encrypted_content)
111}
112
113#[wasm_bindgen]
114pub fn decrypt_dh(
115    position: usize,
116    mut encrypted_content: Vec<u8>,
117    verifier: Vec<u8>,
118    public_key: Vec<u8>,
119    private_key: Vec<u8>,
120) -> Result<Vec<u8>, String> {
121    let fixed_verifier: [u8; 32] = match verifier.try_into() {
122        Ok(f) => f,
123        Err(_) => return Err("failed to convert verifier to 32 len array".into()),
124    };
125
126    let fixed_public_key: [u8; 32] = match public_key.try_into() {
127        Ok(f) => f,
128        Err(_) => return Err("failed to convert public_key to 32 len array".into()),
129    };
130
131    let fixed_private_key: [u8; 32] = match private_key.try_into() {
132        Ok(f) => f,
133        Err(_) => return Err("failed to convert private_key to 32 len array".into()),
134    };
135
136    if let rgp::Components::Dh(encrypted_key, _) =
137        rgp::extract_components_mut(position, &mut encrypted_content)
138    {
139        let decrypted_content = match rgp::decrypt(
140            Some(&fixed_verifier),
141            &encrypted_content,
142            rgp::Decrypt::Dh(encrypted_key, fixed_public_key, fixed_private_key, None),
143        ) {
144            Ok((decrypted_content, _)) => decrypted_content,
145            Err(err) => return Err(err.into()),
146        };
147
148        return Ok(decrypted_content);
149    }
150
151    Err("not DH encryption type".into())
152}