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