feat: Added age-ffi.

This commit is contained in:
2026-04-26 17:29:52 -04:00
parent 41944af80c
commit 0db97b714f
30 changed files with 7901 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
//! Key generation and derivation functions.
use crate::helpers::{cstr_to_str, string_to_cstr};
use crate::types::{AgeKeypair, AgeResult};
use age::secrecy::ExposeSecret;
use std::ffi::CString;
use std::os::raw::c_char;
use std::str::FromStr;
/// Generate a new age x25519 keypair.
///
/// # Arguments
/// * `keypair` - Pointer to receive the generated keypair
///
/// # Returns
/// AgeResult indicating success or failure
#[no_mangle]
pub extern "C" fn age_generate_x25519(keypair: *mut AgeKeypair) -> AgeResult {
if keypair.is_null() {
return AgeResult::InvalidInput;
}
let identity = age::x25519::Identity::generate();
let public_key = identity.to_public().to_string();
let private_key = identity.to_string().expose_secret().to_string();
let c_public = match string_to_cstr(public_key) {
Ok(s) => s,
Err(e) => return e,
};
let c_private = match string_to_cstr(private_key) {
Ok(s) => s,
Err(e) => {
unsafe { drop(CString::from_raw(c_public)); }
return e;
}
};
unsafe {
(*keypair).public_key = c_public;
(*keypair).private_key = c_private;
}
AgeResult::Success
}
/// Alias for age_generate_x25519 for backwards compatibility.
#[no_mangle]
pub extern "C" fn age_generate_keypair(keypair: *mut AgeKeypair) -> AgeResult {
age_generate_x25519(keypair)
}
/// Derive the public key from a private x25519 identity.
///
/// # Arguments
/// * `private_key` - The private key string (AGE-SECRET-KEY-1...)
/// * `public_key` - Pointer to receive the public key string
///
/// # Returns
/// AgeResult indicating success or failure
#[no_mangle]
pub extern "C" fn age_x25519_to_public(
private_key: *const c_char,
public_key: *mut *mut c_char,
) -> AgeResult {
if public_key.is_null() {
return AgeResult::InvalidInput;
}
let private_str = match unsafe { cstr_to_str(private_key) } {
Ok(s) => s,
Err(e) => return e,
};
let identity = match age::x25519::Identity::from_str(private_str) {
Ok(i) => i,
Err(_) => return AgeResult::InvalidIdentity,
};
let public_str = identity.to_public().to_string();
let c_public = match string_to_cstr(public_str) {
Ok(s) => s,
Err(e) => return e,
};
unsafe {
*public_key = c_public;
}
AgeResult::Success
}