Skip to content

Commit

Permalink
Add function for listing GPG keys
Browse files Browse the repository at this point in the history
  • Loading branch information
silbermm committed Jul 28, 2023
1 parent 1bea3f9 commit 618b6b5
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- function for listing keys on the system

## [0.0.11]
### Updated
Expand Down
4 changes: 4 additions & 0 deletions lib/rust/gpg.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ defmodule GPG.Rust.GPG do

@impl true
def key_info(public_key), do: NIF.key_info(public_key, gpg_home(), gpg_bin())

@impl true
def list_keys(), do: NIF.list_keys(gpg_home(), gpg_bin())

end
1 change: 1 addition & 0 deletions lib/rust/gpg_nif_rust.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ defmodule GPG.Rust.NIF do
def delete_key(_reference, _binary), do: :erlang.nif_error(:nif_not_loaded)
def import_key(_binary, _home_dir, _path), do: :erlang.nif_error(:nif_not_loaded)
def key_info(_public_key, _home_dir, _path), do: :erlang.nif_error(:nif_not_loaded)
def list_keys(_home_dir, _path), do: :erlang.nif_error(:nif_not_loaded)
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule GPGMEx.MixProject do
def project do
[
app: :gpgmex,
version: "0.0.11",
version: "0.0.12-pre",
elixir: "~> 1.12",
package: package(),
start_permanent: Mix.env() == :prod,
Expand Down
39 changes: 37 additions & 2 deletions native/gpg_rust_nif/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use gpgme::{Context, Data, EncryptFlags, Key, Protocol};
use gpgme::{Context, Data, EncryptFlags, Key, Protocol, KeyListMode};
use rustler::{Atom, Error, NifMap, NifTuple};

mod atoms {
Expand Down Expand Up @@ -187,6 +187,7 @@ struct PublicKeyInfo {
pub is_valid: bool,
pub user_ids: Vec<String>,
pub email: Vec<String>,
pub can_sign: bool
}

#[rustler::nif]
Expand All @@ -210,6 +211,7 @@ fn key_info(key: String, home_dir: String, path: String) -> Result<PublicKeyInfo
.user_ids()
.map(|uid| uid.email().unwrap_or("invalid").to_string())
.collect(),
can_sign: k.can_sign(),
});
}
return Err(Error::Term(Box::new("no valid key found".to_string())));
Expand All @@ -218,6 +220,38 @@ fn key_info(key: String, home_dir: String, path: String) -> Result<PublicKeyInfo
}
}

#[rustler::nif]
fn list_keys(home_dir: String, path: String) -> Result<Vec<PublicKeyInfo>, Error> {
let mut ctx = get_context(home_dir, path)?;
ctx.set_key_list_mode(KeyListMode::LOCAL).unwrap();
let mut keys = ctx.find_keys(Vec::<String>::new()).unwrap();
let keyinfos = keys
.by_ref()
.filter_map(|x| x.ok())
.map(|k| PublicKeyInfo {
id: k.id().unwrap_or("").to_string(),
fingerprint: k.fingerprint().unwrap_or("invalid").to_string(),
can_encrypt: k.can_encrypt(),
is_valid: !k.is_invalid(),
user_ids: k
.user_ids()
.enumerate()
.map(|(_, uid)| uid.id().unwrap_or("invalid").to_string())
.collect(),
email: k
.user_ids()
.map(|uid| uid.email().unwrap_or("invalid").to_string())
.collect(),
can_sign: k.can_sign(),
})
.collect();

if keys.finish().unwrap().is_truncated() {
return Err(Error::Term(Box::new("key listing failed".to_string())));
}
Ok(keyinfos)
}

rustler::init!(
"Elixir.GPG.Rust.NIF",
[
Expand All @@ -230,6 +264,7 @@ rustler::init!(
verify_clear,
import_key,
public_key,
key_info
key_info,
list_keys
]
);

0 comments on commit 618b6b5

Please sign in to comment.