1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package libkb
5
6import (
7	"fmt"
8
9	keybase1 "github.com/keybase/client/go/protocol/keybase1"
10)
11
12type NaclKeyPair interface {
13	GenericKey
14}
15
16type NaclGenerator func() (NaclKeyPair, error)
17
18type NaclKeyGenArg struct {
19	Signer         GenericKey // who is going to sign us into the Chain
20	ExpiresIn      int
21	Generator      NaclGenerator
22	Me             *User
23	DelegationType DelegationType
24	ExpireIn       int          // how long it lasts
25	EldestKeyID    keybase1.KID // the eldest KID for this epoch
26	Device         *Device
27	RevSig         string // optional reverse sig.  set to nil for autogenerate.
28}
29
30type NaclKeyGen struct {
31	arg  *NaclKeyGenArg
32	pair NaclKeyPair
33}
34
35func NewNaclKeyGen(arg NaclKeyGenArg) *NaclKeyGen {
36	return &NaclKeyGen{arg: &arg}
37}
38
39func (g *NaclKeyGen) Generate() (err error) {
40	g.pair, err = g.arg.Generator()
41	return
42}
43
44func (g *NaclKeyGen) SaveLKS(m MetaContext, lks *LKSec) error {
45	_, err := WriteLksSKBToKeyring(m, g.pair, lks)
46	return err
47}
48
49func (g *NaclKeyGen) Push(m MetaContext, aggregated bool) (d Delegator, err error) {
50	if g.pair == nil {
51		return Delegator{}, fmt.Errorf("cannot Push delegator before Generate")
52	}
53	d = Delegator{
54		NewKey:         g.pair,
55		RevSig:         g.arg.RevSig,
56		Device:         g.arg.Device,
57		Expire:         g.arg.ExpireIn,
58		DelegationType: g.arg.DelegationType,
59		ExistingKey:    g.arg.Signer,
60		Me:             g.arg.Me,
61		EldestKID:      g.arg.EldestKeyID,
62	}
63
64	if aggregated {
65		return
66	}
67
68	err = d.Run(m)
69	return
70}
71
72func (g *NaclKeyGen) GetKeyPair() NaclKeyPair {
73	return g.pair
74}
75
76func (g *NaclKeyGen) UpdateArg(signer GenericKey, eldestKID keybase1.KID, delegationType DelegationType, user *User) {
77	g.arg.Signer = signer
78	g.arg.EldestKeyID = eldestKID
79	g.arg.DelegationType = delegationType
80	// if a user is passed in, then update the user pointer
81	// this is necessary if the sigchain changed between generation and push.
82	if user != nil {
83		g.arg.Me = user
84	}
85}
86