[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: gpg changesets (was Re: Bits from the DPL: DSA and buildds and DAM, oh my!)

Anthony Towns wrote:
> On Fri, Feb 23, 2007 at 11:15:00PM -0500, Joey Hess wrote:
> > Changed-By: Joey Hess <joeyh@debian.org>
> > Comment: Removing an old email address.
> I'm not sure that's plausible -- afaik the keyring gets synced to the
> real keyservers for new signatures and uids, so removing addresses
> doesn't work; though iirc you can do a revocation of a uid these days.

Sure, I just wanted to show it can be used for anything you'd do via
--edit-keys. I'm not sure what classes of changes keyring-maint
typically makes so it seemed best to cover all of them.

> There should be some way of getting back to the original conversation
> in case something goes wrong. I guess a field containing a URL to an rt
> entry or similar would work?

Could be an url or even the whole message included, sure. I also left
out a Date field, which should be included.

> > Note that this is a relative changeset: its action depends on the
> > keyring it's run on, since it deletes uid 3 of 788A3F4C. 
> That means you can't reorder changesets easily. I wonder if it'd be
> better say "del uid joeyh@master.debian.org" and have the tool work out
> which uid (if any) that is.

I don't feel that reordering changesets is a good thing in general, since
it can lead to other problems (for example, reordering a key deletion to
come before a key addition), and it loses history that can be useful for
reviewing why and when a given change was made.

> > joey@kodama:~>cmp input.gpg TESTRING.gpg 
> > joey@kodama:~>
> Didn't you delete a uid as well as add and remove a key? Why aren't
> there differences?

Because it's a review tool, so it's not intended to actually change the
input keyring. For that something like the attached would be used.

see shy jo
# Applies a changeset to a keyring.
use warnings;
use strict;
use File::Temp;

my @allowed_actions=qw(import edit-key delete-key);
my @gpgopts=qw(--command-fd 0 --no-auto-check-trustdb --no-default-keyring);

my $keyring=shift || usage();
my $changeset=shift || usage();

push @gpgopts, "--keyring", $keyring;

my %fields;
my $field;
open(CHANGESET, "<", $changeset) || die "$changeset: $!";
while (<CHANGESET>) {
	if (/^([^\s]+):(?:\s+(.*))?/) {
		$field=lc $1;
		if (defined $2) {
		else {
	elsif (/^\s+\.$/ && defined $field) {
	elsif (/^\s+(.*)/ && defined $field) {
		$fields{$field}.="\n" if length $fields{$field};
	elsif ($_ eq "") {
		process() if defined $field;
	else {
		die "parse error on line $. of $changeset";
process() if defined $field;

sub process {
	if (! exists $fields{action}) {
		die "$changeset missing action field";
	my @action=split(' ', $fields{action});
	my $command=shift @action;
	if (! grep { $_ eq $command } @allowed_actions) {
		die "$changeset contains disallowed action \"$command\"";
	if (! exists $fields{data}) {
		die "$changeset missing data field";

	my $pid = open(GPG, "|-");
	$SIG{PIPE} = sub { die "whoops, pipe broke" };
	if (! $pid) {
		print "gpg --$command @action\n";
		exec("gpg", @gpgopts, "--$command", @action) ||
			die("failed to run gpg");
	foreach my $line (split("\n", $fields{data})) {
		print ">> $line\n" if $command ne 'import';
		print GPG "$line\n" || die "failed talking to gpg";
	close GPG || die "gpg exited nonzero";
	print "gpg operation complete\n\n";

sub usage {
	die "Usage: changeset-apply keyring changeset\n"; 

Attachment: signature.asc
Description: Digital signature

Reply to: