1// Copyright 2018 The NATS Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package nkeys
15
16import (
17	"bytes"
18	"crypto/rand"
19	"encoding/base64"
20	"io"
21	"os"
22	"regexp"
23	"testing"
24
25	"golang.org/x/crypto/ed25519"
26)
27
28func TestVersion(t *testing.T) {
29	// Semantic versioning
30	verRe := regexp.MustCompile(`\d+.\d+.\d+(-\S+)?`)
31	if !verRe.MatchString(Version) {
32		t.Fatalf("Version not compatible with semantic versioning: %q", Version)
33	}
34}
35
36func TestVersionMatchesTag(t *testing.T) {
37	tag := os.Getenv("TRAVIS_TAG")
38	if tag == "" {
39		t.SkipNow()
40	}
41	// We expect a tag of the form vX.Y.Z. If that's not the case,
42	// we need someone to have a look. So fail if first letter is not
43	// a `v`
44	if tag[0] != 'v' {
45		t.Fatalf("Expect tag to start with `v`, tag is: %s", tag)
46	}
47	// Strip the `v` from the tag for the version comparison.
48	if Version != tag[1:] {
49		t.Fatalf("Version (%s) does not match tag (%s)", Version, tag[1:])
50	}
51}
52
53func TestEncode(t *testing.T) {
54	var rawKey [32]byte
55
56	_, err := io.ReadFull(rand.Reader, rawKey[:])
57	if err != nil {
58		t.Fatalf("Unexpected error reading from crypto/rand: %v", err)
59	}
60	_, err = Encode(PrefixByteUser, rawKey[:])
61	if err != nil {
62		t.Fatalf("Unexpected error from Encode: %v", err)
63	}
64	str, err := Encode(22<<3, rawKey[:])
65	if err == nil {
66		t.Fatal("Expected an error from Encode but received nil")
67	}
68	if str != nil {
69		t.Fatalf("Expected empty string from Encode: got %s", str)
70	}
71}
72
73func TestDecode(t *testing.T) {
74	var rawKey [32]byte
75
76	_, err := io.ReadFull(rand.Reader, rawKey[:])
77	if err != nil {
78		t.Fatalf("Unexpected error reading from crypto/rand: %v", err)
79	}
80	str, err := Encode(PrefixByteUser, rawKey[:])
81	if err != nil {
82		t.Fatalf("Unexpected error from Encode: %v", err)
83	}
84
85	decoded, err := Decode(PrefixByteUser, str)
86	if err != nil {
87		t.Fatalf("Unexpected error from Decode: %v", err)
88	}
89	if !bytes.Equal(decoded, rawKey[:]) {
90		t.Fatalf("Decoded does not match the original")
91	}
92}
93
94func TestSeed(t *testing.T) {
95	var rawKeyShort [16]byte
96
97	_, err := io.ReadFull(rand.Reader, rawKeyShort[:])
98	if err != nil {
99		t.Fatalf("Unexpected error reading from crypto/rand: %v", err)
100	}
101	// Seeds need to be 64 bytes
102	if _, err := EncodeSeed(PrefixByteUser, rawKeyShort[:]); err != ErrInvalidSeedLen {
103		t.Fatalf("Did not receive ErrInvalidSeed error, received %v", err)
104	}
105	// Seeds need to be typed with only public types.
106	if _, err := EncodeSeed(PrefixByteSeed, rawKeyShort[:]); err != ErrInvalidPrefixByte {
107		t.Fatalf("Did not receive ErrInvalidPrefixByte error, received %v", err)
108	}
109
110	var rawSeed [ed25519.SeedSize]byte
111
112	_, err = io.ReadFull(rand.Reader, rawSeed[:])
113	if err != nil {
114		t.Fatalf("Unexpected error reading from crypto/rand: %v", err)
115	}
116
117	seed, err := EncodeSeed(PrefixByteUser, rawSeed[:])
118	if err != nil {
119		t.Fatalf("EncodeSeed received an error: %v", err)
120	}
121
122	pre, decoded, err := DecodeSeed(seed)
123	if err != nil {
124		t.Fatalf("Got an unexpected error from DecodeSeed: %v", err)
125	}
126	if pre != PrefixByteUser {
127		t.Fatalf("Expected the prefix to be PrefixByteUser(%v), got %v",
128			PrefixByteUser, pre)
129	}
130	if !bytes.Equal(decoded, rawSeed[:]) {
131		t.Fatalf("Decoded seed does not match the original")
132	}
133}
134
135func TestAccount(t *testing.T) {
136	account, err := CreateAccount()
137	if err != nil {
138		t.Fatalf("Expected non-nil error on CreateAccount, received %v", err)
139	}
140	if account == nil {
141		t.Fatal("Expect a non-nil account")
142	}
143	seed, err := account.Seed()
144	if err != nil {
145		t.Fatalf("Unexpected error retrieving seed: %v", err)
146	}
147	_, err = Decode(PrefixByteSeed, seed)
148	if err != nil {
149		t.Fatalf("Expected a proper seed string, got %s", seed)
150	}
151
152	// Check Public
153	public, err := account.PublicKey()
154	if err != nil {
155		t.Fatalf("Received an error retrieving public key: %v", err)
156	}
157	if public[0] != 'A' {
158		t.Fatalf("Expected a prefix of 'A' but got %c", public[0])
159	}
160	if !IsValidPublicAccountKey(public) {
161		t.Fatalf("Not a valid public account key")
162	}
163
164	// Check Private
165	private, err := account.PrivateKey()
166	if err != nil {
167		t.Fatalf("Received an error retrieving private key: %v", err)
168	}
169	if private[0] != 'P' {
170		t.Fatalf("Expected a prefix of 'P' but got %v", private[0])
171	}
172
173	// Check Sign and Verify
174	data := []byte("Hello World")
175	sig, err := account.Sign(data)
176	if err != nil {
177		t.Fatalf("Unexpected error signing from account: %v", err)
178	}
179	if len(sig) != ed25519.SignatureSize {
180		t.Fatalf("Expected signature size of %d but got %d",
181			ed25519.SignatureSize, len(sig))
182	}
183	err = account.Verify(data, sig)
184	if err != nil {
185		t.Fatalf("Unexpected error verifying signature: %v", err)
186	}
187}
188
189func TestUser(t *testing.T) {
190	user, err := CreateUser()
191	if err != nil {
192		t.Fatalf("Expected non-nil error on CreateUser, received %v", err)
193	}
194	if user == nil {
195		t.Fatal("Expect a non-nil user")
196	}
197
198	// Check Public
199	public, err := user.PublicKey()
200	if err != nil {
201		t.Fatalf("Received an error retrieving public key: %v", err)
202	}
203	if public[0] != 'U' {
204		t.Fatalf("Expected a prefix of 'U' but got %c", public[0])
205	}
206	if !IsValidPublicUserKey(public) {
207		t.Fatalf("Not a valid public user key")
208	}
209}
210
211func TestOperator(t *testing.T) {
212	operator, err := CreateOperator()
213	if err != nil {
214		t.Fatalf("Expected non-nil error on CreateOperator, received %v", err)
215	}
216	if operator == nil {
217		t.Fatal("Expect a non-nil operator")
218	}
219
220	// Check Public
221	public, err := operator.PublicKey()
222	if err != nil {
223		t.Fatalf("Received an error retrieving public key: %v", err)
224	}
225	if public[0] != 'O' {
226		t.Fatalf("Expected a prefix of 'O' but got %c", public[0])
227	}
228	if !IsValidPublicOperatorKey(public) {
229		t.Fatalf("Not a valid public cluster key")
230	}
231}
232
233func TestCluster(t *testing.T) {
234	cluster, err := CreateCluster()
235	if err != nil {
236		t.Fatalf("Expected non-nil error on CreateCluster, received %v", err)
237	}
238	if cluster == nil {
239		t.Fatal("Expect a non-nil cluster")
240	}
241
242	// Check Public
243	public, err := cluster.PublicKey()
244	if err != nil {
245		t.Fatalf("Received an error retrieving public key: %v", err)
246	}
247	if public[0] != 'C' {
248		t.Fatalf("Expected a prefix of 'C' but got %c", public[0])
249	}
250	if !IsValidPublicClusterKey(public) {
251		t.Fatalf("Not a valid public cluster key")
252	}
253}
254
255func TestServer(t *testing.T) {
256	server, err := CreateServer()
257	if err != nil {
258		t.Fatalf("Expected non-nil error on CreateServer, received %v", err)
259	}
260	if server == nil {
261		t.Fatal("Expect a non-nil server")
262	}
263
264	// Check Public
265	public, err := server.PublicKey()
266	if err != nil {
267		t.Fatalf("Received an error retrieving public key: %v", err)
268	}
269	if public[0] != 'N' {
270		t.Fatalf("Expected a prefix of 'N' but got %c", public[0])
271	}
272	if !IsValidPublicServerKey(public) {
273		t.Fatalf("Not a valid public server key")
274	}
275}
276
277func TestPrefixByte(t *testing.T) {
278	user, _ := CreateUser()
279	pub, _ := user.PublicKey()
280	if pre := Prefix(pub); pre != PrefixByteUser {
281		t.Fatalf("Expected %s, got %s\n", PrefixByteUser, pre)
282	}
283	seed, _ := user.Seed()
284	if pre := Prefix(string(seed)); pre != PrefixByteSeed {
285		t.Fatalf("Expected %s, got %s\n", PrefixByteSeed, pre)
286	}
287	if pre := Prefix("SEED"); pre != PrefixByteUnknown {
288		t.Fatalf("Expected %s, got %s\n", PrefixByteUnknown, pre)
289	}
290	account, _ := CreateAccount()
291	pub, _ = account.PublicKey()
292	if pre := Prefix(pub); pre != PrefixByteAccount {
293		t.Fatalf("Expected %s, got %s\n", PrefixByteAccount, pre)
294	}
295}
296
297func TestIsValidPublic(t *testing.T) {
298	user, _ := CreateUser()
299	pub, _ := user.PublicKey()
300	if !IsValidPublicKey(pub) {
301		t.Fatalf("Expected pub to be a valid public key")
302	}
303	seed, _ := user.Seed()
304	if IsValidPublicKey(string(seed)) {
305		t.Fatalf("Expected seed to not be a valid public key")
306	}
307	if IsValidPublicKey("BAD") {
308		t.Fatalf("Expected BAD to not be a valid public key")
309	}
310	account, _ := CreateAccount()
311	pub, _ = account.PublicKey()
312	if !IsValidPublicKey(pub) {
313		t.Fatalf("Expected pub to be a valid public key")
314	}
315}
316
317func TestFromPublic(t *testing.T) {
318	// Create a User
319	user, err := CreateUser()
320	if err != nil {
321		t.Fatalf("Expected non-nil error on CreateUser, received %v", err)
322	}
323	if user == nil {
324		t.Fatal("Expect a non-nil user")
325	}
326
327	// Now create a publickey only KeyPair
328	publicKey, err := user.PublicKey()
329	if err != nil {
330		t.Fatalf("Error retrieving public key from user: %v", err)
331	}
332	publicKeyClone, _ := user.PublicKey()
333	if publicKeyClone != publicKey {
334		t.Fatalf("Expected the public keys to match: %q vs %q", publicKeyClone, publicKey)
335	}
336
337	pubUser, err := FromPublicKey(publicKey)
338	if err != nil {
339		t.Fatalf("Error creating public key only user: %v", err)
340	}
341
342	publicKey2, err := pubUser.PublicKey()
343	if err != nil {
344		t.Fatalf("Error retrieving public key from public user: %v", err)
345	}
346	// Make sure they match
347	if publicKey2 != publicKey {
348		t.Fatalf("Expected the public keys to match: %q vs %q", publicKey2, publicKey)
349	}
350
351	if _, err = pubUser.PrivateKey(); err == nil {
352		t.Fatalf("Expected and error trying to get private key")
353	}
354	if _, err := pubUser.Seed(); err == nil {
355		t.Fatalf("Expected and error trying to get seed")
356	}
357
358	data := []byte("Hello World")
359
360	// Can't sign..
361	if _, err = pubUser.Sign(data); err != ErrCannotSign {
362		t.Fatalf("Expected %v, but got %v", ErrCannotSign, err)
363	}
364
365	// Should be able to verify with pubUser.
366	sig, err := user.Sign(data)
367	if err != nil {
368		t.Fatalf("Unexpected error signing from user: %v", err)
369	}
370
371	err = pubUser.Verify(data, sig)
372	if err != nil {
373		t.Fatalf("Unexpected error verifying signature: %v", err)
374	}
375
376	// Create another user to sign and make sure verify fails.
377	user2, _ := CreateUser()
378	sig, _ = user2.Sign(data)
379
380	err = pubUser.Verify(data, sig)
381	if err == nil {
382		t.Fatalf("Expected verification to fail.")
383	}
384}
385
386func TestFromSeed(t *testing.T) {
387	account, err := CreateAccount()
388	if err != nil {
389		t.Fatalf("Expected non-nil error on CreateAccount, received %v", err)
390	}
391	if account == nil {
392		t.Fatal("Expect a non-nil account")
393	}
394
395	data := []byte("Hello World")
396	sig, err := account.Sign(data)
397	if err != nil {
398		t.Fatalf("Unexpected error signing from account: %v", err)
399	}
400
401	seed, err := account.Seed()
402	if err != nil {
403		t.Fatalf("Unexpected error retrieving seed: %v", err)
404	}
405	// Make sure the seed starts with SA
406	if !bytes.HasPrefix(seed, []byte("SA")) {
407		t.Fatalf("Expected seed to start with 'SA', go '%s'", seed[:2])
408	}
409
410	account2, err := FromSeed(seed)
411	if err != nil {
412		t.Fatalf("Error recreating account from seed: %v", err)
413	}
414	if account2 == nil {
415		t.Fatal("Expect a non-nil account")
416	}
417	err = account2.Verify(data, sig)
418	if err != nil {
419		t.Fatalf("Unexpected error verifying signature: %v", err)
420	}
421}
422
423func TestKeyPairFailures(t *testing.T) {
424	var tooshort [8]byte
425	if _, err := EncodeSeed(PrefixByteUser, tooshort[:]); err == nil {
426		t.Fatal("Expected an error with insufficient rand")
427	}
428
429	if _, err := CreatePair(PrefixBytePrivate); err == nil {
430		t.Fatal("Expected an error with non-public prefix")
431	}
432	kpbad := &kp{[]byte("SEEDBAD")}
433	if _, _, err := kpbad.keys(); err == nil {
434		t.Fatal("Expected an error decoding keys with a bad seed")
435	}
436	if _, err := kpbad.PublicKey(); err == nil {
437		t.Fatal("Expected an error getting PublicKey from KP with a bad seed")
438	}
439	if _, err := kpbad.PrivateKey(); err == nil {
440		t.Fatal("Expected an error getting PrivateKey from KP with a bad seed")
441	}
442	if _, err := kpbad.Sign([]byte("ok")); err == nil {
443		t.Fatal("Expected an error from Signing from KP with a bad seed")
444	}
445}
446
447func TestBadDecode(t *testing.T) {
448	if _, err := decode([]byte("foo!")); err == nil {
449		t.Fatal("Expected an error decoding non-base32")
450	}
451	if _, err := decode([]byte("OK")); err == nil {
452		t.Fatal("Expected an error decoding a too short string")
453	}
454
455	// Create invalid checksum
456	account, _ := CreateAccount()
457	pkey, _ := account.PublicKey()
458	bpkey := []byte(pkey)
459	bpkey[len(pkey)-1] = '0'
460	bpkey[len(pkey)-2] = '0'
461	if _, err := decode(bpkey); err == nil {
462		t.Fatal("Expected error on decode with bad checksum")
463	}
464
465	if _, err := Decode(PrefixByteUser, []byte(pkey)); err == nil {
466		t.Fatal("Expected error on Decode with mismatched prefix")
467	}
468	if _, err := Decode(PrefixByte(3<<3), []byte(pkey)); err == nil {
469		t.Fatal("Expected error on Decode with invalid prefix")
470	}
471	if _, err := Decode(PrefixByteAccount, bpkey); err == nil {
472		t.Fatal("Expected error on Decode with bad checksum")
473	}
474	// Seed version
475	if _, _, err := DecodeSeed(bpkey); err == nil {
476		t.Fatal("Expected error on DecodeSeed with bad checksum")
477	}
478	if _, _, err := DecodeSeed([]byte(pkey)); err == nil {
479		t.Fatal("Expected error on DecodeSeed with bad seed type")
480	}
481
482	seed, _ := account.Seed()
483	bseed := []byte(seed)
484	bseed[1] = 'S'
485	if _, _, err := DecodeSeed(bseed); err == nil {
486		t.Fatal("Expected error on DecodeSeed with bad prefix type")
487	}
488	if _, err := FromSeed(bseed); err == nil {
489		t.Fatal("Expected error on FromSeed with bad prefix type")
490	}
491
492	if _, err := FromPublicKey(string(bpkey)); err == nil {
493		t.Fatal("Expected error on FromPublicKey with bad checksum")
494	}
495	if _, err := FromPublicKey(string(seed)); err == nil {
496		t.Fatal("Expected error on FromPublicKey with bad checksum")
497	}
498}
499
500func TestFromRawSeed(t *testing.T) {
501	user, err := CreateUser()
502	if err != nil {
503		t.Fatalf("Expected non-nil error on CreateUser, received %v", err)
504	}
505	se, _ := user.Seed()
506	_, raw, _ := DecodeSeed(se)
507	user2, err := FromRawSeed(PrefixByteUser, raw)
508	if err != nil {
509		t.Fatalf("Expected non-nil error on FromRawSeed, received %v", err)
510	}
511	s2e, _ := user2.Seed()
512	if !bytes.Equal(se, s2e) {
513		t.Fatalf("Expected the seeds to be the same, got %v vs %v\n", se, s2e)
514	}
515}
516
517func TestWipe(t *testing.T) {
518	user, err := CreateUser()
519	if err != nil {
520		t.Fatalf("Expected non-nil error on CreateUser, received %v", err)
521	}
522	pubKey, err := user.PublicKey()
523	if err != nil {
524		t.Fatalf("Received an error retrieving public key: %v", err)
525	}
526	seed := user.(*kp).seed
527	// Copy so we know the original
528	copy := append([]byte{}, seed...)
529	user.Wipe()
530	// Make sure new seed is nil
531	if wiped := user.(*kp).seed; wiped != nil {
532		t.Fatalf("Expected the seed to be nil, got %q", wiped)
533	}
534	// Make sure the original seed is not equal to the seed in memory.
535	if bytes.Equal(seed, copy) {
536		t.Fatalf("Expected the memory for the seed to be randomized")
537	}
538
539	// Now test public
540	user, err = FromPublicKey(pubKey)
541	if err != nil {
542		t.Fatalf("Received an error create KeyPair from PublicKey: %v", err)
543	}
544
545	edPub := user.(*pub).pub
546	// Copy so we know the original
547	copy = append([]byte{}, edPub...)
548
549	user.Wipe()
550
551	// First check pre was changed
552	if user.(*pub).pre != '0' {
553		t.Fatalf("Expected prefix to be changed")
554	}
555
556	// Make sure the original key is not equal to the one in memory.
557	if bytes.Equal(edPub, copy) {
558		t.Fatalf("Expected the memory for the pubKey to be randomized")
559	}
560}
561
562const (
563	nonceRawLen = 16
564	nonceLen    = 22 // base64.RawURLEncoding.EncodedLen(nonceRawLen)
565)
566
567func BenchmarkSign(b *testing.B) {
568	data := make([]byte, nonceRawLen)
569	nonce := make([]byte, nonceLen)
570	rand.Read(data)
571	base64.RawURLEncoding.Encode(nonce, data)
572
573	user, err := CreateUser()
574	if err != nil {
575		b.Fatalf("Error creating User Nkey: %v", err)
576	}
577
578	b.ResetTimer()
579	for i := 0; i < b.N; i++ {
580		if _, err := user.Sign(nonce); err != nil {
581			b.Fatalf("Error signing nonce: %v", err)
582		}
583	}
584}
585
586func BenchmarkVerify(b *testing.B) {
587	data := make([]byte, nonceRawLen)
588	nonce := make([]byte, nonceLen)
589	rand.Read(data)
590	base64.RawURLEncoding.Encode(nonce, data)
591
592	user, err := CreateUser()
593	if err != nil {
594		b.Fatalf("Error creating User Nkey: %v", err)
595	}
596	sig, err := user.Sign(nonce)
597	if err != nil {
598		b.Fatalf("Error sigining nonce: %v", err)
599	}
600
601	b.ResetTimer()
602	for i := 0; i < b.N; i++ {
603		if err := user.Verify(nonce, sig); err != nil {
604			b.Fatalf("Error verifying nonce: %v", err)
605		}
606	}
607}
608
609func BenchmarkPublicVerify(b *testing.B) {
610	data := make([]byte, nonceRawLen)
611	nonce := make([]byte, nonceLen)
612	rand.Read(data)
613	base64.RawURLEncoding.Encode(nonce, data)
614
615	user, err := CreateUser()
616	if err != nil {
617		b.Fatalf("Error creating User Nkey: %v", err)
618	}
619	sig, err := user.Sign(nonce)
620	if err != nil {
621		b.Fatalf("Error sigining nonce: %v", err)
622	}
623	pk, err := user.PublicKey()
624	if err != nil {
625		b.Fatalf("Could not extract public key from user: %v", err)
626	}
627	pub, err := FromPublicKey(pk)
628	if err != nil {
629		b.Fatalf("Could not create public key pair from public key string: %v", err)
630	}
631
632	b.ResetTimer()
633	for i := 0; i < b.N; i++ {
634		if err := pub.Verify(nonce, sig); err != nil {
635			b.Fatalf("Error verifying nonce: %v", err)
636		}
637	}
638}
639
640func TestValidateKeyPairRole(t *testing.T) {
641	okp, err := CreateOperator()
642	if err != nil {
643		t.Fatal(err)
644	}
645	akp, err := CreateAccount()
646	if err != nil {
647		t.Fatal(err)
648	}
649	ukp, err := CreateUser()
650	if err != nil {
651		t.Fatal(err)
652	}
653	ckp, err := CreateCluster()
654	if err != nil {
655		t.Fatal(err)
656	}
657	skp, err := CreateServer()
658	if err != nil {
659		t.Fatal(err)
660	}
661
662	var keyroles = []struct {
663		kp    KeyPair
664		roles []PrefixByte
665		ok    bool
666		name  string
667	}{
668		{kp: okp, name: "want operator", roles: []PrefixByte{PrefixByteOperator}, ok: true},
669		{kp: akp, name: "want account", roles: []PrefixByte{PrefixByteAccount}, ok: true},
670		{kp: ukp, name: "want user", roles: []PrefixByte{PrefixByteUser}, ok: true},
671		{kp: ckp, name: "want cluster", roles: []PrefixByte{PrefixByteCluster}, ok: true},
672		{kp: skp, name: "want server", roles: []PrefixByte{PrefixByteServer}, ok: true},
673
674		{kp: okp, name: "want account or operator", roles: []PrefixByte{PrefixByteOperator, PrefixByteAccount}, ok: true},
675		{kp: akp, name: "want account or operator", roles: []PrefixByte{PrefixByteOperator, PrefixByteAccount}, ok: true},
676
677		{kp: akp, name: "want operator got account", roles: []PrefixByte{PrefixByteOperator}, ok: false},
678		{kp: ukp, name: "want account or operator got user", roles: []PrefixByte{PrefixByteOperator, PrefixByteAccount}, ok: false},
679	}
680
681	for _, e := range keyroles {
682		err := CompatibleKeyPair(e.kp, e.roles...)
683		if err == nil && !e.ok {
684			t.Fatalf("test %q should have failed but didn't", e.name)
685		}
686		if err != nil && e.ok {
687			t.Fatalf("test %q should have not failed: %v", e.name, err)
688
689		}
690		if err != nil && !e.ok && err != ErrIncompatibleKey {
691			t.Fatalf("unexpected error type for %q: %v", e.name, err)
692		}
693	}
694}
695