This program can be used by anonymous contributors to release partial
information about their identity - they can show that they are someone
from a list of PGP key holders, without revealing which member of the
list they are.  Maybe it can help in the recent controvery over the
identity of anonymous posters.  It's a fairly low-level program that
should be wrapped in a nicer UI.  I'll send a couple of perl scripts
later that make it easier to use.

===

/* Implementation of ring signatures from
 * http://theory.lcs.mit.edu/~rivest/RivestShamirTauman-HowToLeakASecret.pdf
 * by Rivest, Shamir and Tauman
 *
 * This creates and verifies a signature such that it was produced from
 * one of a fixed set of RSA keys.
 *
 * It requires the openssl library to build, which is available from
 * www.openssl.org.
 *
 * This program takes a PGP public key ring file which holds a set of
 * old-style RSA public keys.  It creates and verifies signatures which
 * are such that they were issued by one of the keys in that file, but
 * there is no way to tell which one did it.  In this way the signer can
 * leak partial information about his identity - that he is one member
 * of a selected set of signers.
 *
 * To sign, the signer must also give a PGP secret key file which holds
 * one key (actually the program ignores any keys past the first).
 * That key should be the secret part of one of the keys in the public
 * key file.  Also, it should be set to have no passphrase - it is too
 * complicated for a simple program like this to try to untangle PGP
 * passphrases.  So set your key to have no passphrase, then run this
 * program, then set it back.
 *
 * The program outputs the signature in the form of a list of big numbers,
 * base64 encoded.  There will be as many numbers as there were keys in
 * the public key file.  So signatures are quite large in this scheme,
 * proportional to the number of keys in the group that the signature
 * comes from.  They are also proportional to the largest key in the
 * group, so all else being equal try not to include really big keys if
 * you care about size.
 *
 * The signature is not appended to the text being signed, it is just
 * output separately.  The signer can combine them manually with some kind
 * of cut marks so that the recipient can separate out the signature from
 * the file being signed.  Some perl scripts that do this are supposed
 * to be distributed with the program.  (That is what is used to verify
 * the signature in this file itself.)
 *
 * The recipient must use the same PGP public key file that the signer
 * used.  So that may have to be sent along as well.  He runs the program
 * with the PGP file and the file to be verified, and sends the signature
 * data into stdin (using the "<" character).  The program will print
 * whether the signature is good or not.
 *
 * This program was written in just a couple of evenings so it is
 * a little rough.  This is version 0.9 or so - at least it works.
 * It has only been tested on my Linux system.
 *
 * The program is released into the public domain.  See the end for
 * authorship information.
 */


#include <stdio.h>
#include <stdlib.h>
#include "openssl/bn.h"
#include "openssl/rsa.h"
#include "openssl/sha.h"
#include "openssl/evp.h"

/* Cipher block size; we use Blowfish */
#define CIPHERBLOCK 8

typedef unsigned char uchar;

enum {
        ERR_OK = 0,
        ERR_BADPKT=-100,
        ERR_EOF,
        ERR_SECNOTFOUND,
        ERR_BADSIG,
};


/************************** PGP FILE PARSING ***************************/

/* Read the N and E values from a PGP public key packet */
int
rdpgppub( BIGNUM *n, BIGNUM *e, unsigned *bytesused, uchar *buf, unsigned len )
{
        int nbits, nlen, ebits, elen;
        unsigned o=2;

        if (len < 10)
                return ERR_BADPKT;
        if (buf[0] == 4)                                        /* Check version 4, 3, 
or 2 */
                o = 0;
        else if (buf[0] != 2 && buf[0] != 3) /* V2&3 have 2 extra bytes */
                return ERR_BADPKT;
        if (buf[5+o] != 1)                                      /* Check alg - 1 is 
RSA */
                return ERR_BADPKT;
        nbits = (buf[6+o] << 8) | buf[7+o];     /* Read modulus */
        nlen = (nbits + 7)/8;
        if (len < 10+o+nlen)
                return ERR_BADPKT;
        BN_bin2bn(buf+o+8, nlen, n);
        ebits = (buf[8+o+nlen] << 8) | buf[9+o+nlen];   /* Read exponent */
        elen = (ebits + 7)/8;
        if (len < 10+o+nlen+elen)
                return ERR_BADPKT;
        BN_bin2bn(buf+10+o+nlen, elen, e);
        if (bytesused)
                *bytesused = 10+o+nlen+elen;
        return ERR_OK;
}

/* Read the N, E, D values from a PGP secret key packet with no passphrase */
int
rdpgpsec( BIGNUM *n, BIGNUM *e, BIGNUM *d, uchar *buf, unsigned len )
{
        int err;
        int nbits, nlen, ebits, elen, dbits, dlen;
        unsigned o;

        if ((err = rdpgppub(n, e, &o, buf, len)) < 0)
                return err;
        if (len < o+3)
                return ERR_BADPKT;
        if (buf[o] != 0)                                        /* Check that packet 
is unencrypted */
                return ERR_BADPKT;
        dbits = (buf[o+1] << 8) | buf[o+2];     /* Read private exponent */
        dlen = (dbits + 7)/8;
        if (len < o+3+dlen)
                return ERR_BADPKT;
        BN_bin2bn(buf+o+3, dlen, d);
        return ERR_OK;
}

/* Read the next PGP packet into malloc'd memory */
int
getpgppkt( uchar **pbuf, unsigned *plen, int *type, FILE *f )
{
        int c, c1;
        uchar *buf;
        unsigned len;
        int llen;
        uchar lbuf[4];

        c = fgetc(f);
        if (c == EOF)
                return ERR_EOF;
        if ((c & 0xc0) == 0x80) {
                /* Old PGP packet */
                *type = (c >> 2) & 0xf;
                llen = c & 0x3;
                if (llen++==3)
                        return ERR_BADPKT;
rdllen:
                if (llen==3)
                        llen=4;
                memset (lbuf, 0, 4);
                if (fread(lbuf+4-llen, 1, llen, f) != llen)
                        return ERR_BADPKT;
                len = (lbuf[0]<<24) | (lbuf[1]<<16) | (lbuf[2]<<8) | lbuf[3];
        } else if ((c & 0xc0) == 0xc0) {
                /* New PGP packet */
                *type = c & 0x3f;
                c = fgetc(f);
                if (c == EOF)
                        return ERR_BADPKT;
                if (c == 0xff) {
                        llen = 4;
                        goto rdllen;
                }
                if (c >= 0xe0)
                        return ERR_BADPKT;
                if (c >= 0xc0) {
                        /* Two byte length */
                        c1 = fgetc(f);
                        if (c1 == EOF)
                                return ERR_BADPKT;
                        len = (c<<8) + c1 - 0xc000 + 0xc0;
                } else {
                        /* One byte length */
                        len = c;
                }
        } else {
                /* Non PGP packet */
                return ERR_BADPKT;
        }
        buf = malloc(len);
        if (buf==NULL)
                return ERR_BADPKT;
        if (fread(buf, 1, len, f) != len)
                return ERR_BADPKT;
        *pbuf = buf;
        *plen = len;
        return ERR_OK;
}


/* Read a PGP key ring and create arrays of all the n, e values */
int
rdpgppubring(BIGNUM ***n_arr_ptr, BIGNUM ***e_arr_ptr, int *nkeys_ptr, FILE *f)
{
        int err = ERR_OK;
        uchar *buf;
        unsigned len;
        int type;
        int nkeys = 0;
        BIGNUM **n_arr = NULL;
        BIGNUM **e_arr = NULL;
        BIGNUM *n, *e;

        n_arr = malloc(sizeof(BIGNUM *));
        e_arr = malloc(sizeof(BIGNUM *));

        while (err == ERR_OK)
        {
                err = getpgppkt (&buf, &len, &type, f);
                if (err != ERR_OK)
                        break;
                if (type == 6)                  /* public key packet */
                {
                        n = BN_new();
                        e = BN_new();
                        err = rdpgppub(n, e, NULL, buf, len);
                        if (err != ERR_OK)
                                break;
                        ++nkeys;
                        n_arr = realloc(n_arr, sizeof(BIGNUM *) * nkeys);
                        e_arr = realloc(e_arr, sizeof(BIGNUM *) * nkeys);
                        n_arr[nkeys-1] = n;
                        e_arr[nkeys-1] = e;
                }
                free (buf);
        }
        if (err != ERR_EOF)
                return err;
        err = ERR_OK;

        *n_arr_ptr = n_arr;
        *e_arr_ptr = e_arr;
        *nkeys_ptr = nkeys;

        return err;
}

/* Read a PGP secret key file and find the corresponding value in the
 * array of public key values.  Return the d value and the index in the
 * public key array.
 */
int
rdpgpsecring(BIGNUM *d, int *secindex, BIGNUM **n_arr, BIGNUM **e_arr,
        int nkeys, FILE *f)
{
        int err = ERR_OK;
        BIGNUM *n, *e;
        uchar *buf;
        unsigned len;
        int i;
        int type;

        err = getpgppkt (&buf, &len, &type, f);
        if (err != ERR_OK)
                return err;
        if (type != 5)                                  /* Secret key packet */
                return ERR_BADPKT;
        n = BN_new();
        e = BN_new();
        err = rdpgpsec(n, e, d, buf, len);
        if (err != ERR_OK)
                return err;
        for (i=0; i<nkeys; i++)                 /* Find corresponding public key */
        {
                if (BN_cmp (n, n_arr[i]) == 0  &&  BN_cmp (e, e_arr[i]) == 0)
                        break;
        }
        if (i == nkeys)
                return ERR_SECNOTFOUND;
        *secindex = i;
        return ERR_OK;
}



/************************** UTILITY FUNCTIONS ***************************/


/* Sort the n and e arrays by increasing n */
int
sortkeys (BIGNUM **n, BIGNUM **e, int nkeys)
{
        int i, j;
        BIGNUM *t;

        /* Do a bubble sort as the number of keys is not usually very large */
        for (i=0; i<nkeys-1; i++)
        {
                for (j=i+1; j<nkeys; j++)
                {
                        if (BN_cmp( n[i], n[j] ) > 0)
                        {
                                t = n[i]; n[i] = n[j]; n[j] = t;
                                t = e[i]; e[i] = e[j]; e[j] = t;
                        }
                }
        }
        return ERR_OK;
}


/* Hash the file.  Should have opened it in ASCII mode so that we have
 * standard Unix line endings (newlines only).
 */
int
hashfile( uchar md[5], FILE *f )
{
        char buf[1024];
        SHA_CTX sha;

        SHA_Init(&sha);

        for ( ; ; )
        {
                if (fgets (buf, sizeof(buf), f) == NULL)
                        break;
                SHA_Update(&sha, buf, strlen(buf));
        }
        SHA_Final (md, &sha);
        return ERR_OK;
}


/* Do an RSA enc/dec, where the input/output value may be larger
 * than n.  In fact, val should be much larger than n or this may fail
 * to keep val within the desired range.
 * To decrypt pass d in place of e.
 */
int
rsaencdec( BIGNUM *rslt, BIGNUM *val, BIGNUM *n, BIGNUM *e, BN_CTX *ctx )
{
        BIGNUM *rem = BN_new();
        BIGNUM *newrem = BN_new();

        BN_div (NULL, rem, val, n, ctx);
        BN_mod_exp (newrem, rem, e, n, ctx);
        BN_sub (rslt, val, rem);
        BN_add (rslt, rslt, newrem);
        BN_free (rem);
        BN_free (newrem);
}



/************************** SIG CREATE/VERIFY ***************************/


/* Verify a signature.  sigs holds the per-key signature values,
 * hashval is the hash of the data which was signed, valbytes is the
 * length of the values we work with, several bytes longer than the longest
 * modulus, and n_arr and e_arr are the RSA public key values, of whic
 * there are nkeys of them.  (There are also nkeys of sigs.)
 */
int
checksig( BIGNUM **sigs, uchar *hashval, int hashvalbytes, int valbytes,
        BIGNUM **n_arr, BIGNUM **e_arr, int nkeys, BN_CTX *ctx )
{
        BIGNUM *val = BN_new();
        uchar ivec[CIPHERBLOCK];
        BF_KEY bf;
        uchar *sigbuf;
        uchar *xorbuf;
        int vallen;
        int i, j;

        /* Key cipher with the hash value */
        BF_set_key (&bf, hashvalbytes, hashval);

        /* Init xorbuf to 0's */
        xorbuf = malloc(valbytes);
        memset (xorbuf, 0, valbytes);

        sigbuf = malloc(valbytes);

        for (i=0; i<nkeys; i++)
        {
                rsaencdec (val, sigs[i], n_arr[i], e_arr[i], ctx);
                vallen = BN_num_bytes(val);
                if (vallen > valbytes) {
                        fprintf (stderr, "Bad signature created by signer\n");
                        exit (3);
                }
                /* XOR into buffer */
                memset (sigbuf, 0, valbytes);
                BN_bn2bin (val, sigbuf+valbytes-vallen);
                for (j=0; j<valbytes; j++)
                        xorbuf[j] ^= sigbuf[j];
                memset (ivec, 0, sizeof(ivec));
                BF_cbc_encrypt (xorbuf, xorbuf, valbytes, &bf, ivec, BF_ENCRYPT);
        }
        BN_free (val);

        /* xorbuf should be all 0's for the sig to verify */
        for (j=0; j<valbytes; j++)
                if (xorbuf[j] != 0)
                        break;

        free (xorbuf);
        free (sigbuf);

        if (j < valbytes)
                return ERR_BADSIG;

        return ERR_OK;
}


/* Create a signature.  psigarray is the returned array of bignums,
 * of which there are nkeys.  hashval is the hash of the data being
 * signed.  d is the RSA private key value for the key at position
 * secindex.  valbytes is the size of the values we are working with,
 * several bytes greater than the length of the longest modulus.
 * And n_arr and e_arr are the RSA public key values, of which there
 * are nkeys.
 */
int
createsig( BIGNUM ***psigarray, uchar *hashval, int hashvalbytes, BIGNUM *d,
        int secindex, int valbytes, BIGNUM **n_arr, BIGNUM **e_arr, int nkeys,
        BN_CTX *ctx )
{
        BIGNUM *val = BN_new();
        BIGNUM *bigval = BN_new();
        BIGNUM **sigs;
        BF_KEY bf;
        uchar ivec[CIPHERBLOCK];
        uchar *sigbuf;
        uchar *lxorbuf;
        uchar *rxorbuf;
        int vallen;
        int i, j;

        /* Key cipher with the hash value */
        BF_set_key (&bf, hashvalbytes, hashval);

        BN_lshift (bigval, BN_value_one(), valbytes*8);

        /* Init two xorbufs we will make meet in the middle */
        rxorbuf = malloc(valbytes);
        memset (rxorbuf, 0, valbytes);
        lxorbuf = malloc(valbytes);
        memset (lxorbuf, 0, valbytes);
        memset (ivec, 0, sizeof(ivec));

        /* Start the MITM process on the left xorbuf */
        BF_cbc_encrypt (lxorbuf, lxorbuf, valbytes, &bf, ivec, BF_DECRYPT);

        sigbuf = malloc(valbytes);
        sigs = (BIGNUM **)malloc(nkeys * sizeof(BIGNUM *));

        for (i=0; i<secindex; i++)
        {
                /* For other keys do a fake value */
                sigs[i] = BN_new();
                BN_rand_range (sigs[i], bigval);
                rsaencdec (val, sigs[i], n_arr[i], e_arr[i], ctx);
                /* Infinitisimal chance that vallen > valbytes with random val */
                vallen = BN_num_bytes(val);
                /* XOR into right xor buf and encrypt */
                memset (sigbuf, 0, valbytes);
                BN_bn2bin (val, sigbuf+valbytes-vallen);
                for (j=0; j<valbytes; j++)
                        rxorbuf[j] ^= sigbuf[j];
                memset (ivec, 0, sizeof(ivec));
                BF_cbc_encrypt (rxorbuf, rxorbuf, valbytes, &bf, ivec, BF_ENCRYPT);
        }

        for (i=nkeys-1; i>secindex; i--)
        {
                /* For other keys do a fake value */
                sigs[i] = BN_new();
                BN_rand_range (sigs[i], bigval);
                rsaencdec (val, sigs[i], n_arr[i], e_arr[i], ctx);
                /* Infinitisimal chance that vallen > valbytes with random val */
                vallen = BN_num_bytes(val);
                /* XOR into left xor buf and decrypt */
                memset (sigbuf, 0, valbytes);
                BN_bn2bin (val, sigbuf+valbytes-vallen);
                for (j=0; j<valbytes; j++)
                        lxorbuf[j] ^= sigbuf[j];
                memset (ivec, 0, sizeof(ivec));
                BF_cbc_encrypt (lxorbuf, lxorbuf, valbytes, &bf, ivec, BF_DECRYPT);
        }

        /* XOR the two buffers to get the value we must RSA sign */
        for (j=0; j<valbytes; j++)
                lxorbuf[j] ^= rxorbuf[j];

        /* Get val as the value we need to do the RSA signature to */
        sigs[secindex] = BN_new();
        BN_bin2bn (lxorbuf, valbytes, val);
        rsaencdec (sigs[secindex], val, n_arr[secindex], d, ctx);
        BN_free (val);
        BN_free (bigval);
        free (sigbuf);
        free (lxorbuf);
        free (rxorbuf);
        *psigarray = sigs;
        return ERR_OK;
}



/*************************** USER INTERFACE ****************************/

static char *prog;

void
userr()
{
        fprintf (stderr, "Usage:\n"
                "To sign (signature data to stdout):\n"
                "   %s -s textfile pubkeyfile seckeyfile\n"
                "To verify a signature (signature data from stdin):\n"
                "   %s -v textfile pubkeyfile\n", prog, prog);
        exit (1);
}

int
main (int ac, char **av)
{
        FILE *fpub, *fsec, *fdata;
        BN_CTX *ctx;
        BIGNUM *d;
        BIGNUM **n_arr;
        BIGNUM **e_arr;
        BIGNUM **sigarray;
        uchar md[SHA_DIGEST_LENGTH];
        int secindex;
        int valbytes;
        int nkeys;
        int i;
        int dosign;
        int err;

        ctx = BN_CTX_new();
        d = BN_new();

        prog = av[0];
        if (ac < 2)
                userr();
        if (strcmp( av[1], "-s" ) == 0)
                dosign = 1;
        else if (strcmp( av[1], "-v" ) == 0)
                dosign = 0;
        else
                userr();

        if (ac < (dosign ? 5 : 4) )
                userr();
        fdata = fopen (av[2], "r");     /* text mode */
        if (fdata==NULL)
                userr();
        fpub = fopen (av[3], "rb");
        if (fpub==NULL)
                userr();
        if (dosign)
        {
                fsec = fopen (av[4], "rb");
                if (fsec==NULL)
                        userr();
        }
        err = rdpgppubring(&n_arr, &e_arr, &nkeys, fpub);
        if (err != ERR_OK)
                goto error;
        fclose (fpub);
        sortkeys (n_arr, e_arr, nkeys);
        if (dosign)
        {
                err = rdpgpsecring(d, &secindex, n_arr, e_arr, nkeys, fsec);
                if (err != ERR_OK)
                        goto error;
                fclose (fsec);
        }

        /* For our values we use 2^128 times the largest n; mult of CIPHERBLOCK */
        valbytes = BN_num_bytes (n_arr[nkeys-1]) + 16;
        valbytes = ((valbytes+CIPHERBLOCK-1)/CIPHERBLOCK)*CIPHERBLOCK;

        /* Hash the file to sign/verify */
        err = hashfile (md, fdata);

        if (dosign)
        {
                BIO *bio, *b64;
                uchar *sigbuf;

                err = createsig (&sigarray, md, sizeof(md), d, secindex, valbytes,
                                        n_arr, e_arr, nkeys, ctx);
                if (err != ERR_OK)
                        goto error;

                b64 = BIO_new(BIO_f_base64());
                bio = BIO_new_fp(stdout, BIO_NOCLOSE);
                bio = BIO_push(b64, bio);
                sigbuf = (uchar *)malloc(valbytes);
                for (i=0; i<nkeys; i++)
                {
                        memset (sigbuf, 0, valbytes);
                        BN_bn2bin(sigarray[i], 
sigbuf+valbytes-BN_num_bytes(sigarray[i]));
                        BIO_write(bio, sigbuf, valbytes);
                }
                BIO_flush(bio);
                BIO_free_all(bio);
                free (sigbuf);
        } else {
                /* Read sig data from stdin */
                BIO *bio, *b64;
                uchar *sigbuf;
                int inlen;

                b64 = BIO_new(BIO_f_base64());
                bio = BIO_new_fp(stdin, BIO_NOCLOSE);
                bio = BIO_push(b64, bio);

                sigarray = (BIGNUM **)malloc(nkeys * sizeof(BIGNUM *));
                sigbuf = (uchar *)malloc(valbytes);
                for (i=0; i<nkeys; i++)
                {
                        if ((inlen = BIO_read(bio, sigbuf, valbytes)) < valbytes)
                                userr();
                        sigarray[i] = BN_bin2bn (sigbuf, valbytes, NULL);
                }
                free (sigbuf);
                BIO_free_all(bio);

                err = checksig (sigarray, md, sizeof(md), valbytes, n_arr, e_arr,
                        nkeys, ctx);
                if (err == ERR_OK)
                {
                        printf ("Good signature\n");
                } else if (err = ERR_BADSIG) {
                        printf ("ERROR: Bad signature\n");
                        exit (2);
                } else {
                        goto error;
                }
        }

error:
        if (err != ERR_OK)
        {
                fprintf (stderr, "Error %d\n", err);
                exit (1);
        }
        exit (0);
}

/*
  Signature block!  Who wrote this program?  Someone from the keys below.

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.2

mQCNAisbwocAAAED/jitkUnDwPdZk1Rdr0YNT7h7OHd9zbJbTZEQgdEs5LxQ1h4t
S+fCbgM6zxfMvCWqWPendS3ikEStq1PMGQKtt0b0/4BafB6dO1ljSBp+UWkw86FL
BmCcQkED0CmQOFAEy2p2SURvdO4tExerfUgf+oYQg99v03mvYlVkk3dax7hlAAUR
tBBsb2tpQG9ic2N1cmEuY29ttChMYW5jZSBNLiBDb3R0cmVsbCA8bG9raUBuYXRl
bHkudWNzZC5lZHU+tDhMYW5jZSBNLiBDb3R0cmVsbCAoYXQgaG9tZSkgPGxjb3R0
cmVsbEBwb3BtYWlsLnVjc2QuZWR1PpkAjQMxav4LAAABBADJkZ8ZP83waDvuf/Lx
4UB7KFSkm9IKKht2FpW5ztHG22EmCuarCYhSB+R7dzIAN4Wx9UcdS3x724ozuoNm
bQboiSsSKO41efGcn5zbzFKlLU+Im5utXJ1QtYlbjx6PjnfZiajVAIpgwiekwP7I
PxL6V0i4jYlln3dGUYkxK0j29QAFEbQjSWFuIEdvbGRiZXJnIDxpYW5nQGNzLmJl
cmtlbGV5LmVkdT60IUlhbiBHb2xkYmVyZyA8aWFuQGN5cGhlcnB1bmtzLmNhPrQk
SWFuIEdvbGRiZXJnIDxpYW5AemVyb2tub3dsZWRnZS5jb20+mQCNAi0xHTIAAAEE
AKeIU9S010e1AxYy2R379ptHunqM0kRMgWnOwfCnVets8jThr7B87pzFNVj6kBs8
F9TKQdk62JR5Kiq2rVODFSLmN2JThnhfDu/tAYAz8fJsWkxGn5IhcjxkQpfb2LDs
4EBJgWhI9HxIfCvhSkFdrFe9JBfm0KKB5sGoFIWXVYodAAUTtCFQcjBkdWN0IEN5
cGhlciA8YWx0LnNlY3VyaXR5LnBncD6ZAI0CL7SNAQAAAQQAruhfQV42dxod9rW/
5XtIxS+ICbyoHyitYbTO+Nrhm1KsdWD88zCmlSHji3kRED2WW1EF0e7fT5hKHxrV
1i3Vc4PzeeSfOP2uG2kUA+rLLCUtWE1Vjc9UvIxtQvDbtoQAZz5K0WqsOhRDT6P1
BT9gf8jJU32sFonKGwgMRScZrzUABRG0KEJlbiBMYXVyaWUgPGJlbkBnb256by5i
ZW4uYWxncm91cC5jby51az60HEJlbiBMYXVyaWUgPGJlbkBjcnlwdGl4Lm9yZz60
HkJlbiBMYXVyaWUgPGJlbkBhbGdyb3VwLmNvLnVrPpkAjQIqrDZMAAABBADCljOd
puRFotKHCuLtXAtjz8h0+rWr5PTwt0weVwWA3oH93bJXUaZ4yY9a/mjtPBRTvkCx
CPcLQar39Tzz+Yi1+7A9riFZSR9eDD7clbY5vWSm/CTLQlu+NOOQYLRwQvckN1e7
1zVeYzOnRNqHJx+ACP6QRaxiyTyoEwOvWCFMNwAFEbQmSGFsIEZpbm5leSA8NzQw
NzYuMTA0MUBjb21wdXNlcnZlLmNvbT6ZAI0DMxu7SwAAAQQApJs0Xcl4sIUngK32
4f1sQ9H7GGctVkjxynj5b3or0rhiI2u/OowQCj7VwnCdoM/Itqz6HUiVRO8D+eHz
XQRpAXKoeEgxzMN45iNvgneU0/VsN49bCDCM7JPHau2cMm4xWhQUA6s59CxhR+Y2
cMWxLpwcXDJ//+YoNZtIfcgAK9EABRG0HkVyaWMgWW91bmcgPGVheUBjcnlwdHNv
ZnQuY29tPpkAjQIty/OuAAABBACkXvI/UFKi+Dw0ErJYkykNMk5HSy/ARQZu3NN0
QvTpeTz/So/0bZ7HcRTE7Vu8JDME6WNYxdtx0fseeC6zqYvIoOhxJol1VVrjQckY
0jIM/I765zDNP7SDgjwIDTMYgDVFqq3rTxFgmRPbC28pZCa6zneeGSslwU8Pw+wC
+7uKsQAFEbQhQ29saW4gUGx1bWIgPGNvbGluQG55eC5jcy5kdS5lZHU+
=/CJG
-----END PGP PUBLIC KEY BLOCK-----

  ++multisig v1.0
pEsBwalpBRxWyJR8tkYm6qR27UW9IT6Vg8SlOHIsEkk04RJvoSy0cy4ISFCq6vDX
5ub6c+MYi/UoyR6tI7oqpMu1abcXWm2DkfDiCsD6jQddVkiiYdG7Bih8JWdWmp5l
AgzqUoz14671/ezmWSrPNsTNKV96+ZLEanZsqfkpQcnZpLkWVpJzQFe0VgDQ64b2
+e2efrbknLFq0FTdX7Sh3qzAfzNYYgADmeOxDoTm9sb6T0fULf1P7mjiN2LZXuEW
m/8QvksaQi9KGa/0xN2m0heNtS1cfsTa+NJz8XYyG/tnMy7+mvI3c3lrnz+6Dpyp
pbNwaX+12VcqtfNec9faoq8RJgFxmSO/ZfMOGM8cFBQ75ZOaoBJP5ObHZ/63FFh5
Wh5GzwJjQs0vLwpM3iF6G+IixEqAQYisUdCopP1wXCLgltDM6l7jRlXxNDj0AXQ1
eQJolo32vemcy8Z8GAn5tpQHmJwpdzZpboWRQY53pD4mVnEMN4GBC1mhbbI2z+Oh
lPglqmmy3p4D+psNU1rlNv6yH/L0PgcuW7taVpbopjl4HLuJdWcKHJlXish3D/jb
eoQ856fYFZ/omGiO9x1D0BsnGFLZVWob4OIZRzO/Pc49VIhFy5NsV2zuozStId89
[...]
 */

Reply via email to