in reply to Crypt:OpenPGP Recipients Problem

I've never used Crypt::OpenPGP, but I know a little about OpenPGP and GnuPG in particular.

I'm not clear on what you mean when you say you add USER1 to an ADMIN group. GnuPG allows you to specify a group in its config file, but this is like an email alias. When you specify the group as a recipient, GnuPG will treat that as if you had specified all of the group's members as recipients.

It might help to show more of the procedure you went through to create the group, add keys to it, and how you're invoking Crypt::OpenPGP to create your messages. Crypt::OpenPGP doesn't seem to have any facilities for managing a keyring, so I'm guessing you are using an external tool to create your keys and populate the database you mention. Whatever you can tell us about that might help us solve your problem also.

Replies are listed 'Best First'.
Re^2: Crypt:OpenPGP Recipients Problem
by radtad (Initiate) on Jan 10, 2008 at 22:40 UTC
    Thanks for the input. The code is a little convoluted, so I'll try to include only some of the major parts.
    createGroup('ADMIN','foo'); createUser('USER1','bar'); createUser('USER2','bar2'); addGroupUser('USER1','ADMIN'); decryptGroupData('ADMIN','bar'); sub initPGP { my($uid) = @_; my(%args,$sql,$sth,$ret,$public,$secret,$ring,$kb,$pubring,$secrin +g); if ($uid =~ m#\d{3,6}$#) { $sql = "SELECT public,secret FROM gpg_user WHERE code=$uid"; } else { $sql = "SELECT public,secret FROM gpg_group WHERE group_name='$uid'"; } $sth = runSQL($sql); $ret = $sth->fetchrow_arrayref; if ($ret) { ($public,$secret) = unarmourKeys($ret->[0],$ret->[1]); $pubring = Crypt::OpenPGP::KeyRing->new( Data => $pub +lic ); $secring = Crypt::OpenPGP::KeyRing->new( Data => $sec +ret ); $kb = $pubring->find_keyblock_by_uid($uid); $args{SecRing} = $secring; $args{PubRing} = $pubring; } $args{Compat} = COMPAT; $args{Verbosity} = DEBUG; return(Crypt::OpenPGP->new(%args),$kb); } sub unarmourKeys { my($public,$secret) = @_; my($pubsaved,$secsaved); $pubsaved = uri_unescape($public); $secsaved = uri_unescape($secret); $pubsaved = Crypt::OpenPGP::Armour->unarmour($pubsaved); $secsaved = Crypt::OpenPGP::Armour->unarmour($secsaved); return($pubsaved->{Data},$secsaved->{Data}); } sub addGroupUser { my($code,$grouppass,$group) = @_; my($groupid,$sql); $groupid = getGroupID($group); if ($code && $groupid) { $sql = "INSERT INTO gpg_group_user(groupid,code) VALUES ('$groupid','$code')"; runSQL($sql); encryptGroupData($grouppass,$group); } } sub createUser { my($code,$password) = @_; my($info,$public,$secret,$finger,$keyid,$uid, $sql,$data,$pubring,$secring,@recipients); $info = genKeys($password,$code); $public = $info->{public}; $secret = $info->{secret}; $finger = $info->{finger}; $keyid = $info->{keyid}; if ($finger) { $sql = "INSERT INTO gpg_user(code,public,secret,fingerprint) VALUES ($code,'$public','$secret','$finger')"; runSQL($sql); push(@recipients, $keyid); ($pubring,$secring) = unarmourKeys($public,$secret); print "ENCODED: " . encode_base64($password) . "\n"; $info->{public} = $pubring; $info->{secret} = $secring; $info->{text} = encode_base64($password); $info->{recipients} = \@recipients; $info->{password} = $password; $data = encryptData($code,$info); $sql = "UPDATE gpg_user SET data='$data' WHERE code='$code'"; runSQL($sql); } } sub createGroup { my($group, $password) = @_; my($sql,$info,$pubring,$secring,@recipients,$public,$secret,$data); $info = genKeys($password,$group); if ($info->{keyid}) { $public = $info->{public}; $secret = $info->{secret}; push(@recipients, $info->{keyid}); ($pubring,$secring) = unarmourKeys($public,$secret); $info->{public} = $pubring; $info->{secret} = $secring; $info->{text} = encode_base64($password); $info->{recipients} = \@recipients; $info->{password} = $password; $data = encryptData($group,$info); $sql = "INSERT INTO gpg_group(group_name,fingerprint,public, secret,description,data) VALUES ('$group','$info->{finger}','$public', '$secret','','$data')"; runSQL($sql); } } sub encryptData { my($groups,$info) = @_; my($pgp,$encrypt,$kb,%encArgs,$group); $pgp = initRingsPGP($info->{public},$info->{secret}); $encArgs{Data} = $info->{text}; $encArgs{Recipients} = $info->{recipients}; $encArgs{Armour} = 1; $encrypt = $pgp->encrypt(%encArgs) or die "Error encrypt: " . $pgp +->errstr; $encrypt = uri_escape($encrypt); return($encrypt); } sub initRingsPGP { my($public,$secret) = @_; my($pubring,$secring,%args); $pubring = Crypt::OpenPGP::KeyRing->new( Data => $public ); $secring = Crypt::OpenPGP::KeyRing->new( Data => $secret ); $args{SecRing} = $secring; $args{PubRing} = $pubring; $args{Compat} = COMPAT; $args{Verbosity} = DEBUG; return(Crypt::OpenPGP->new(%args)); } sub encryptGroupData { my($grouppass,$group) = @_; my($text,$info,$encrypt,$sql); $info = setGroupRecipients($group); $info->{text} = encode_base64($grouppass); $encrypt = encryptData($group,$info); $sql = "UPDATE gpg_group SET data='$encrypt' WHERE group_name='$group'"; runSQL($sql); } sub setGroupRecipients { my($group) = @_; my(@recipients,$info,$ring,$public,$uids); $info = getGroupUsersPubkey($group); $public = $info->{public}; $uids = $info->{uids}; $ring = Crypt::OpenPGP::KeyRing->new( Data => $public ); foreach my $uid (@{$uids}) { my $kb = $ring->find_keyblock_by_uid($uid); my $keyid = $kb->key->key_id_hex; push(@recipients, $keyid); } push(@recipients, $info->{keyid} ); $info->{recipients} = \@recipients; return($info); } sub getGroupUsersPubkey { my($group) = @_; my($sql,$sth,$ret,@public,@secret,@uids,$info,$ring,$kb,$keyid,@ke +yids); $sql = "SELECT public,secret FROM gpg_group WHERE group_name='$gro +up'"; $sth = runSQL($sql); $ret = $sth->fetchrow_arrayref; my($pubring,$secring) = unarmourKeys($ret->[0],$ret->[1]); push(@public, $pubring ); push(@secret, $secring ); $ring = Crypt::OpenPGP::KeyRing->new( Data => $pubring ); $kb = $ring->find_keyblock_by_uid($group); $keyid = $kb->key->key_id_hex; $sql = "SELECT u.code,u.public,u.secret FROM gpg_user u, gpg_group_user i, gpg_group g WHERE u.code=i.code AND i.groupid=g.id AND g.group_name='$group'"; $sth = runSQL($sql); while($ret = $sth->fetchrow_arrayref) { my($pub,$sec) = unarmourKeys($ret->[1],$ret->[2]); push(@uids, $ret->[0]); push(@public, $pub ); push(@secret, $sec ); } $info->{keyid} = $keyid; $info->{public} = join("", @public); $info->{secret} = join("", @secret); $info->{uids} = \@uids; return($info); } sub decryptGroupData { my($group,$password) = @_; my($sql,$sth,$ret,$data,$encrypt,%decArgs,$info,@groups); $info = getGroupUsersPubkey($group); $sql = "SELECT data FROM gpg_group WHERE group_name='$group' AND active"; $sth = runSQL($sql); $ret = $sth->fetchrow_arrayref; $info->{data} = $ret->[0]; $info->{pass} = $password; $info->{uid} = $group; my($dec,$valid,$sig) = gpgDecryptData($info); return decode_base64($dec); }
      Found the problem. This sub should be this instead of what it was:
      sub decryptGroupData { my($group,$password,$code) = @_; my($sql,$sth,$ret,$data,$encrypt,%decArgs,$info,@groups,$ring,$kb, +$keyid); $sql = "SELECT data, public, secret FROM gpg_user WHERE code='$code' AND active"; $sth = runSQL($sql); $ret = $sth->fetchrow_arrayref; my($pubring,$secring) = unarmourKeys($ret->[1],$ret->[2]); $ring = Crypt::OpenPGP::KeyRing->new( Data => $pubring ); $kb = $ring->find_keyblock_by_uid($code); $keyid = $kb->key->key_id_hex; $info->{keyid} = $keyid; $info->{public} = $pubring; $info->{secret} = $secring; $info->{uid} = $code; $sql = "SELECT data FROM gpg_group WHERE group_name='$group' AND active"; $sth = runSQL($sql); $ret = $sth->fetchrow_arrayref; $info->{data} = $ret->[0]; $info->{pass} = $password; my($dec,$valid,$sig) = gpgDecryptData($info); return decode_base64($dec); }