Securegit is an open-source tool that provides end-to-end security properties for Git users against other attackers, including compromised Git servers. The underlying scheme of this tool is demonstrated in the paper "End-to-End Encrypted Git Services" accepted by ACM CCS 2025. The artifact is licensed under Apache 2.0.
Before installing, make sure you have Python 3.8 or higher, pip, and Git installed on your system.
It is recommended to use a virtual environment to isolate the package and its dependencies.
Download securegit-0.7.0-py3-none-any.whl.
Please make sure that your local Git username matches your GitHub account username. You can check and update it as follows:
This command creates new SecureGit repositories consisting of two linked repositories:
- A plaintext repository named \<name\>
- An encrypted repository named \<name\>_cipher
It also generates a random 32-byte symmetric key file used for encryption and decryption.
<name> The base name of the repositories. The plaintext repository will be created at ./\<name\>, and the encrypted repository will be created at ./\<name\>_cipher.
--key-path <path> Path to save the generated key file. Defaults to ./symkey.bin.
2. securegit adduser - Share an encrypted SecureGit repository with a user
The command adds a new collaborator (sharee) to an encrypted SecureGit repository. It performs the following actions:
- Copy the sharee’s encryption and signing public keys into the encrypted repository’s shareinfo directory.
- Encrypt the symmetric key for the sharee with AES-CTR and write it to shareinfo/<share_name>_keycipher.bin.
- Sign the shareinfo folder using the owner's private key.
- Send a GitHub repository invitation if a GitHub token and origin remote are available.
<enc_repo_path> Path to the encrypted repository. Must exist.
**Before running this command, make sure that you have created a repository on the GitHub server, and the local encrypted repository has added the remote url. **
--owner-key <owner_key> Path to the owner’s signing private key (DER format). Required.
--share-name <share_name> Username of the new collaborator. Optional. No need when add the owner's public keys.
--enc-pub <enc_pub> Path to the sharee’s encryption public key (DER). Required.
--sig-pub <sig_pub> Path to the sharee’s signing public key (DER). Required.
--sym-key <sym_key> Path to the symmetric key file (binary) to encrypt for the sharee. Required.
--token GitHub personal access token for sending a collaborator invite. Optional. No need when add the owner's public keys.
The username must be the same as the one registered on GitHub.
A repository owner also needs to run this command to add their own public keys owner_enc_pub.der and owner_sign_pub.der to the encrypted repository. For example:
The minimal requirement of tokens used in this command:
- Personal access tokens (classic): choose repo
- Fine-grained personal access token: choose Administration: Read and Write for the seleted reopsitory.
The command works like git add, but with encryption support. It stages changes in the plaintext repository and simultaneously updates the encrypted repository, encrypting modified files according to the configured mode.
On first use, you must specify an encryption mode (--char or --line). This mode will be stored in a configuration file inside the encrypted repository (securegit_config.json). Subsequent invocations will reuse this mode automatically.
<plaintext_repo_path> Path to the plaintext repository. Changes are staged here with git add -A. <encrypted_repo_path> Path to the corresponding encrypted repository. <key_path> Path to the AES key file used for encryption.
--char Update the ciphertext by encrypting the character-wise diff --line Update the ciphertext by encrypting the line-wise diff
The command commits changes to both the plaintext and the encrypted repositories.
<plaintext_repo_path> Path to the plaintext repository to be committed. <encrypted_repo_path> Path to the encrypted repository to be committed. <msg> Commit message to use for the plaintext repository. It must be placed in double quotes. <private_key_path> Path to the private key (DER format) used for generating the commit signature.
5. securegit branch - Same as git branch, but in both plaintext and encrypted repositories at the same time.
This command mirrors the functionality of git branch, but applies it to both the plaintext repository and the encrypted repository. Any arguments passed after the repository paths (such as -M, -d, -a, or branch names) are forwarded directly to git branch.
<plaintext_repo_path> Path to the plaintext repository. <encrypted_repo_path> Path to the encrypted repository. [git branch args...] Additional arguments passed to git branch. For example:
- -M main (rename branch to main)
- -d old-branch (delete branch)
- -a (list all branches, including remote)
The command wraps the standard git remote command but applies only to the encrypted repository. It is typically used to configure or inspect remote connections for the encrypted repository. Any additional arguments after <encrypted_repo_path> are passed directly to git remote.
<encrypted_repo_path> Path to the encrypted repository. [git remote args...] Arguments passed to git remote. For example:
- -v — Show remotes with URLs.
- add <name> <url> — Add a new remote.
- remove <name> — Remove a remote.
- rename <old> <new> — Rename a remote.
- set-url <name> <url> — Change a remote URL.
This command runs git push inside the encrypted repository and streams the output directly to the terminal.
<encrypted_repo_path> Path to the encrypted repository. [git push args...] Additional arguments passed to git push. For example:
- <remote> — Name of the remote (e.g., origin).
- <branch> — Name of the branch to push.
- --force — Force push.
This command fetches an encrypted repository from a remote and reconstructs the corresponding plaintext repository locally. It replays all commits in chronological order, decrypting and applying changes to the plaintext working tree while preserving author and committer information.
<remote_url> Remote URL of the encrypted repository. <encrypted_repo_path> Local path where the encrypted repository will be cloned. <plaintext_repo_path> Local path where the decrypted plaintext repository will be constructed. <owner_name> Repository owner’s username. <sharee_name> Current collaborator’s username. <sharee_privkey> Path to the collaborator’s private key (used to decrypt the symmetric key).
--sym_key_out <file> Save the decrypted symmetric key to (default: ./symkey.bin) -b, --branch <branch> Branch to clone and replay (default: main)
This command ensures that the same .gitignore file is created or updated in both the plaintext and encrypted repositories.
<plaintext_repo_path> Path to the local plaintext repository
<encrypted_repo_path> Path to the corresponding encrypted repository
<patterns...> One or more ignore patterns (files, directories) to be added to .gitignore
The command generates a new key pair that is exported in DER format. Both output paths can be customized.
--privkey-out <path> Path to save the private key (default: ./private_key.der)
--pubkey-out <path> Path to save the public key (default: ./public_key.der)
This command can create a new repository on the GitHub server under the authenticated user’s account. By default, the repository will be public, unless the --private option is given.
<repository-name> The name of the repository to create. Must be unique under your account.
--token <token> GitHub Personal Access Token used for authentication.
--private Create the a private repository. By default, repositories are public.
The minimal requirement of tokens used in this command:
- Personal access tokens (classic): choose repo for private repositories and only choose repo: public for public repositories
- Fine-grained personal access token: choose Administration: Read and Write for the All reopsitory.
This command can updates the encrypted repository by fetching from the given remote and branch and then integrates changes into the local plaintext repository.
<plaintext-repo-path> Local path of the plaintext repository. <encrypted-repo-path> Local path of the encrypted repository.
--sym-key <file> Read the symmetric AES key from the specified file.
--private-key <file> Use the specified private key to decrypt the AES key share stored in the encrypted repository.
--sym-key-out <file> Write the decrypted AES key to the specified path. If not given, defaults to ./symkey.bin.
<remote> The name of the remote to fetch from. Defaults to origin.
<branch> The branch to fetch and replay commits from. Defaults to main.
13. securegit checkout — switch branches or restore working tree in both plaintext and encrypted repositories
This command works like git checkout, but it operates simultaneously on both the plaintext repository and its corresponding encrypted repository.
<plaintext-repo-path> Local path of the plaintext repository. <encrypted-repo-path> Local path of the encrypted repository. [git checkout args...] Arguments passed to git remote. For example:
- -b branch_name — Create a new branch branch_name from the current HEAD.
- branch_name — swift to branch_name.
This command is a secure version of git merge designed for SecureGit environments. It merges two branches in both the plaintext repository and its corresponding encrypted repository, respecting the configured encryption mode (char or line).
<plain_repo_path> Path to the plaintext repository. <encrypted_repo_path> Path to the encrypted repository. <branch_name_a> Base branch to merge into. <branch_name_b> Branch to merge from.
Before run this command, must first swift to the base branch.
** After completing the securegit merge, please follow the prompts to carry out the subsequent operations. **
When you run securegit merge and both branches modify the same part of a file, Git cannot automatically determine which version to keep. Instead of choosing for you, Git marks the conflict directly inside the file so that you can resolve it manually. For example,
<<<<<<< HEAD: Start of conflict (your version)
=======: Separator between the two versions
>>>>>>> branch: End of conflict (other branch’s version)
You must edit the file to remove the markers and decide the final content.
The user must run securegit commit after running securegit add.
The user can run securegit adduser multiple times before running securegit commit.
For one commit, both securegit add and securegit adduser commands can be run.
Navigate to your desired directory where you want to store your repositories.
In order to be able to execute all of the above commands, we recommend generating a classic token with repo permission or a fine-grained token with Administration: Read and Write for all repository.
Before initializing new repositories, you need to creat two public/private keypairs, one is used for encryption, and the other one is used for signing. If you do not have keypairs, please run the following command to generate,
You can change the output path and name, reffering the detailed introduction to this command before.
It will initialize a plaintext repository myrepo and a ciphertext repository myrepo_cipher. It will also output a file named symkey.bin at the current dictionary to store the encryption key for myrepo.
On macOS, it is necessary to create a .gitignore file to prevent .DS_Store from being tracked by Git.
Add the remote url with <token> for the encrypted repository:
It also supports SSH url, please make sure that your local environment is properly configured with an SSH key linked to your GitHub account.
Run the following command to add owner's public key
For example, use the following command to add owner's public keys owner_enc_pub.der and owner_sign_pub.der and sign them with their private key owner_sign_priv.der and encrypt the symmetric key symkey.bin with owner_enc_pub.der.
Run the following command to add collaborator's public key
For example, invite a sharee named alice:
After making changes in your plaintext repository, use securegit add to stage the modifications for encryption:
Only need to specify the mode for the first time.
After running securegit add, then commit the modifications:
Assume alice fetches the latest commits, then run
If alice has the symetric encryption key, then run
Assume alice wants to clone the repository:
To Do: support git merge, Done; support default path; support git credential manager to get token; support different permission for share support bitbuct (adduser, newrepo)
.png)


