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	"encoding/base32"
19	"encoding/binary"
20	"golang.org/x/crypto/ed25519"
21)
22
23// PrefixByte is a lead byte representing the type.
24type PrefixByte byte
25
26const (
27	// PrefixByteSeed is the version byte used for encoded NATS Seeds
28	PrefixByteSeed PrefixByte = 18 << 3 // Base32-encodes to 'S...'
29
30	// PrefixBytePrivate is the version byte used for encoded NATS Private keys
31	PrefixBytePrivate PrefixByte = 15 << 3 // Base32-encodes to 'P...'
32
33	// PrefixByteServer is the version byte used for encoded NATS Servers
34	PrefixByteServer PrefixByte = 13 << 3 // Base32-encodes to 'N...'
35
36	// PrefixByteCluster is the version byte used for encoded NATS Clusters
37	PrefixByteCluster PrefixByte = 2 << 3 // Base32-encodes to 'C...'
38
39	// PrefixByteOperator is the version byte used for encoded NATS Operators
40	PrefixByteOperator PrefixByte = 14 << 3 // Base32-encodes to 'O...'
41
42	// PrefixByteAccount is the version byte used for encoded NATS Accounts
43	PrefixByteAccount PrefixByte = 0 // Base32-encodes to 'A...'
44
45	// PrefixByteUser is the version byte used for encoded NATS Users
46	PrefixByteUser PrefixByte = 20 << 3 // Base32-encodes to 'U...'
47
48	// PrefixByteUnknown is for unknown prefixes.
49	PrefixByteUnknown PrefixByte = 23 << 3 // Base32-encodes to 'X...'
50)
51
52// Set our encoding to not include padding '=='
53var b32Enc = base32.StdEncoding.WithPadding(base32.NoPadding)
54
55// Encode will encode a raw key or seed with the prefix and crc16 and then base32 encoded.
56func Encode(prefix PrefixByte, src []byte) ([]byte, error) {
57	if err := checkValidPrefixByte(prefix); err != nil {
58		return nil, err
59	}
60
61	var raw bytes.Buffer
62
63	// write prefix byte
64	if err := raw.WriteByte(byte(prefix)); err != nil {
65		return nil, err
66	}
67
68	// write payload
69	if _, err := raw.Write(src); err != nil {
70		return nil, err
71	}
72
73	// Calculate and write crc16 checksum
74	err := binary.Write(&raw, binary.LittleEndian, crc16(raw.Bytes()))
75	if err != nil {
76		return nil, err
77	}
78
79	data := raw.Bytes()
80	buf := make([]byte, b32Enc.EncodedLen(len(data)))
81	b32Enc.Encode(buf, data)
82	return buf[:], nil
83}
84
85// EncodeSeed will encode a raw key with the prefix and then seed prefix and crc16 and then base32 encoded.
86func EncodeSeed(public PrefixByte, src []byte) ([]byte, error) {
87	if err := checkValidPublicPrefixByte(public); err != nil {
88		return nil, err
89	}
90
91	if len(src) != ed25519.SeedSize {
92		return nil, ErrInvalidSeedLen
93	}
94
95	// In order to make this human printable for both bytes, we need to do a little
96	// bit manipulation to setup for base32 encoding which takes 5 bits at a time.
97	b1 := byte(PrefixByteSeed) | (byte(public) >> 5)
98	b2 := (byte(public) & 31) << 3 // 31 = 00011111
99
100	var raw bytes.Buffer
101
102	raw.WriteByte(b1)
103	raw.WriteByte(b2)
104
105	// write payload
106	if _, err := raw.Write(src); err != nil {
107		return nil, err
108	}
109
110	// Calculate and write crc16 checksum
111	err := binary.Write(&raw, binary.LittleEndian, crc16(raw.Bytes()))
112	if err != nil {
113		return nil, err
114	}
115
116	data := raw.Bytes()
117	buf := make([]byte, b32Enc.EncodedLen(len(data)))
118	b32Enc.Encode(buf, data)
119	return buf, nil
120}
121
122// IsValidEncoding will tell you if the encoding is a valid key.
123func IsValidEncoding(src []byte) bool {
124	_, err := decode(src)
125	return err == nil
126}
127
128// decode will decode the base32 and check crc16 and the prefix for validity.
129func decode(src []byte) ([]byte, error) {
130	raw := make([]byte, b32Enc.DecodedLen(len(src)))
131	n, err := b32Enc.Decode(raw, src)
132	if err != nil {
133		return nil, err
134	}
135	raw = raw[:n]
136
137	if len(raw) < 4 {
138		return nil, ErrInvalidEncoding
139	}
140
141	var crc uint16
142	checksum := bytes.NewReader(raw[len(raw)-2:])
143	if err := binary.Read(checksum, binary.LittleEndian, &crc); err != nil {
144		return nil, err
145	}
146
147	// ensure checksum is valid
148	if err := validate(raw[0:len(raw)-2], crc); err != nil {
149		return nil, err
150	}
151
152	return raw[:len(raw)-2], nil
153}
154
155// Decode will decode the base32 string and check crc16 and enforce the prefix is what is expected.
156func Decode(expectedPrefix PrefixByte, src []byte) ([]byte, error) {
157	if err := checkValidPrefixByte(expectedPrefix); err != nil {
158		return nil, err
159	}
160	raw, err := decode(src)
161	if err != nil {
162		return nil, err
163	}
164	if prefix := PrefixByte(raw[0]); prefix != expectedPrefix {
165		return nil, ErrInvalidPrefixByte
166	}
167	return raw[1:], nil
168}
169
170// DecodeSeed will decode the base32 string and check crc16 and enforce the prefix is a seed
171// and the subsequent type is a valid type.
172func DecodeSeed(src []byte) (PrefixByte, []byte, error) {
173	raw, err := decode(src)
174	if err != nil {
175		return PrefixByteSeed, nil, err
176	}
177	// Need to do the reverse here to get back to internal representation.
178	b1 := raw[0] & 248                          // 248 = 11111000
179	b2 := (raw[0]&7)<<5 | ((raw[1] & 248) >> 3) // 7 = 00000111
180
181	if PrefixByte(b1) != PrefixByteSeed {
182		return PrefixByteSeed, nil, ErrInvalidSeed
183	}
184	if checkValidPublicPrefixByte(PrefixByte(b2)) != nil {
185		return PrefixByteSeed, nil, ErrInvalidSeed
186	}
187	return PrefixByte(b2), raw[2:], nil
188}
189
190// Prefix returns PrefixBytes of its input
191func Prefix(src string) PrefixByte {
192	b, err := decode([]byte(src))
193	if err != nil {
194		return PrefixByteUnknown
195	}
196	prefix := PrefixByte(b[0])
197	err = checkValidPrefixByte(prefix)
198	if err == nil {
199		return prefix
200	}
201	// Might be a seed.
202	b1 := b[0] & 248
203	if PrefixByte(b1) == PrefixByteSeed {
204		return PrefixByteSeed
205	}
206	return PrefixByteUnknown
207}
208
209// IsValidPublicKey will decode and verify that the string is a valid encoded public key.
210func IsValidPublicKey(src string) bool {
211	b, err := decode([]byte(src))
212	if err != nil {
213		return false
214	}
215	if prefix := PrefixByte(b[0]); checkValidPublicPrefixByte(prefix) != nil {
216		return false
217	}
218	return true
219}
220
221// IsValidPublicUserKey will decode and verify the string is a valid encoded Public User Key.
222func IsValidPublicUserKey(src string) bool {
223	_, err := Decode(PrefixByteUser, []byte(src))
224	return err == nil
225}
226
227// IsValidPublicAccountKey will decode and verify the string is a valid encoded Public Account Key.
228func IsValidPublicAccountKey(src string) bool {
229	_, err := Decode(PrefixByteAccount, []byte(src))
230	return err == nil
231}
232
233// IsValidPublicServerKey will decode and verify the string is a valid encoded Public Server Key.
234func IsValidPublicServerKey(src string) bool {
235	_, err := Decode(PrefixByteServer, []byte(src))
236	return err == nil
237}
238
239// IsValidPublicClusterKey will decode and verify the string is a valid encoded Public Cluster Key.
240func IsValidPublicClusterKey(src string) bool {
241	_, err := Decode(PrefixByteCluster, []byte(src))
242	return err == nil
243}
244
245// IsValidPublicOperatorKey will decode and verify the string is a valid encoded Public Operator Key.
246func IsValidPublicOperatorKey(src string) bool {
247	_, err := Decode(PrefixByteOperator, []byte(src))
248	return err == nil
249}
250
251// checkValidPrefixByte returns an error if the provided value
252// is not one of the defined valid prefix byte constants.
253func checkValidPrefixByte(prefix PrefixByte) error {
254	switch prefix {
255	case PrefixByteOperator, PrefixByteServer, PrefixByteCluster,
256		PrefixByteAccount, PrefixByteUser, PrefixByteSeed, PrefixBytePrivate:
257		return nil
258	}
259	return ErrInvalidPrefixByte
260}
261
262// checkValidPublicPrefixByte returns an error if the provided value
263// is not one of the public defined valid prefix byte constants.
264func checkValidPublicPrefixByte(prefix PrefixByte) error {
265	switch prefix {
266	case PrefixByteServer, PrefixByteCluster, PrefixByteOperator, PrefixByteAccount, PrefixByteUser:
267		return nil
268	}
269	return ErrInvalidPrefixByte
270}
271
272func (p PrefixByte) String() string {
273	switch p {
274	case PrefixByteOperator:
275		return "operator"
276	case PrefixByteServer:
277		return "server"
278	case PrefixByteCluster:
279		return "cluster"
280	case PrefixByteAccount:
281		return "account"
282	case PrefixByteUser:
283		return "user"
284	case PrefixByteSeed:
285		return "seed"
286	case PrefixBytePrivate:
287		return "private"
288	}
289	return "unknown"
290}
291
292// CompatibleKeyPair returns an error if the KeyPair doesn't match expected PrefixByte(s)
293func CompatibleKeyPair(kp KeyPair, expected ...PrefixByte) error {
294	pk, err := kp.PublicKey()
295	if err != nil {
296		return err
297	}
298	pkType := Prefix(pk)
299	for _, k := range expected {
300		if pkType == k {
301			return nil
302		}
303	}
304
305	return ErrIncompatibleKey
306}
307