-
-
Notifications
You must be signed in to change notification settings - Fork 573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sign git commits with SSH keys #1149
Comments
GitHub now supports verifying commits using SSH keys: https://github.blog/changelog/2022-08-23-ssh-commit-verification-now-supported/ |
this feature needs to be supported by upstream |
I did try to implement GPG signing in the past as part of #97, and it turned out to be very difficult, due to not having a native Rust crate for the GPG part. Basically, it complicated builds on Windows due to some extra C dependencies and licensing might be problematic too. So I recently tried out to implement SSH signing instead, as I discovered the relatively new The workflow is exactly the same as with GPG signing, so we wouldn't have to wait for Here is a very minimal example: # Cargo.toml
[package]
name = "gitsign"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.66"
dirs = "4.0.0"
git2 = "0.15.0"
ssh-key = { version = "0.5.0-rc.0", features = ["ed25519", "encryption"] } // src/main.rs
use std::{env, fs};
use anyhow::Result;
use git2::Repository;
use ssh_key::{HashAlg, LineEnding, PrivateKey};
fn main() -> Result<()> {
// Create a new repo at ./tmp
let dir = env::current_dir()?.join("tmp");
fs::remove_dir_all(&dir).ok();
fs::create_dir_all(&dir)?;
let repo = Repository::init(&dir)?;
// Prepare an empty commit
let mut index = repo.index()?;
let tree = index.write_tree()?;
let tree = repo.find_tree(tree)?;
let signature = repo.signature()?;
let content = repo.commit_create_buffer(&signature, &signature, "Initial commit", &tree, &[])?;
let content = String::from_utf8(content.to_vec())?;
// Sign with SSH key
let ssh_dir = dirs::home_dir().unwrap().join(".ssh");
let key = fs::read(ssh_dir.join("id_ed25519"))?;
let key = PrivateKey::from_openssh(key)?.decrypt("<YOUR PRIVATE KEY PASSWORD>")?;
let sig = key
.sign("git", HashAlg::Sha256, content.as_bytes())?
.to_pem(LineEnding::default())?;
// Perform actual commit
let commit = repo.commit_signed(&content, &sig, None)?;
let commit = repo.find_commit(commit)?;
repo.branch("main", &commit, true)?;
Ok(())
} After running it, you can go to the @extrawurst with that, what do you think about implementing SSH signing first, before continuing on the GPG signing path, which seems rather stuck? There is just one problem: Getting the private key. The Git configuration allows different ways of specifying the key. It can be:
Given all these possible options, it might even be easier to just do the same as Git and shell out to |
absolutely welcome. and as usual I am for implementing the first version (MVP) of it as simple as possible and then iterate over it. so I assume a direct path to the key to be used via program param would be the way to go. after that we should look into querying the agent and only afterwards go for the most complicated version where we need to have a UI for the user to choose from key options. |
This issue has been automatically marked as stale because it has not had any activity half a year. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
Still relevant. |
libgit2/libgit2#6617 - soon supported by upstream |
Also really interesting read about another tool using libgit2-only without shellout to support ssh signing: https://blog.gitbutler.com/signing-commits-in-git-explained/ |
Since this is now supported upstream in libgit2, will gitui automatically respect the |
@SaadiSave there was no release of |
Hi @dnaka91 Do you have any idea about this? Many thanks. |
Despite this now being ssh signature signing, it's reusing the old header. You can see in the above link that it's still under the Makes sense because even the settings are still all the same and just swap the underlying signing program (more or less). |
I got it. There is still a problem here. |
Also, I am not sure the None is valid for BUG: gpg-interface.c:284: bad signature '-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgTjgfFOnWZfMF8CBzrp50Vvs/E6
aHZKmKF2GhZRjHBiUAAAADZ2l0AAAAAAAAAAZzaGEyNTYAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQADCbMrw19YOZSdJxhjCgJvWIRpHT842Wu8xhITmurehYcHtn9pFcibpsx47V0D73f
1zRD4DptJ7v7t9IbKx8Qk=
-----END SSH SIGNATURE-----
'
(END)[1] 24547 abort (core dumped) git log --show-signature |
I noticed a small difference with the regular Git signatures, and that is a trailing newline in the signature. Don't know about gpg-interface so that might be a thing? Just for fun I tried implementing the same thing with The repo is here: https://github.com/dnaka91/gitsign Could it be that your Git CLI is a bit dated and doesn't have the SSH signing feature yet? Edit: I'm using Git 2.43.0 which is the latest version at the time of writing. |
Hi @extrawurst
It seems hard to avoid these. Will the defects be accepted? |
Since SSH signing is now supported by libgit2, can you please reimplement this feature to drop dependency on the |
got same on Alpine Linux with gitui v0.26.3 |
Is your feature request related to a problem? Please describe.
I would like to be able to sign git commits with SSH keys from gitui.
This is a new feature that seems to only work properly with OpenSSH 8.8 and above, which can make it challenging to test on more stable OSes; but if you are able to use it, it seems painless compared to GPG. Because it is new, it also has poor support on GitHub and other code forges, but I expect that will change.
It may also seem premature to consider, given that GPG signing isn't supported in gitui yet; on the other hand, now may be a good time to consider the user interface to make it easy to support signing with SSH keys as well as GPG keys in the future.
The text was updated successfully, but these errors were encountered: