Пример #1
0
         ensure_recipient_specified(opts)
         pitchfork.init()
         params = pitchfork.start_ecdh(opts.recipient[0])
     else:
         params = dh1_handler()
     if params:
         print "[pbp] secret exponent", b85encode(params[0])
         print "[pbp] public component", b85encode(params[1])
         clearmem(params[0])
 # receive ECDH
 elif opts.action=='d2':
     ensure_dhparam_specified(opts)
     if PITCHFORK and opts.PITCHFORK:
         ensure_recipient_specified(opts)
         pitchfork.init()
         params = pitchfork.resp_ecdh(opts.dh_param, opts.recipient[0])
     else:
         params = dh2_handler(binascii.unhexlify(opts.dh_param))
     if params:
         print "[pbp] shared secret", b85encode(params[1])
         print "[pbp] public component", b85encode(params[0])
         clearmem(params[0])
         clearmem(params[1])
 # finish ECDH
 elif opts.action=='d3':
     ensure_dhparam_specified(opts)
     ensure_dhexp_specified(opts)
     if PITCHFORK and opts.PITCHFORK:
         pitchfork.init()
         sec = pitchfork.end_ecdh(opts.dh_param, opts.dh_exp)
     else:
Пример #2
0
         ensure_recipient_specified(opts)
         pitchfork.init()
         params = pitchfork.start_ecdh(opts.recipient[0])
     else:
         params = dh1_handler()
     if params:
         print "secret exponent", b85encode(params[0])
         print "public component", b85encode(params[1])
         clearmem(params[0])
 # receive ECDH
 elif opts.action=='d2':
     ensure_dhparam_specified(opts)
     if PITCHFORK:
         ensure_recipient_specified(opts)
         pitchfork.init()
         params = pitchfork.resp_ecdh(opts.dh_param, opts.recipient[0])
     else:
         params = dh2_handler(binascii.unhexlify(opts.dh_param))
     if params:
         print "shared secret", b85encode(params[1])
         print "public component", b85encode(params[0])
         clearmem(params[0])
         clearmem(params[1])
 # finish ECDH
 elif opts.action=='d3':
     ensure_dhparam_specified(opts)
     ensure_dhexp_specified(opts)
     if PITCHFORK:
         pitchfork.init()
         sec = pitchfork.end_ecdh(opts.dh_param, opts.dh_exp)
     else:
Пример #3
0
Файл: main.py Проект: stef/pbp
def main():
    # main command line handler for pbp
    parser = argparse.ArgumentParser(description='pbp')
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--gen-key',
                       '-g',
                       dest='action',
                       action='store_const',
                       const='g',
                       help="generates a new key")
    group.add_argument('--encrypt',
                       '-c',
                       dest='action',
                       action='store_const',
                       const='c',
                       help="encrypts")
    group.add_argument('--decrypt',
                       '-d',
                       dest='action',
                       action='store_const',
                       const='d',
                       help="decrypts")
    group.add_argument('--sign',
                       '-s',
                       dest='action',
                       action='store_const',
                       const='s',
                       help="signs")
    group.add_argument('--master-sign',
                       '-m',
                       dest='action',
                       action='store_const',
                       const='m',
                       help="signs keys with your masterkey")
    group.add_argument('--verify',
                       '-v',
                       dest='action',
                       action='store_const',
                       const='v',
                       help="verifies")
    group.add_argument('--hash',
                       '-H',
                       dest='action',
                       action='store_const',
                       const='h',
                       help="hashes")
    group.add_argument('--list',
                       '-l',
                       dest='action',
                       action='store_const',
                       const='l',
                       help="lists public keys")
    group.add_argument('--list-secret',
                       '-L',
                       dest='action',
                       action='store_const',
                       const='L',
                       help="Lists secret keys")
    group.add_argument('--export-key',
                       '-x',
                       dest='action',
                       action='store_const',
                       const='x',
                       help="export public key")
    group.add_argument('--import-key',
                       '-I',
                       dest='action',
                       action='store_const',
                       const='i',
                       help="import public key")
    group.add_argument('--check-sigs',
                       '-C',
                       dest='action',
                       action='store_const',
                       const='C',
                       help="lists all known sigs on a public key")
    group.add_argument('--fcrypt',
                       '-e',
                       dest='action',
                       action='store_const',
                       const='e',
                       help="encrypts a message using PFS to a peer")
    group.add_argument('--fdecrypt',
                       '-E',
                       dest='action',
                       action='store_const',
                       const='E',
                       help="decrypts a message using PFS to a peer")
    group.add_argument('-D1',
                       dest='action',
                       action='store_const',
                       const='d1',
                       help="initiates an ECDH key exchange")
    group.add_argument('-D2',
                       dest='action',
                       action='store_const',
                       const='d2',
                       help="responds to an ECDH key request")
    group.add_argument('-D3',
                       dest='action',
                       action='store_const',
                       const='d3',
                       help="finalizes an ECDH key exchange")
    group.add_argument('--dh-start',
                       '-Ds',
                       dest='action',
                       action='store_const',
                       const='ds',
                       help="initiates an ECDH key exchange")
    group.add_argument('--dh-end',
                       '-De',
                       dest='action',
                       action='store_const',
                       const='de',
                       help="finalizes an ECDH key exchange")
    group.add_argument('--rand-stream',
                       '-R',
                       dest='action',
                       action='store_const',
                       const='R',
                       help="generate arbitrary random stream")

    if PITCHFORK:
        parser.add_argument('--pitchfork',
                            '-P',
                            dest='PITCHFORK',
                            action='store_const',
                            const='P',
                            help="arms PITCHFORK",
                            default=False)
    parser.add_argument('--signature',
                        '-z',
                        help="sets the pitchfork sig to verify")
    parser.add_argument(
        '--recipient',
        '-r',
        action='append',
        help="designates a recipient for public key encryption")
    parser.add_argument('--name', '-n', help="sets the name for a new key")
    parser.add_argument(
        '--max-recipients',
        help="set the number of recipients to check when decrypting",
        default=20)
    parser.add_argument('--sender', help="set the key of the sender")
    parser.add_argument(
        '--basedir',
        '-b',
        '--base-dir',
        help="set the base directory for all key storage needs",
        default=defaultbase)
    parser.add_argument('--self', '-S', help="sets your own key")
    parser.add_argument('--key', '-k', help="some password or secret")
    parser.add_argument('--dh-param',
                        '-DP',
                        help="public parameter for ECDH key exchange")
    parser.add_argument(
        '--dh-exp',
        '-DE',
        help="secret exp for final step of a ECDH key exchange")
    parser.add_argument('--size',
                        '-Rs',
                        help="size of random stream to generate")
    parser.add_argument(
        '--dh-peers',
        '-Dp',
        help="the number of peers participating in a ECDH key exchange")
    parser.add_argument('--infile', '-i', help="file to operate on")
    parser.add_argument('--armor',
                        '-a',
                        action='store_true',
                        help="ascii armors the output")
    parser.add_argument('--outfile', '-o', help="file to output to")
    opts = parser.parse_args()

    opts.basedir = os.path.expandvars(os.path.expanduser(opts.basedir))

    if os.path.exists(opts.basedir):
        mode = os.stat(opts.basedir).st_mode & 0o777
        if mode not in [0o700, 0o600]:
            print('[pbp] ABORT: unsafe permissions %s on basedir %s' %
                  (oct(mode), opts.basedir),
                  file=sys.stderr)

    # Generate key
    if opts.action == 'g':
        ensure_name_specified(opts)
        publickey.Identity(opts.name, create=True, basedir=opts.basedir)

    # list public keys
    elif opts.action == 'l':
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            res = pitchfork.listkeys(opts.name)
            if (res):
                keys, stats = res
                pitchfork.print_keys(keys)
                pitchfork.storage_stats(stats, keys)
            else:
                print('none')
        else:
            for i in publickey.get_public_keys(opts.basedir):
                print(('valid' if i.valid > datetime.datetime.utcnow() >
                       i.created else 'INVALID'), i.keyid(), i.name)

    # list secret keys
    elif opts.action == 'L':
        for i in publickey.get_secret_keys(opts.basedir):
            print(('valid' if i.valid > datetime.datetime.utcnow() > i.created
                   else 'INVALID'), i.keyid(), i.name)

    # encrypt
    elif opts.action == 'c':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res = pitchfork.encrypt(opts.recipient[0],
                                    infile=opts.infile,
                                    outfile=opts.outfile)
            if res:
                print(b85encode(res), file=sys.stderr)
            return
        if opts.recipient or opts.self:
            ensure_self_specified(opts)
            ensure_recipient_specified(opts)
        encrypt_handler(infile=opts.infile,
                        outfile=opts.outfile,
                        recipient=opts.recipient,
                        self=opts.self,
                        basedir=opts.basedir)

    # decrypt
    elif opts.action == 'd':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res = pitchfork.decrypt(opts.recipient[0],
                                    infile=opts.infile,
                                    outfile=opts.outfile)
        else:
            try:
                sender = decrypt_handler(infile=opts.infile,
                                         outfile=opts.outfile,
                                         self=opts.self,
                                         max_recipients=int(
                                             opts.max_recipients),
                                         peer=opts.sender,
                                         basedir=opts.basedir)
            except ValueError as e:
                print(e)
                sys.exit(1)
            else:
                if sender:
                    print('[pbp] good message from', sender, file=sys.stderr)

    # sign
    elif opts.action == 's':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res = pitchfork.sign(opts.recipient[0],
                                 infile=opts.infile,
                                 outfile=opts.outfile)
            if res:
                print(b85encode(res[0]), b85encode(res[1]), file=sys.stderr)
            return
        ensure_self_specified(opts)
        sign_handler(infile=opts.infile,
                     outfile=opts.outfile,
                     self=opts.self,
                     armor=opts.armor,
                     basedir=opts.basedir)

    # verify
    elif opts.action == 'v':
        if PITCHFORK and opts.PITCHFORK:
            ensure_signature_specified(opts)
            ensure_recipient_specified(opts)
            pitchfork.init()
            res = pitchfork.verify(opts.signature,
                                   opts.recipient[0],
                                   infile=opts.infile,
                                   outfile=opts.outfile)
        else:
            res = verify_handler(infile=opts.infile,
                                 outfile=opts.outfile,
                                 basedir=opts.basedir)
        if res:
            print("[pbp] good message from", res, file=sys.stderr)
        else:
            print('[pbp] VERIFICATION FAILED', file=sys.stderr)

    # key sign
    elif opts.action == 'm':
        ensure_name_specified(opts)
        ensure_self_specified(opts)
        sig = keysign_handler(name=opts.name,
                              self=opts.self,
                              basedir=opts.basedir)
        if sig: print("[pbp] key signed in", sig)
        else: print('[pbp] SIGNATURE FAILED', file=sys.stderr)

    # lists signatures owners on public keys
    elif opts.action == 'C':
        ensure_name_specified(opts)
        sigs = keycheck_handler(name=opts.name, basedir=opts.basedir)
        if sigs:
            print('[pbp] good signatures on',
                  opts.name,
                  'from',
                  ', '.join(sigs),
                  file=sys.stderr)
        else:
            print('[pbp] NO GOOD SIGS FOUND', file=sys.stderr)

    # export public key
    elif opts.action == 'x':
        ensure_self_specified(opts)
        k = export_handler(opts.self, basedir=opts.basedir)
        print(k)
    # import public key
    elif opts.action == 'i':
        n = import_handler(infile=opts.infile, basedir=opts.basedir)
        if n:
            print('[pbp] Success: imported public keys for', n)
        else:
            print('[pbp] IMPORT FAILED')

    # forward encrypt
    elif opts.action == 'e':
        ensure_recipient_specified(opts)
        ensure_only_one_recipient(opts)
        # TODO could try to find out this automatically if non-ambiguous
        ensure_self_specified(opts)
        chaining_encrypt_handler(opts.infile,
                                 outfile=opts.outfile,
                                 recipient=opts.recipient[0],
                                 self=opts.self,
                                 basedir=opts.basedir)

    # forward decrypt
    elif opts.action == 'E':
        ensure_recipient_specified(opts)
        ensure_only_one_recipient(opts)
        # TODO could try to find out this automatically if non-ambiguous
        ensure_self_specified(opts)
        chaining_decrypt_handler(opts.infile,
                                 outfile=opts.outfile,
                                 recipient=opts.recipient[0],
                                 self=opts.self,
                                 basedir=opts.basedir)
    # start ECDH
    elif opts.action == 'd1':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            params = pitchfork.start_ecdh(opts.recipient[0])
        else:
            params = dh1_handler()
        if params:
            print("[pbp] secret exponent", b85encode(params[0]))
            print("[pbp] public component", b85encode(params[1]))
            clearmem(params[0])
    # receive ECDH
    elif opts.action == 'd2':
        ensure_dhparam_specified(opts)
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            params = pitchfork.resp_ecdh(opts.dh_param, opts.recipient[0])
        else:
            params = dh2_handler(binascii.unhexlify(opts.dh_param))
        if params:
            print("[pbp] shared secret", b85encode(params[1]))
            print("[pbp] public component", b85encode(params[0]))
            clearmem(params[0])
            clearmem(params[1])
    # finish ECDH
    elif opts.action == 'd3':
        ensure_dhparam_specified(opts)
        ensure_dhexp_specified(opts)
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            sec = pitchfork.end_ecdh(opts.dh_param, opts.dh_exp)
        else:
            sec = dh3_handler(binascii.unhexlify(opts.dh_param),
                              binascii.unhexlify(opts.dh_exp))
        if sec:
            print("[pbp] shared secret", b85encode(sec))
            clearmem(sec)
    # start MPECDH
    elif opts.action == 'ds':
        ensure_self_specified(opts)
        ensure_dhpeers_specified(opts)
        ensure_name_specified(opts)
        sec = mpecdh_start_handler(opts.name, opts.dh_peers, opts.self,
                                   opts.infile, opts.outfile, opts.basedir)
        if sec:
            print("[pbp] pushed shared secret, hash",
                  b85encode(nacl.crypto_generichash(sec, outlen=6)),
                  file=sys.stderr)
            clearmem(sec)
            sec = None

    # finish MPECDH
    elif opts.action == 'de':
        ensure_self_specified(opts)
        ensure_name_specified(opts)
        sec = mpecdh_end_handler(opts.name, opts.self, opts.infile,
                                 opts.outfile, opts.basedir)
        if sec:
            print("[pbp] pushed shared secret, hash",
                  b85encode(nacl.crypto_generichash(sec, outlen=6)),
                  file=sys.stderr)
            clearmem(sec)
            sec = None

    elif opts.action == 'R':
        ensure_size_good(opts)
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            pitchfork.rng(int(opts.size), opts.outfile)
        else:
            random_stream_handler(opts.outfile, opts.size)

    elif opts.action == 'h':
        hsum = hash_handler(opts.infile,
                            k=load_key(opts.key),
                            outlen=int(opts.size or '16'))
        if hsum:
            print(' '.join(split_by_n(binascii.hexlify(hsum), 4)))
Пример #4
0
Файл: main.py Проект: stef/pbp
def main():
    # main command line handler for pbp
    parser = argparse.ArgumentParser(description='pbp')
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--gen-key',     '-g',  dest='action', action='store_const', const='g', help="generates a new key")
    group.add_argument('--encrypt',     '-c',  dest='action', action='store_const', const='c',help="encrypts")
    group.add_argument('--decrypt',     '-d',  dest='action', action='store_const', const='d',help="decrypts")
    group.add_argument('--sign',        '-s',  dest='action', action='store_const', const='s',help="signs")
    group.add_argument('--master-sign', '-m',  dest='action', action='store_const', const='m',help="signs keys with your masterkey")
    group.add_argument('--verify',      '-v',  dest='action', action='store_const', const='v',help="verifies")
    group.add_argument('--hash',        '-H',  dest='action', action='store_const', const='h',help="hashes")
    group.add_argument('--list',        '-l',  dest='action', action='store_const', const='l',help="lists public keys")
    group.add_argument('--list-secret', '-L',  dest='action', action='store_const', const='L',help="Lists secret keys")
    group.add_argument('--export-key',  '-x',  dest='action', action='store_const', const='x',help="export public key")
    group.add_argument('--import-key',  '-I',  dest='action', action='store_const', const='i',help="import public key")
    group.add_argument('--check-sigs',  '-C',  dest='action', action='store_const', const='C',help="lists all known sigs on a public key")
    group.add_argument('--fcrypt',      '-e',  dest='action', action='store_const', const='e',help="encrypts a message using PFS to a peer")
    group.add_argument('--fdecrypt',    '-E',  dest='action', action='store_const', const='E',help="decrypts a message using PFS to a peer")
    group.add_argument(                 '-D1', dest='action', action='store_const', const='d1',help="initiates an ECDH key exchange")
    group.add_argument(                 '-D2', dest='action', action='store_const', const='d2',help="responds to an ECDH key request")
    group.add_argument(                 '-D3', dest='action', action='store_const', const='d3',help="finalizes an ECDH key exchange")
    group.add_argument('--dh-start',    '-Ds', dest='action', action='store_const', const='ds',help="initiates an ECDH key exchange")
    group.add_argument('--dh-end',      '-De', dest='action', action='store_const', const='de',help="finalizes an ECDH key exchange")
    group.add_argument('--rand-stream', '-R',  dest='action', action='store_const', const='R',help="generate arbitrary random stream")

    if PITCHFORK: parser.add_argument('--pitchfork',  '-P',  dest='PITCHFORK', action='store_const', const='P',help="arms PITCHFORK", default=False)
    parser.add_argument('--signature',  '-z', help="sets the pitchfork sig to verify")
    parser.add_argument('--recipient',  '-r', action='append', help="designates a recipient for public key encryption")
    parser.add_argument('--name',       '-n', help="sets the name for a new key")
    parser.add_argument('--max-recipients',   help="set the number of recipients to check when decrypting", default=20)
    parser.add_argument('--sender',           help="set the key of the sender")
    parser.add_argument('--basedir',    '-b', '--base-dir', help="set the base directory for all key storage needs", default=defaultbase)
    parser.add_argument('--self',       '-S', help="sets your own key")
    parser.add_argument('--key',        '-k', help="some password or secret")
    parser.add_argument('--dh-param',   '-DP',help="public parameter for ECDH key exchange")
    parser.add_argument('--dh-exp',     '-DE',help="secret exp for final step of a ECDH key exchange")
    parser.add_argument('--size',       '-Rs',help="size of random stream to generate")
    parser.add_argument('--dh-peers',   '-Dp',help="the number of peers participating in a ECDH key exchange")
    parser.add_argument('--infile',     '-i', help="file to operate on")
    parser.add_argument('--armor',      '-a', action='store_true', help="ascii armors the output")
    parser.add_argument('--outfile',    '-o', help="file to output to")
    opts=parser.parse_args()

    opts.basedir=os.path.expandvars( os.path.expanduser(opts.basedir))

    if os.path.exists(opts.basedir):
        mode = os.stat(opts.basedir).st_mode & 0o777
        if mode not in [0o700, 0o600]:
            print('[pbp] ABORT: unsafe permissions %s on basedir %s' % (oct(mode), opts.basedir), file=sys.stderr)

    # Generate key
    if opts.action=='g':
        ensure_name_specified(opts)
        publickey.Identity(opts.name, create=True, basedir=opts.basedir)

    # list public keys
    elif opts.action=='l':
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            res = pitchfork.listkeys(opts.name)
            if(res):
                keys, stats = res
                pitchfork.print_keys(keys)
                pitchfork.storage_stats(stats, keys)
            else:
                print('none')
        else:
            for i in publickey.get_public_keys(opts.basedir):
                print(('valid' if i.valid > datetime.datetime.utcnow() > i.created
                       else 'INVALID'), i.keyid(), i.name)

    # list secret keys
    elif opts.action=='L':
        for i in publickey.get_secret_keys(opts.basedir):
            print(('valid' if i.valid > datetime.datetime.utcnow() > i.created
                   else 'INVALID'), i.keyid(), i.name)

    # encrypt
    elif opts.action=='c':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res=pitchfork.encrypt(opts.recipient[0],
                                   infile=opts.infile,
                                   outfile=opts.outfile)
            if res:
                print(b85encode(res), file=sys.stderr)
            return
        if opts.recipient or opts.self:
            ensure_self_specified(opts)
            ensure_recipient_specified(opts)
        encrypt_handler(infile=opts.infile,
                        outfile=opts.outfile,
                        recipient=opts.recipient,
                        self=opts.self,
                        basedir=opts.basedir)

    # decrypt
    elif opts.action=='d':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res=pitchfork.decrypt(opts.recipient[0],
                                  infile=opts.infile,
                                  outfile=opts.outfile)
        else:
            try:
                sender = decrypt_handler(infile=opts.infile,
                                         outfile=opts.outfile,
                                         self=opts.self,
                                         max_recipients=int(opts.max_recipients),
                                         peer=opts.sender,
                                         basedir=opts.basedir)
            except ValueError as e:
                print(e)
                sys.exit(1)
            else:
                if sender:
                    print('[pbp] good message from', sender, file=sys.stderr)

    # sign
    elif opts.action=='s':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            res=pitchfork.sign(opts.recipient[0],
                               infile=opts.infile,
                               outfile=opts.outfile)
            if res:
                print(b85encode(res[0]), b85encode(res[1]), file=sys.stderr)
            return
        ensure_self_specified(opts)
        sign_handler(infile=opts.infile,
                     outfile=opts.outfile,
                     self=opts.self,
                     armor=opts.armor,
                     basedir=opts.basedir)

    # verify
    elif opts.action=='v':
        if PITCHFORK and opts.PITCHFORK:
            ensure_signature_specified(opts)
            ensure_recipient_specified(opts)
            pitchfork.init()
            res=pitchfork.verify(opts.signature,
                                 opts.recipient[0],
                                 infile=opts.infile,
                                 outfile=opts.outfile)
        else:
            res = verify_handler(infile=opts.infile,
                                 outfile=opts.outfile,
                                 basedir=opts.basedir)
        if res:
            print("[pbp] good message from", res, file=sys.stderr)
        else:
            print('[pbp] VERIFICATION FAILED', file=sys.stderr)

    # key sign
    elif opts.action=='m':
        ensure_name_specified(opts)
        ensure_self_specified(opts)
        sig = keysign_handler(name=opts.name,
                              self=opts.self,
                              basedir=opts.basedir)
        if sig: print("[pbp] key signed in", sig)
        else: print('[pbp] SIGNATURE FAILED', file=sys.stderr)

    # lists signatures owners on public keys
    elif opts.action=='C':
        ensure_name_specified(opts)
        sigs = keycheck_handler(name=opts.name,
                         basedir=opts.basedir)
        if sigs:
            print('[pbp] good signatures on', opts.name, 'from', ', '.join(sigs), file=sys.stderr)
        else: print('[pbp] NO GOOD SIGS FOUND', file=sys.stderr)

    # export public key
    elif opts.action=='x':
        ensure_self_specified(opts)
        k = export_handler(opts.self,
                           basedir=opts.basedir)
        print(k)
    # import public key
    elif opts.action=='i':
        n = import_handler(infile=opts.infile,
                           basedir=opts.basedir)
        if n:
            print('[pbp] Success: imported public keys for', n)
        else:
            print('[pbp] IMPORT FAILED')

    # forward encrypt
    elif opts.action=='e':
        ensure_recipient_specified(opts)
        ensure_only_one_recipient(opts)
        # TODO could try to find out this automatically if non-ambiguous
        ensure_self_specified(opts)
        chaining_encrypt_handler(opts.infile,
                        outfile=opts.outfile,
                        recipient=opts.recipient[0],
                        self=opts.self,
                        basedir=opts.basedir)

    # forward decrypt
    elif opts.action=='E':
        ensure_recipient_specified(opts)
        ensure_only_one_recipient(opts)
        # TODO could try to find out this automatically if non-ambiguous
        ensure_self_specified(opts)
        chaining_decrypt_handler(opts.infile,
                            outfile=opts.outfile,
                            recipient=opts.recipient[0],
                            self=opts.self,
                            basedir=opts.basedir)
    # start ECDH
    elif opts.action=='d1':
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            params = pitchfork.start_ecdh(opts.recipient[0])
        else:
            params = dh1_handler()
        if params:
            print("[pbp] secret exponent", b85encode(params[0]))
            print("[pbp] public component", b85encode(params[1]))
            clearmem(params[0])
    # receive ECDH
    elif opts.action=='d2':
        ensure_dhparam_specified(opts)
        if PITCHFORK and opts.PITCHFORK:
            ensure_recipient_specified(opts)
            pitchfork.init()
            params = pitchfork.resp_ecdh(opts.dh_param, opts.recipient[0])
        else:
            params = dh2_handler(binascii.unhexlify(opts.dh_param))
        if params:
            print("[pbp] shared secret", b85encode(params[1]))
            print("[pbp] public component", b85encode(params[0]))
            clearmem(params[0])
            clearmem(params[1])
    # finish ECDH
    elif opts.action=='d3':
        ensure_dhparam_specified(opts)
        ensure_dhexp_specified(opts)
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            sec = pitchfork.end_ecdh(opts.dh_param, opts.dh_exp)
        else:
            sec = dh3_handler(binascii.unhexlify(opts.dh_param), binascii.unhexlify(opts.dh_exp))
        if sec:
            print("[pbp] shared secret", b85encode(sec))
            clearmem(sec)
    # start MPECDH
    elif opts.action=='ds':
        ensure_self_specified(opts)
        ensure_dhpeers_specified(opts)
        ensure_name_specified(opts)
        sec = mpecdh_start_handler(opts.name, opts.dh_peers, opts.self, opts.infile, opts.outfile, opts.basedir)
        if sec:
            print("[pbp] pushed shared secret, hash", b85encode(nacl.crypto_generichash(sec, outlen=6)), file=sys.stderr)
            clearmem(sec)
            sec = None

    # finish MPECDH
    elif opts.action=='de':
        ensure_self_specified(opts)
        ensure_name_specified(opts)
        sec = mpecdh_end_handler(opts.name, opts.self, opts.infile, opts.outfile, opts.basedir)
        if sec:
            print("[pbp] pushed shared secret, hash", b85encode(nacl.crypto_generichash(sec, outlen=6)), file=sys.stderr)
            clearmem(sec)
            sec = None

    elif opts.action=='R':
        ensure_size_good(opts)
        if PITCHFORK and opts.PITCHFORK:
            pitchfork.init()
            pitchfork.rng(int(opts.size), opts.outfile)
        else:
            random_stream_handler(opts.outfile, opts.size)

    elif opts.action=='h':
        hsum = hash_handler(opts.infile, k=load_key(opts.key), outlen=int(opts.size or '16'))
        if hsum:
            print(' '.join(split_by_n(binascii.hexlify(hsum),4)))