Skip to content

Commit

Permalink
wip: fix public key parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
cilki committed Jun 8, 2024
1 parent 4fdc986 commit 457395d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 49 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ chrono = "0.4.38"
tokio_schedule = "0.3.1"
base64 = "0.22.1"
hex = "0.4.3"
# gpgme = "0.11.0"

[features]
monero = ["dep:monero-rpc"]
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ occurs, maintainers can cancel payouts or ban contributors.

Since `turbine` is self-hosted, the crypto wallet is fully under control of the
project owner. We have to trust them not to misuse funds deposited in `turbine`,
just like we have to trust them not to include a backdoor in the software.
just like we have to trust them not to include a backdoor in the software (for example).

## Using `turbine` as a contributor

Expand All @@ -47,9 +47,47 @@ is currently small enough to maintain here:

TODO

### Generate a GPG keypair

If you don't already have a GPG keypair, generate a new one:

```
gpg --full-generate-key
```

Make sure to use the same email address as your git config: `git config user.email`.

### Setup commit signing

Turn on commit signing globally (or on a per-repo basis):

```
git config --global commit.gpgsign true
git config --global user.signingkey <public key ID>
```

### Send your public key to a keyserver

To allow `turbine` to find your public key and verify commits, upload it to this
keyserver:

```
gpg --keyserver hkp://keys.gnupg.net --send-keys <public key ID>
```

### Commit your payment address

Add your payment address to a signed commit message so `turbine` knows who to pay.
If you ever update your GPG key or wallet address, this commit can be made multiple
times and the last one takes effect.

```
git commit --allow-empty -m "turbine: XMR <wallet address>"
```

### Start contributing!

Contribute as normal and `turbine` will pay you automatically.

## Running your own `turbine`

Expand Down
2 changes: 1 addition & 1 deletion src/currency/monero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl MoneroState {

Ok(transfers
.get(&GetTransfersCategory::Out)
.unwrap()
.unwrap_or(&vec![])
.iter()
.filter(|transfer| transfer.address.to_string() == address.to_string())
.count())
Expand Down
89 changes: 42 additions & 47 deletions src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,58 +55,25 @@ fn get_public_key_id(commit: &Commit) -> Result<String> {
if let Some(header) = commit.raw_header() {
if let Some((_, gpgsig)) = header.split_once("gpgsig") {
let mut signature_base64 = String::new();
let mut lines = gpgsig.lines();
loop {
match lines.next() {
Some(line) => {
if line.starts_with("-----BEGIN") {
continue;
} else if line.starts_with("-----END") {
break;
} else {
signature_base64.push_str(&line);
}
}
None => bail!("Failed to get GPG signature"),
for line in gpgsig.lines() {
let line = line.trim();
if line.starts_with("-----BEGIN") {
continue;
} else if line.starts_with("=") {
// Ascii armor checksum means we're done
break;
} else {
signature_base64.push_str(&line);
}
}

let decoded = BASE64_STANDARD.decode(signature_base64)?;
return Ok(hex::encode(&decoded[19..26]));
return Ok(hex::encode(&decoded[12..32]));
}
}
bail!("Failed to get GPG public key ID");
}

/// Verify a commit's GPG signature and return its key ID.
#[instrument(ret)]
fn verify_signature(commit: &Commit) -> Result<String> {
// Receive the public key first
Command::new("gpg")
.arg("--recv-keys")
.arg(get_public_key_id(&commit)?)
.spawn()?
.wait()?;

let output = Command::new("git")
.arg("verify-commit")
.arg("--raw")
.arg(commit.id().to_string())
.stdout(Stdio::piped())
.output()?;
let output = std::str::from_utf8(&output.stdout)?;

trace!(output = output, "verify-commit output");
for line in output.lines() {
if line.contains("GOODSIG") {
return Ok(line.split_whitespace().nth(2).unwrap().into());
}
}

// TODO verify the signature ourselves
bail!("Failed to verify signature");
}

impl TurbineRepo {
pub fn new(remote: &str, branch: &str) -> Result<Self> {
let tmp = tempfile::tempdir()?;
Expand All @@ -125,6 +92,33 @@ impl TurbineRepo {
Ok(repo)
}

/// Verify a commit's GPG signature and return its key ID.
#[instrument(ret)]
fn verify_signature(&self, commit: &Commit) -> Result<String> {
// Receive the public key first
Command::new("gpg")
.arg("--keyserver")
.arg("hkp://keys.gnupg.net")
.arg("--recv-keys")
.arg(get_public_key_id(&commit)?)
.spawn()?
.wait()?;

// TODO verify the signature ourselves (gpgme?)
if Command::new("git")
.arg("verify-commit")
.arg(commit.id().to_string())
.current_dir(self.tmp.path())
.spawn()?
.wait()?
.success()
{
Ok(get_public_key_id(&commit)?)
} else {
bail!("Failed to verify signature");
}
}

pub fn refresh(&mut self) -> Result<()> {
// Always fetch the repo first
debug!("Fetching upstream repo");
Expand Down Expand Up @@ -159,9 +153,10 @@ impl TurbineRepo {
}
}

if let Ok(key_id) = verify_signature(&commit) {
if let Ok(key_id) = self.verify_signature(&commit) {
if let Some(message) = commit.message() {
if let Some((_, address)) = message.split_once("XMR") {
let address = address.trim().to_string();
if let Some(contributor) = self
.contributors
.iter_mut()
Expand All @@ -172,10 +167,10 @@ impl TurbineRepo {
new = ?address,
"Updating contributor address"
);
contributor.address = Address::XMR(address.into());
contributor.address = Address::XMR(address);
} else {
let contributor = Contributor {
address: Address::XMR(address.into()),
address: Address::XMR(address),
last_payout: None,
key_id,
commits: Vec::new(),
Expand Down Expand Up @@ -207,7 +202,7 @@ impl TurbineRepo {
}
}

if let Ok(key_id) = verify_signature(&commit) {
if let Ok(key_id) = self.verify_signature(&commit) {
if let Some(contributor) = self
.contributors
.iter_mut()
Expand Down

0 comments on commit 457395d

Please sign in to comment.