python代码
import hashlib
import binascii
def scrypt_kdf_python(password: str, salt: str):
"""
等效于 Rust 版的 scrypt_kdf:
参数: N=32768 (2^15), r=8, p=1, dklen=32
"""
# 1. 将字符串转换为字节数组
password_bytes = password.encode("utf-8")
salt_bytes = salt.encode("utf-8")
# 2. 内部计算 (对应 scrypt_derive_key_internal)
# n=32768, r=8, p=1, dklen=32
key_bytes = hashlib.scrypt(
password=password_bytes,
salt=salt_bytes,
n=32768,
r=8,
p=1,
dklen=32,
maxmem=64 * 1024 * 1024, # 这里的单位是字节
)
# 3. 转换为十六进制字符串 (对应 hex::encode)
return binascii.hexlify(key_bytes).decode("utf-8")
if __name__ == "__main__":
pwd = "secret123"
slt = "somesalt"
result = scrypt_kdf_python(pwd, slt)
assert result == "ab987e2ef8501600c5413c7ae1eb0bed219dff784a1e4bf56017f8ea0261d780"
print(f"Result: {result}")
# 64位十六进制字符
print(f"Length: {len(result)}")
Rust代码
1. Cargo.toml
[package]
name = "kdf_scrypt"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
name = "scrypt"
[dependencies]
hex = "0.4.3"
scrypt = "0.11.0"
2. lib.rs
use hex;
use scrypt::Params;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ptr;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn scrypt_kdf(password: *const c_char, salt: *const c_char) -> *mut c_char {
// 1. 检查指针是否为 null
if password.is_null() || salt.is_null() {
return ptr::null_mut();
}
// 2. 将 C 字符串转换为字节数组 (更健壮,不强制要求 UTF-8)
let password_bytes = unsafe { CStr::from_ptr(password).to_bytes() };
let salt_bytes = unsafe { CStr::from_ptr(salt).to_bytes() };
// 3. 内部计算
match scrypt_derive_key_internal(password_bytes, salt_bytes) {
Ok(key_hex) => {
// 将 Rust 字符串转换为 C 字符串并将所有权移交给 C
match CString::new(key_hex) {
Ok(c_string) => c_string.into_raw(),
Err(_) => ptr::null_mut(),
}
}
Err(_) => ptr::null_mut(),
}
}
/// 必须提供此函数供其他语言调用,以释放 scrypt_kdf 返回的内存
#[unsafe(no_mangle)]
pub unsafe extern "C" fn free_string(s: *mut c_char) {
if s.is_null() {
return;
}
unsafe {
let _ = CString::from_raw(s);
} // 变量在此处离开作用域,内存被释放
}
// 内部逻辑优化
fn scrypt_derive_key_internal(
password: &[u8],
salt: &[u8],
) -> Result<String, Box<dyn std::error::Error>> {
// 配置 Scrypt 参数: N=32768, r=8, p=1
let params = Params::new(15, 8, 1, 32)?;
let mut output = vec![0u8; 32];
scrypt::scrypt(password, salt, ¶ms, &mut output)?;
Ok(hex::encode(output))
}
3. 编译成32位dll
cargo build --release --target i686-pc-windows-msvc
aardio代码
import console;
::ScryptLib = raw.loadDll("D:\rust_project\kdf_scrypt\target\i686-pc-windows-msvc\release\scrypt.dll",,"cdecl");
var scrypt_kdf = ::ScryptLib.api("scrypt_kdf", "pointer(string password, string salt)");
var free_string = ::ScryptLib.api("free_string", "void(pointer)");
// 调用
var ptr = scrypt_kdf("secret123", "somesalt");
if(ptr && ptr !== 0){
var kdf_result = raw.str(ptr);
console.log("KDF 结果:", kdf_result);
// 释放内存
free_string(ptr);
}
console.pause();