1package pgpkeys
2
3import (
4	"bytes"
5	"encoding/base64"
6	"encoding/hex"
7	"flag"
8	"fmt"
9	"io/ioutil"
10	"os"
11	"reflect"
12	"strings"
13	"testing"
14
15	"github.com/keybase/go-crypto/openpgp"
16	"github.com/keybase/go-crypto/openpgp/packet"
17)
18
19func TestPubKeyFilesFlag_implements(t *testing.T) {
20	var raw interface{}
21	raw = new(PubKeyFilesFlag)
22	if _, ok := raw.(flag.Value); !ok {
23		t.Fatalf("PubKeysFilesFlag should be a Value")
24	}
25}
26
27func TestPubKeyFilesFlagSetBinary(t *testing.T) {
28	tempDir, err := ioutil.TempDir("", "vault-test")
29	if err != nil {
30		t.Fatalf("Error creating temporary directory: %s", err)
31	}
32	defer os.RemoveAll(tempDir)
33
34	decoder := base64.StdEncoding
35	pub1Bytes, err := decoder.DecodeString(pubKey1)
36	if err != nil {
37		t.Fatalf("Error decoding bytes for public key 1: %s", err)
38	}
39	err = ioutil.WriteFile(tempDir+"/pubkey1", pub1Bytes, 0755)
40	if err != nil {
41		t.Fatalf("Error writing pub key 1 to temp file: %s", err)
42	}
43	pub2Bytes, err := decoder.DecodeString(pubKey2)
44	if err != nil {
45		t.Fatalf("Error decoding bytes for public key 2: %s", err)
46	}
47	err = ioutil.WriteFile(tempDir+"/pubkey2", pub2Bytes, 0755)
48	if err != nil {
49		t.Fatalf("Error writing pub key 2 to temp file: %s", err)
50	}
51	pub3Bytes, err := decoder.DecodeString(pubKey3)
52	if err != nil {
53		t.Fatalf("Error decoding bytes for public key 3: %s", err)
54	}
55	err = ioutil.WriteFile(tempDir+"/pubkey3", pub3Bytes, 0755)
56	if err != nil {
57		t.Fatalf("Error writing pub key 3 to temp file: %s", err)
58	}
59
60	pkf := new(PubKeyFilesFlag)
61	err = pkf.Set(tempDir + "/pubkey1,@" + tempDir + "/pubkey2")
62	if err != nil {
63		t.Fatalf("err: %s", err)
64	}
65
66	err = pkf.Set(tempDir + "/pubkey3")
67	if err == nil {
68		t.Fatalf("err: should not have been able to set a second value")
69	}
70
71	expected := []string{strings.Replace(pubKey1, "\n", "", -1), strings.Replace(pubKey2, "\n", "", -1)}
72	if !reflect.DeepEqual(pkf.String(), fmt.Sprint(expected)) {
73		t.Fatalf("Bad: %#v", pkf)
74	}
75}
76
77func TestPubKeyFilesFlagSetB64(t *testing.T) {
78	tempDir, err := ioutil.TempDir("", "vault-test")
79	if err != nil {
80		t.Fatalf("Error creating temporary directory: %s", err)
81	}
82	defer os.RemoveAll(tempDir)
83
84	err = ioutil.WriteFile(tempDir+"/pubkey1", []byte(pubKey1), 0755)
85	if err != nil {
86		t.Fatalf("Error writing pub key 1 to temp file: %s", err)
87	}
88	err = ioutil.WriteFile(tempDir+"/pubkey2", []byte(pubKey2), 0755)
89	if err != nil {
90		t.Fatalf("Error writing pub key 2 to temp file: %s", err)
91	}
92	err = ioutil.WriteFile(tempDir+"/pubkey3", []byte(pubKey3), 0755)
93	if err != nil {
94		t.Fatalf("Error writing pub key 3 to temp file: %s", err)
95	}
96
97	pkf := new(PubKeyFilesFlag)
98	err = pkf.Set(tempDir + "/pubkey1,@" + tempDir + "/pubkey2")
99	if err != nil {
100		t.Fatalf("err: %s", err)
101	}
102
103	err = pkf.Set(tempDir + "/pubkey3")
104	if err == nil {
105		t.Fatalf("err: should not have been able to set a second value")
106	}
107
108	expected := []string{pubKey1, pubKey2}
109	if !reflect.DeepEqual(pkf.String(), fmt.Sprint(expected)) {
110		t.Fatalf("bad: got %s, expected %s", pkf.String(), fmt.Sprint(expected))
111	}
112}
113
114func TestPubKeyFilesFlagSetKeybase(t *testing.T) {
115	tempDir, err := ioutil.TempDir("", "vault-test")
116	if err != nil {
117		t.Fatalf("Error creating temporary directory: %s", err)
118	}
119	defer os.RemoveAll(tempDir)
120
121	err = ioutil.WriteFile(tempDir+"/pubkey2", []byte(pubKey2), 0755)
122	if err != nil {
123		t.Fatalf("Error writing pub key 2 to temp file: %s", err)
124	}
125
126	pkf := new(PubKeyFilesFlag)
127	err = pkf.Set("keybase:jefferai,@" + tempDir + "/pubkey2" + ",keybase:hashicorp")
128	if err != nil {
129		t.Fatalf("err: %s", err)
130	}
131	fingerprints := []string{}
132	for _, pubkey := range []string(*pkf) {
133		keyBytes, err := base64.StdEncoding.DecodeString(pubkey)
134		if err != nil {
135			t.Fatalf("bad: %v", err)
136		}
137		pubKeyBuf := bytes.NewBuffer(keyBytes)
138		reader := packet.NewReader(pubKeyBuf)
139		entity, err := openpgp.ReadEntity(reader)
140		if err != nil {
141			t.Fatalf("bad: %v", err)
142		}
143		if entity == nil {
144			t.Fatalf("nil entity encountered")
145		}
146		fingerprints = append(fingerprints, hex.EncodeToString(entity.PrimaryKey.Fingerprint[:]))
147	}
148
149	exp := []string{
150		"0f801f518ec853daff611e836528efcac6caa3db",
151		"cf3d4694c9f57b28cb4092c2eb832c67eb5e8957",
152		"91a6e7f85d05c65630bef18951852d87348ffc4c",
153	}
154
155	if !reflect.DeepEqual(fingerprints, exp) {
156		t.Fatalf("bad: got \n%#v\nexpected\n%#v\n", fingerprints, exp)
157	}
158}
159
160const pubKey1 = `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`
186const pubKey2 = `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`
212const pubKey3 = `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`
238