mirror of
https://github.com/sbrow/envr.git
synced 2026-06-27 18:48:33 -04:00
feat: Added age-ffi.
This commit is contained in:
139
zig-vendor/age-ffi/src/passphrase.rs
Normal file
139
zig-vendor/age-ffi/src/passphrase.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
//! Passphrase-based encryption and decryption (scrypt).
|
||||
|
||||
use crate::helpers::cstr_to_string;
|
||||
use crate::types::{AgeBuffer, AgeResult};
|
||||
use age::secrecy::SecretString;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::raw::c_char;
|
||||
|
||||
/// Encrypt data using a passphrase.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `plaintext` - Pointer to the plaintext data
|
||||
/// * `plaintext_len` - Length of the plaintext
|
||||
/// * `passphrase` - The passphrase string
|
||||
/// * `armor` - If true, output will be ASCII-armored
|
||||
/// * `output` - Pointer to receive the encrypted buffer
|
||||
///
|
||||
/// # Returns
|
||||
/// AgeResult indicating success or failure
|
||||
#[no_mangle]
|
||||
pub extern "C" fn age_encrypt_passphrase(
|
||||
plaintext: *const u8,
|
||||
plaintext_len: usize,
|
||||
passphrase: *const c_char,
|
||||
armor: bool,
|
||||
output: *mut AgeBuffer,
|
||||
) -> AgeResult {
|
||||
if plaintext.is_null() || output.is_null() {
|
||||
return AgeResult::InvalidInput;
|
||||
}
|
||||
|
||||
let plaintext = unsafe { std::slice::from_raw_parts(plaintext, plaintext_len) };
|
||||
|
||||
let passphrase_str = match unsafe { cstr_to_string(passphrase) } {
|
||||
Ok(s) => s,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
let secret = SecretString::from(passphrase_str);
|
||||
let encryptor = age::Encryptor::with_user_passphrase(secret);
|
||||
|
||||
let mut encrypted = Vec::new();
|
||||
|
||||
let result = if armor {
|
||||
let armor_writer = age::armor::ArmoredWriter::wrap_output(&mut encrypted, age::armor::Format::AsciiArmor)
|
||||
.map_err(|_| AgeResult::ArmorError);
|
||||
|
||||
match armor_writer {
|
||||
Ok(armor) => {
|
||||
match encryptor.wrap_output(armor) {
|
||||
Ok(mut writer) => {
|
||||
if writer.write_all(plaintext).is_err() {
|
||||
return AgeResult::EncryptionFailed;
|
||||
}
|
||||
match writer.finish() {
|
||||
Ok(armor) => armor.finish().map_err(|_| AgeResult::ArmorError),
|
||||
Err(_) => return AgeResult::EncryptionFailed,
|
||||
}
|
||||
}
|
||||
Err(_) => return AgeResult::EncryptionFailed,
|
||||
}
|
||||
}
|
||||
Err(e) => return e,
|
||||
}
|
||||
} else {
|
||||
match encryptor.wrap_output(&mut encrypted) {
|
||||
Ok(mut writer) => {
|
||||
if writer.write_all(plaintext).is_err() {
|
||||
return AgeResult::EncryptionFailed;
|
||||
}
|
||||
writer.finish().map_err(|_| AgeResult::EncryptionFailed)
|
||||
}
|
||||
Err(_) => return AgeResult::EncryptionFailed,
|
||||
}
|
||||
};
|
||||
|
||||
if result.is_err() {
|
||||
return AgeResult::EncryptionFailed;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
*output = AgeBuffer::from_vec(encrypted);
|
||||
}
|
||||
|
||||
AgeResult::Success
|
||||
}
|
||||
|
||||
/// Decrypt data using a passphrase.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `ciphertext` - Pointer to the encrypted data
|
||||
/// * `ciphertext_len` - Length of the ciphertext
|
||||
/// * `passphrase` - The passphrase string
|
||||
/// * `output` - Pointer to receive the decrypted buffer
|
||||
///
|
||||
/// # Returns
|
||||
/// AgeResult indicating success or failure
|
||||
#[no_mangle]
|
||||
pub extern "C" fn age_decrypt_passphrase(
|
||||
ciphertext: *const u8,
|
||||
ciphertext_len: usize,
|
||||
passphrase: *const c_char,
|
||||
output: *mut AgeBuffer,
|
||||
) -> AgeResult {
|
||||
if ciphertext.is_null() || output.is_null() {
|
||||
return AgeResult::InvalidInput;
|
||||
}
|
||||
|
||||
let ciphertext = unsafe { std::slice::from_raw_parts(ciphertext, ciphertext_len) };
|
||||
|
||||
let passphrase_str = match unsafe { cstr_to_string(passphrase) } {
|
||||
Ok(s) => s,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
let secret = SecretString::from(passphrase_str);
|
||||
let identity = age::scrypt::Identity::new(secret);
|
||||
|
||||
let decryptor = match age::Decryptor::new(ciphertext) {
|
||||
Ok(d) => d,
|
||||
Err(_) => return AgeResult::DecryptionFailed,
|
||||
};
|
||||
|
||||
let mut decrypted = Vec::new();
|
||||
let mut reader = match decryptor.decrypt(std::iter::once(&identity as &dyn age::Identity)) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return AgeResult::DecryptionFailed,
|
||||
};
|
||||
|
||||
if reader.read_to_end(&mut decrypted).is_err() {
|
||||
return AgeResult::DecryptionFailed;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
*output = AgeBuffer::from_vec(decrypted);
|
||||
}
|
||||
|
||||
AgeResult::Success
|
||||
}
|
||||
Reference in New Issue
Block a user