| 135 | /// * `Err(())` - Decryption error (invalid format, authentication failure, etc.) |
| 136 | #[allow(clippy::result_unit_err)] |
| 137 | pub fn open_sealed_box( |
| 138 | sealed_box: &[u8], |
| 139 | public_key: &PublicKey, |
| 140 | secret_key: &StaticSecret, |
| 141 | ) -> Result<Vec<u8>, ()> { |
| 142 | if sealed_box.len() <= PUBLICKEYBYTES { |
| 143 | return Err(()); |
| 144 | } |
| 145 | |
| 146 | let ephemeral_pk_bytes = &sealed_box[..PUBLICKEYBYTES]; |
| 147 | let ciphertext = &sealed_box[PUBLICKEYBYTES..]; |
| 148 | |
| 149 | // Derive the nonce using the ephemeral public key and recipient's public key |
| 150 | let nonce = derive_nonce(ephemeral_pk_bytes, public_key.as_bytes())?; |
| 151 | |
| 152 | // Convert ephemeral public key bytes to x25519-dalek type |
| 153 | let ephemeral_pk_array = <[u8; 32]>::try_from(ephemeral_pk_bytes).map_err(|_| ())?; |
| 154 | let ephemeral_pk = PublicKey::from(ephemeral_pk_array); |
| 155 | |
| 156 | // Compute the shared secret using X25519 Diffie-Hellman |
| 157 | let shared_secret = secret_key.diffie_hellman(&ephemeral_pk); |
| 158 | |
| 159 | // Derive the symmetric key using HSalsa20 |
| 160 | let key_bytes = derive_key(shared_secret.as_bytes()); |
| 161 | |
| 162 | // Create the XSalsa20Poly1305 cipher with the derived key |
| 163 | let cipher = XSalsa20Poly1305::new_from_slice(&key_bytes).map_err(|_| ())?; |
| 164 | |
| 165 | // Decrypt the ciphertext |
| 166 | match cipher.decrypt(&nonce, ciphertext) { |
| 167 | Ok(pt) => Ok(pt), |
| 168 | Err(_) => Err(()), |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | /// Convenience function to convert a public key from bytes to the PublicKey type |
| 173 | pub fn public_key_from_bytes(bytes: &[u8; 32]) -> PublicKey { |