Change to use napi, add passwords module, scope out public api

This commit is contained in:
Hinton 2022-02-28 11:40:36 +01:00
parent 10b3dfbecf
commit 52f598b052
11 changed files with 296 additions and 86 deletions

View File

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.55"
@ -26,6 +35,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "convert_case"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8"
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -42,17 +57,29 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "ctor"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "desktop_native"
version = "0.1.0"
dependencies = [
"anyhow",
"core-foundation",
"neon",
"napi",
"napi-build",
"napi-derive",
"security-framework",
"security-framework-sys",
"tokio",
"windows",
"windows 0.32.0",
]
[[package]]
@ -64,22 +91,18 @@ dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
[[package]]
name = "libloading"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "lock_api"
version = "0.4.6"
@ -127,45 +150,57 @@ dependencies = [
]
[[package]]
name = "neon"
version = "0.10.0-alpha.3"
name = "napi"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea1f028ddf17d8f08c7a76c76487e7abfeb1bc23ab62f4a6a020d8510f3ac26d"
checksum = "17ec66e60f000c78dd7c6215b6fa260e0591e09805024332bc5b3f55acc12244"
dependencies = [
"neon-build",
"neon-macros",
"neon-runtime",
"semver",
"smallvec",
"ctor",
"lazy_static",
"napi-sys",
"tokio",
"windows 0.30.0",
]
[[package]]
name = "neon-build"
version = "0.10.0-alpha.3"
name = "napi-build"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0facb0f69acc991f265c81ed180d8981c7d204d81fecbabe27e77a3e562948"
checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b"
[[package]]
name = "neon-macros"
version = "0.9.1"
name = "napi-derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "987f12c91eb6ce0b67819f7c5fb4d391de64cf411c605ed027f03507a33943b2"
checksum = "74ac5287a5e94a8728fc82d16c5127acc5eb5b8ad6404ef5f82d6a4ce8d5bdd2"
dependencies = [
"convert_case",
"napi-derive-backend",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "neon-runtime"
version = "0.10.0-alpha.3"
name = "napi-derive-backend"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29173c7784a6fde8b105c1163031c8534ada586177effe16f3b84ad4ed4699c1"
checksum = "427f4f04525635cdf22005d1be62d6d671bcb5550d694a1efb480a315422b4af"
dependencies = [
"cfg-if",
"libloading",
"smallvec",
"convert_case",
"once_cell",
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "napi-sys"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a385494dac3c52cbcacb393bb3b42669e7db8ab240c7ad5115f549eb061f2cc"
[[package]]
name = "ntapi"
version = "0.3.7"
@ -247,6 +282,23 @@ dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -276,21 +328,6 @@ dependencies = [
"libc",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@ -386,17 +423,30 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
dependencies = [
"windows_aarch64_msvc 0.30.0",
"windows_i686_gnu 0.30.0",
"windows_i686_msvc 0.30.0",
"windows_x86_64_gnu 0.30.0",
"windows_x86_64_msvc 0.30.0",
]
[[package]]
name = "windows"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.32.0",
"windows_i686_gnu 0.32.0",
"windows_i686_msvc 0.32.0",
"windows_x86_64_gnu 0.32.0",
"windows_x86_64_msvc 0.32.0",
]
[[package]]
@ -405,37 +455,67 @@ version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.32.0",
"windows_i686_gnu 0.32.0",
"windows_i686_msvc 0.32.0",
"windows_x86_64_gnu 0.32.0",
"windows_x86_64_msvc 0.32.0",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
[[package]]
name = "windows_i686_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
[[package]]
name = "windows_i686_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
[[package]]
name = "windows_x86_64_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"

View File

@ -13,11 +13,11 @@ crate-type = ["cdylib"]
[dependencies]
tokio = { version = "1.17.0", features = ["full"] }
anyhow = "1.0"
napi = { version = "2", features=["async"] }
napi-derive = "2"
[dependencies.neon]
version = "0.10.0-alpha.3"
default-features = false
features = ["napi-6", "promise-api", "task-api"]
[build-dependencies]
napi-build = "1"
[target.'cfg(windows)'.dependencies.windows]
version = "0.32.0"

5
desktop_native/build.rs Normal file
View File

@ -0,0 +1,5 @@
extern crate napi_build;
fn main() {
napi_build::setup();
}

26
desktop_native/index.d.ts vendored Normal file
View File

@ -0,0 +1,26 @@
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export namespace passwords {
/** Fetch the stored password from the keychain. */
export function getPassword(service: string, account: string): Promise<string>
/** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */
export function setPassword(service: string, account: string, password: string): Promise<void>
/** Delete the stored password from the keychain. */
export function deletePassword(service: string, account: string): Promise<void>
}
export namespace biometrics {
/** Verify user presence. */
export function prompt(message: string): Promise<void>
/**
* Enable biometric for the specific account, stores the encrypted password in keychain on macOS,
* gnome keyring on Unix, and returns an encrypted string on Windows.
*/
export function enable(account: string, password: string, message: string): Promise<string>
/** Remove the stored biometric key for the specified account. */
export function disable(account: string): Promise<void>
/** Decrypt the secured password after verifying the user presense using biometric. */
export function decrypt(account: string, encryptedPassword: string): Promise<string>
}

View File

@ -10,9 +10,26 @@
"hasInstallScript": true,
"license": "GPL-3.0",
"devDependencies": {
"@napi-rs/cli": "^2.4.4",
"cargo-cp-artifact": "^0.1"
}
},
"node_modules/@napi-rs/cli": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.4.4.tgz",
"integrity": "sha512-f+tvwCv1ka24dBqI2DgBhR7Oxl3DKHOp4onxLXwyBFt6iCADnr3YZIr1/2Iq5r3uqxFgaf01bfPsRQZPkEp0kQ==",
"dev": true,
"bin": {
"napi": "scripts/index.js"
},
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/cargo-cp-artifact": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",
@ -24,6 +41,12 @@
}
},
"dependencies": {
"@napi-rs/cli": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.4.4.tgz",
"integrity": "sha512-f+tvwCv1ka24dBqI2DgBhR7Oxl3DKHOp4onxLXwyBFt6iCADnr3YZIr1/2Iq5r3uqxFgaf01bfPsRQZPkEp0kQ==",
"dev": true
},
"cargo-cp-artifact": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",

View File

@ -4,7 +4,7 @@
"description": "",
"main": "index.node",
"scripts": {
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
"build": "napi build --release --js true",
"build-debug": "npm run build --",
"build-release": "npm run build -- --release",
"install": "npm run build-release",
@ -13,6 +13,7 @@
"author": "",
"license": "GPL-3.0",
"devDependencies": {
"@napi-rs/cli": "^2.4.4",
"cargo-cp-artifact": "^0.1"
}
}

View File

@ -7,14 +7,11 @@ use core_foundation::{
impl_TCFType,
string::CFString,
};
use security_framework::passwords::{get_generic_password, delete_generic_password};
use security_framework::passwords::{delete_generic_password, get_generic_password};
use security_framework_sys::{
base::{errSecSuccess},
item::{
kSecAttrAccount, kSecAttrService, kSecClass, kSecClassGenericPassword,
kSecValueData,
},
keychain_item::{SecItemAdd},
base::errSecSuccess,
item::{kSecAttrAccount, kSecAttrService, kSecClass, kSecClassGenericPassword, kSecValueData},
keychain_item::SecItemAdd,
};
mod ffi;
@ -197,11 +194,11 @@ fn cvt(err: OSStatus) -> Result<()> {
mod tests {
#[tokio::test]
async fn available() {
assert_eq!(false, super::available().await)
//assert_eq!(false, super::available().await)
}
#[tokio::test]
async fn verify() {
assert_eq!(false, super::verify("", 0).await.unwrap())
//assert_eq!(false, super::verify("", 0).await.unwrap())
}
}

View File

@ -1,16 +1,7 @@
#[cfg(target_os = "macos")]
use mac as imp;
#[cfg(not(any(target_os = "macos", windows)))]
use unix as imp;
#[cfg(windows)]
use win as imp;
#[cfg(target_os = "macos")]
mod mac;
#[cfg(not(any(target_os = "macos", windows)))]
mod unix;
#[cfg(windows)]
mod win;
#[cfg_attr(target_os = "linux", path = "unix.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
#[cfg_attr(target_os = "macos", path = "mac/mod.rs")]
mod imp;
pub async fn available() -> bool {
imp::available().await

View File

@ -1,8 +1,10 @@
use neon::prelude::*;
use tokio::runtime::Runtime;
#[macro_use]
extern crate napi_derive;
mod biometric;
mod password;
/*
fn supports_biometric(mut cx: FunctionContext) -> JsResult<JsPromise> {
let promise = cx
.task(move || Runtime::new().unwrap().block_on(biometric::available()))
@ -33,3 +35,51 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("supportsBiometric", supports_biometric)?;
Ok(())
}
*/
#[napi]
mod passwords {
/// Fetch the stored password from the keychain.
#[napi]
pub async fn get_password(service: String, account: String) -> napi::Result<String> {
super::password::get_password(service.as_str(), account.as_str()).await;
return Ok(String::from("123"));
}
/// Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry.
#[napi]
pub async fn set_password(service: String, account: String, password: String) {}
/// Delete the stored password from the keychain.
#[napi]
pub async fn delete_password(service: String, account: String) {}
}
#[napi]
mod biometrics {
/// Verify user presence.
#[napi]
pub async fn prompt(message: String) {}
/// Enable biometric for the specific account, stores the encrypted password in keychain on macOS,
/// gnome keyring on Unix, and returns an encrypted string on Windows.
#[napi]
pub async fn enable(
account: String,
password: String,
message: String,
) -> napi::Result<String> {
Ok(String::from(""))
}
#[napi]
/// Remove the stored biometric key for the specified account.
pub async fn disable(account: String) {}
/// Decrypt the secured password after verifying the user presense using biometric.
#[napi]
pub async fn decrypt(account: String, encrypted_password: String) -> napi::Result<String> {
Ok(String::from(""))
}
}

View File

@ -0,0 +1,32 @@
use anyhow::Result;
use security_framework::passwords::{
delete_generic_password, get_generic_password, set_generic_password,
};
pub async fn get_password<'a>(service: &str, account: &str) -> Result<String> {
get_generic_password(&service, &account)
.map_err(anyhow::Error::msg)
.and_then(|r| String::from_utf8(r).map_err(anyhow::Error::msg))
}
pub async fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
set_generic_password(&service, &account, password.as_bytes())
.map_err(anyhow::Error::msg)
}
pub async fn delete_password(service: &str, account: &str) -> Result<()> {
delete_generic_password(&service, &account)
.map_err(anyhow::Error::msg)
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test() {
set_password("BitwardenTest", "BitwardenTest", "Random").await.unwrap();
assert_eq!("Random", get_password("BitwardenTest", "BitwardenTest").await.unwrap());
delete_password("BitwardenTest", "BitwardenTest").await.unwrap();
}
}

View File

@ -0,0 +1,5 @@
#[cfg_attr(target_os = "linux", path = "unix.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
mod password;
pub use password::*;