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	"strings"
8
9	"github.com/keybase/client/go/kbcrypto"
10	keybase1 "github.com/keybase/client/go/protocol/keybase1"
11)
12
13type VerifyContext interface {
14	Debug(format string, args ...interface{})
15}
16
17type RawPublicKey []byte
18type RawPrivateKey []byte
19
20type GenericKey interface {
21	GetKID() keybase1.KID
22	GetBinaryKID() keybase1.BinaryKID
23	GetAlgoType() kbcrypto.AlgoType
24
25	// Sign to an ASCII signature (which includes the message
26	// itself) and return it, along with a derived ID.
27	SignToString(msg []byte) (sig string, id keybase1.SigIDBase, err error)
28
29	// Verify that the given signature is valid and extracts the
30	// embedded message from it. Also returns the signature ID.
31	VerifyStringAndExtract(ctx VerifyContext, sig string) (msg []byte, id keybase1.SigIDBase, err error)
32
33	// Verify that the given signature is valid and that its
34	// embedded message matches the given one. Also returns the
35	// signature ID.
36	VerifyString(ctx VerifyContext, sig string, msg []byte) (id keybase1.SigIDBase, err error)
37
38	// Encrypt to an ASCII armored encryption; optionally include a sender's
39	// (private) key so that we can provably see who sent the message.
40	EncryptToString(plaintext []byte, sender GenericKey) (ciphertext string, err error)
41
42	// Decrypt the output of Encrypt above; provide the plaintext and also
43	// the KID of the key that sent the message (if applicable).
44	DecryptFromString(ciphertext string) (msg []byte, sender keybase1.KID, err error)
45
46	// Derive a secret key from a DH secret key
47	SecretSymmetricKey(reason EncryptionReason) (NaclSecretBoxKey, error)
48
49	VerboseDescription() string
50	CheckSecretKey() error
51	CanSign() bool
52	CanEncrypt() bool
53	CanDecrypt() bool
54	HasSecretKey() bool
55	Encode() (string, error) // encode public key to string
56
57	// ExportPublicAndPrivate to special-purpose types so there is no way we can
58	// accidentally reverse them.
59	ExportPublicAndPrivate() (public RawPublicKey, private RawPrivateKey, err error)
60}
61
62func CanEncrypt(key GenericKey) bool {
63	switch key.(type) {
64	case NaclDHKeyPair:
65		return true
66	case *PGPKeyBundle:
67		return true
68	default:
69		return false
70	}
71}
72
73func skbPushAndSave(m MetaContext, skb *SKB) (err error) {
74	defer m.Trace("skbPushAndSave", &err)()
75	ring, err := m.Keyring()
76	if err != nil {
77		return err
78	}
79	err = ring.PushAndSave(skb)
80	if err != nil {
81		return err
82	}
83	return nil
84}
85
86// Any valid key matches the empty string.
87func KeyMatchesQuery(key GenericKey, q string, exact bool) bool {
88	if key.GetKID().Match(q, exact) {
89		return true
90	}
91	return GetPGPFingerprintFromGenericKey(key).Match(q, exact)
92}
93
94func IsPGP(key GenericKey) bool {
95	_, ok := key.(*PGPKeyBundle)
96	return ok
97}
98
99func ParseGenericKey(bundle string) (GenericKey, *Warnings, error) {
100	if isPGPBundle(bundle) {
101		// PGP key
102		return ReadOneKeyFromStringLiberal(bundle)
103	}
104	// NaCl key
105	key, err := ImportKeypairFromKID(keybase1.KIDFromString(bundle))
106	return key, &Warnings{}, err
107}
108
109func isPGPBundle(armored string) bool {
110	return strings.HasPrefix(armored, "-----BEGIN PGP")
111}
112
113func GenericKeyEqual(k1, k2 GenericKey) bool {
114	return k1.GetKID().Equal(k2.GetKID())
115}
116