Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
toolchain: 1.81.0
override: true
- name: Cache dependencies
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-dependencies
with:
Expand Down
35 changes: 16 additions & 19 deletions bpb/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,22 @@ struct PublicKey {
}

fn keys_file() -> std::path::PathBuf {
// for archaic reasons we first check the config path
// however this is an error, we shouldn’t store this as config seeing as it is
// tied to the private key which is likely a host setting and should not thus be
// synced between machines
// for archaic reasons we first check the config path
// however this is an error, we shouldn’t store this as config seeing as it is
// tied to the private key which is likely a host setting and should not thus be
// synced between machines

let config_path = if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") {
std::path::PathBuf::from(config_home).join("pkgx/bpb.toml")
} else {
std::path::PathBuf::from(std::env::var("HOME").unwrap()).join(".config/pkgx/bpb.toml")
};
let config_path = if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") {
std::path::PathBuf::from(config_home).join("pkgx/bpb.toml")
} else {
std::path::PathBuf::from(std::env::var("HOME").unwrap()).join(".config/pkgx/bpb.toml")
};

if config_path.exists() {
config_path
} else {
let data_path = if let Ok(data_home) = std::env::var("XDG_DATA_HOME") {
std::path::PathBuf::from(data_home).join("pkgx/bpb.toml")
} else {
std::path::PathBuf::from(std::env::var("HOME").unwrap()).join(".local/share/pkgx/bpb.toml")
};
data_path
}
if config_path.exists() {
config_path
} else if let Ok(data_home) = std::env::var("XDG_DATA_HOME") {
std::path::PathBuf::from(data_home).join("pkgx/bpb.toml")
} else {
std::path::PathBuf::from(std::env::var("HOME").unwrap()).join(".local/share/pkgx/bpb.toml")
}
}
6 changes: 2 additions & 4 deletions bpb/src/keychain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ pub fn add_keychain_item(service: &str, account: &str, secret: &str) -> Result<(
Ok(())
} else {
Err(failure::err_msg(format!(
"SecItemAdd failed with status: {}",
status
"SecItemAdd failed with status: {status}"
)))
}
}
Expand Down Expand Up @@ -155,8 +154,7 @@ pub fn get_keychain_item(service: &str, account: &str) -> Result<String, Error>
Ok(secret)
} else {
Err(failure::err_msg(format!(
"SecItemCopyMatching failed with status: {}",
status
"SecItemCopyMatching failed with status: {status}"
)))
}
}
Expand Down
40 changes: 38 additions & 2 deletions bpb/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ fn main() -> Result<(), Error> {
Some("import") => import(),
Some("upgrade") => upgrade(),
Some("print") => print_public_key(),
Some("fingerprint") => print_fingerprint(),
Some("key-id") => print_key_id(),
Some("--help") => print_help_message(),
Some(arg) if gpg_sign_arg(arg) => verify_commit(),
_ => {
Expand All @@ -54,7 +56,10 @@ fn print_help_message() -> Result<(), Error> {
println!("A program for signing git commits.\n");
println!("Arguments:");
println!(" init <userid>: Generate a keypair and store in the keychain.");
println!(" print: Print public key in OpenPGP format.\n");
println!(" import <key>: Import a key from the command line.");
println!(" print: Print public key in OpenPGP format.");
println!(" fingerprint: Print the fingerprint of the public key.");
println!(" key-id: Print the key ID of the public key.\n");
println!("See https://github.com/pkgxdev/bpb for more information.");
Ok(())
}
Expand Down Expand Up @@ -104,6 +109,29 @@ fn print_public_key() -> Result<(), Error> {
Ok(())
}

fn get_fingerprint() -> Result<pbp::Fingerprint, Error> {
let config = Config::load()?;
let service = config.service();
let account = config.user_id();
let secret_str = get_keychain_item(service, account)?;
let secret = to_32_bytes(&secret_str)?;

let keypair = KeyData::load(&config, secret)?;
Ok(keypair.fingerprint())
}

// Prints the fingerprint (sha256 hash of the public key -- 20 bytes)
fn print_fingerprint() -> Result<(), Error> {
println!("{}", pretty_print_hex_string(&get_fingerprint()?));
Ok(())
}

// Prints the long key ID (the last 8 bytes of the fingerprint)
fn print_key_id() -> Result<(), Error> {
println!("{}", pretty_print_hex_string(&get_fingerprint()?[12..]));
Ok(())
}

fn verify_commit() -> Result<(), Error> {
use std::io::Read;

Expand All @@ -123,7 +151,7 @@ fn verify_commit() -> Result<(), Error> {
let sig = keypair.sign(commit.as_bytes())?;

eprintln!("\n[GNUPG:] SIG_CREATED ");
println!("{}", sig);
println!("{sig}");
Ok(())
}

Expand Down Expand Up @@ -167,3 +195,11 @@ fn to_32_bytes(slice: &String) -> Result<[u8; 32], Error> {
array[..len].copy_from_slice(&vector[..len]);
Ok(array)
}

// iterates over a hex array and prints space-separated groups of four characters
fn pretty_print_hex_string(hex: &[u8]) -> String {
hex.chunks(2)
.map(hex::encode_upper)
.collect::<Vec<String>>()
.join(" ")
}
Loading