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	"crypto/sha256"
8	"errors"
9
10	"github.com/keybase/client/go/kbcrypto"
11	keybase1 "github.com/keybase/client/go/protocol/keybase1"
12	"golang.org/x/net/context"
13)
14
15// GPGKey is a shell around gpg cli commands that implements the
16// GenericKey interface.
17type GPGKey struct {
18	fp  *PGPFingerprint
19	kid keybase1.KID
20	ui  GPGUI
21	ct  keybase1.ClientType
22	Contextified
23}
24
25// GPGKey implements the GenericKey interface.
26var _ GenericKey = (*GPGKey)(nil)
27
28func NewGPGKey(g *GlobalContext, fp *PGPFingerprint, kid keybase1.KID, ui GPGUI, ct keybase1.ClientType) *GPGKey {
29	return &GPGKey{Contextified: NewContextified(g), fp: fp, kid: kid, ui: ui, ct: ct}
30}
31
32func (g *GPGKey) GetKID() keybase1.KID {
33	return g.kid
34}
35
36func (g *GPGKey) GetBinaryKID() keybase1.BinaryKID {
37	return g.GetKID().ToBinaryKID()
38}
39
40func (g *GPGKey) GetFingerprintP() *PGPFingerprint {
41	return g.fp
42}
43
44func (g *GPGKey) GetAlgoType() kbcrypto.AlgoType {
45	return kbcrypto.KIDPGPBase
46}
47
48func (g *GPGKey) SignToString(msg []byte) (sig string, id keybase1.SigIDBase, err error) {
49	return g.SignToStringMctx(NewMetaContext(context.TODO(), g.G()), msg)
50}
51
52func (g *GPGKey) SignToStringMctx(mctx MetaContext, msg []byte) (sig string, id keybase1.SigIDBase, err error) {
53	mctx.Debug("+ GPGKey Signing %s", string(msg))
54	defer func() {
55		mctx.Debug("- GPGKey Signing -> %s", err)
56	}()
57
58	if g.ct == keybase1.ClientType_CLI {
59		mctx.Debug("| GPGKey reverse delegate to CLI")
60		sig, err = g.ui.Sign(mctx.Ctx(), keybase1.SignArg{Fingerprint: (*g.fp)[:], Msg: msg})
61	} else {
62		mctx.Debug("| GPGKey sign in-process; let's hope for the best!")
63		sig, err = g.G().GetGpgClient().Sign(mctx, *g.fp, msg)
64	}
65
66	if err != nil {
67		return sig, id, err
68	}
69
70	// compute sig id:
71	h := sha256.New()
72	_, err = h.Write(msg)
73	if err != nil {
74		return sig, id, err
75	}
76	var hsh [32]byte
77	var tmp = h.Sum(nil)
78	copy(hsh[:], tmp)
79	id = keybase1.SigIDBaseFromBytes(hsh)
80	return sig, id, nil
81}
82
83func (g *GPGKey) VerifyStringAndExtract(ctx VerifyContext, sig string) (msg []byte, id keybase1.SigIDBase, err error) {
84	return msg, id, errors.New("VerifyStringAndExtract not implemented")
85}
86
87func (g *GPGKey) VerifyString(ctx VerifyContext, sig string, msg []byte) (id keybase1.SigIDBase, err error) {
88	return id, errors.New("VerifyString not implemented")
89}
90
91func (g *GPGKey) EncryptToString(plaintext []byte, sender GenericKey) (ciphertext string, err error) {
92	return ciphertext, errors.New("EncryptToString not implemented")
93}
94
95func (g *GPGKey) DecryptFromString(ciphertext string) (msg []byte, sender keybase1.KID, err error) {
96	return msg, sender, errors.New("DecryptFromString not implemented")
97}
98
99func (g *GPGKey) ExportPublicAndPrivate() (RawPublicKey, RawPrivateKey, error) {
100	return nil, nil, errors.New("ExportPublicAndPrivate not implemented for GPGKey")
101}
102
103func (g *GPGKey) VerboseDescription() string {
104	return ""
105}
106
107func (g *GPGKey) CheckSecretKey() error {
108	return nil
109}
110
111func (g *GPGKey) CanSign() bool {
112	return true
113}
114
115func (g *GPGKey) CanEncrypt() bool {
116	return false
117}
118
119func (g *GPGKey) CanDecrypt() bool {
120	return false
121}
122
123func (g *GPGKey) HasSecretKey() bool {
124	return true
125}
126
127func (g *GPGKey) Encode() (string, error) {
128	return "", errors.New("Encode not implemented")
129}
130
131func (g *GPGKey) SecretSymmetricKey(reason EncryptionReason) (NaclSecretBoxKey, error) {
132	return NaclSecretBoxKey{}, KeyCannotEncryptError{}
133}
134