123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- package nkeys
- import (
- "bytes"
- "encoding/base32"
- "encoding/binary"
- "golang.org/x/crypto/ed25519"
- )
- type PrefixByte byte
- const (
-
- PrefixByteSeed PrefixByte = 18 << 3
-
- PrefixBytePrivate PrefixByte = 15 << 3
-
- PrefixByteServer PrefixByte = 13 << 3
-
- PrefixByteCluster PrefixByte = 2 << 3
-
- PrefixByteOperator PrefixByte = 14 << 3
-
- PrefixByteAccount PrefixByte = 0
-
- PrefixByteUser PrefixByte = 20 << 3
-
- PrefixByteUnknown PrefixByte = 23 << 3
- )
- var b32Enc = base32.StdEncoding.WithPadding(base32.NoPadding)
- func Encode(prefix PrefixByte, src []byte) ([]byte, error) {
- if err := checkValidPrefixByte(prefix); err != nil {
- return nil, err
- }
- var raw bytes.Buffer
-
- if err := raw.WriteByte(byte(prefix)); err != nil {
- return nil, err
- }
-
- if _, err := raw.Write(src); err != nil {
- return nil, err
- }
-
- err := binary.Write(&raw, binary.LittleEndian, crc16(raw.Bytes()))
- if err != nil {
- return nil, err
- }
- data := raw.Bytes()
- buf := make([]byte, b32Enc.EncodedLen(len(data)))
- b32Enc.Encode(buf, data)
- return buf[:], nil
- }
- func EncodeSeed(public PrefixByte, src []byte) ([]byte, error) {
- if err := checkValidPublicPrefixByte(public); err != nil {
- return nil, err
- }
- if len(src) != ed25519.SeedSize {
- return nil, ErrInvalidSeedLen
- }
-
-
- b1 := byte(PrefixByteSeed) | (byte(public) >> 5)
- b2 := (byte(public) & 31) << 3
- var raw bytes.Buffer
- raw.WriteByte(b1)
- raw.WriteByte(b2)
-
- if _, err := raw.Write(src); err != nil {
- return nil, err
- }
-
- err := binary.Write(&raw, binary.LittleEndian, crc16(raw.Bytes()))
- if err != nil {
- return nil, err
- }
- data := raw.Bytes()
- buf := make([]byte, b32Enc.EncodedLen(len(data)))
- b32Enc.Encode(buf, data)
- return buf, nil
- }
- func IsValidEncoding(src []byte) bool {
- _, err := decode(src)
- return err == nil
- }
- func decode(src []byte) ([]byte, error) {
- raw := make([]byte, b32Enc.DecodedLen(len(src)))
- n, err := b32Enc.Decode(raw, src)
- if err != nil {
- return nil, err
- }
- raw = raw[:n]
- if len(raw) < 4 {
- return nil, ErrInvalidEncoding
- }
- var crc uint16
- checksum := bytes.NewReader(raw[len(raw)-2:])
- if err := binary.Read(checksum, binary.LittleEndian, &crc); err != nil {
- return nil, err
- }
-
- if err := validate(raw[0:len(raw)-2], crc); err != nil {
- return nil, err
- }
- return raw[:len(raw)-2], nil
- }
- func Decode(expectedPrefix PrefixByte, src []byte) ([]byte, error) {
- if err := checkValidPrefixByte(expectedPrefix); err != nil {
- return nil, err
- }
- raw, err := decode(src)
- if err != nil {
- return nil, err
- }
- if prefix := PrefixByte(raw[0]); prefix != expectedPrefix {
- return nil, ErrInvalidPrefixByte
- }
- return raw[1:], nil
- }
- func DecodeSeed(src []byte) (PrefixByte, []byte, error) {
- raw, err := decode(src)
- if err != nil {
- return PrefixByteSeed, nil, err
- }
-
- b1 := raw[0] & 248
- b2 := (raw[0]&7)<<5 | ((raw[1] & 248) >> 3)
- if PrefixByte(b1) != PrefixByteSeed {
- return PrefixByteSeed, nil, ErrInvalidSeed
- }
- if checkValidPublicPrefixByte(PrefixByte(b2)) != nil {
- return PrefixByteSeed, nil, ErrInvalidSeed
- }
- return PrefixByte(b2), raw[2:], nil
- }
- func Prefix(src string) PrefixByte {
- b, err := decode([]byte(src))
- if err != nil {
- return PrefixByteUnknown
- }
- prefix := PrefixByte(b[0])
- err = checkValidPrefixByte(prefix)
- if err == nil {
- return prefix
- }
-
- b1 := b[0] & 248
- if PrefixByte(b1) == PrefixByteSeed {
- return PrefixByteSeed
- }
- return PrefixByteUnknown
- }
- func IsValidPublicKey(src string) bool {
- b, err := decode([]byte(src))
- if err != nil {
- return false
- }
- if prefix := PrefixByte(b[0]); checkValidPublicPrefixByte(prefix) != nil {
- return false
- }
- return true
- }
- func IsValidPublicUserKey(src string) bool {
- _, err := Decode(PrefixByteUser, []byte(src))
- return err == nil
- }
- func IsValidPublicAccountKey(src string) bool {
- _, err := Decode(PrefixByteAccount, []byte(src))
- return err == nil
- }
- func IsValidPublicServerKey(src string) bool {
- _, err := Decode(PrefixByteServer, []byte(src))
- return err == nil
- }
- func IsValidPublicClusterKey(src string) bool {
- _, err := Decode(PrefixByteCluster, []byte(src))
- return err == nil
- }
- func IsValidPublicOperatorKey(src string) bool {
- _, err := Decode(PrefixByteOperator, []byte(src))
- return err == nil
- }
- func checkValidPrefixByte(prefix PrefixByte) error {
- switch prefix {
- case PrefixByteOperator, PrefixByteServer, PrefixByteCluster,
- PrefixByteAccount, PrefixByteUser, PrefixByteSeed, PrefixBytePrivate:
- return nil
- }
- return ErrInvalidPrefixByte
- }
- func checkValidPublicPrefixByte(prefix PrefixByte) error {
- switch prefix {
- case PrefixByteServer, PrefixByteCluster, PrefixByteOperator, PrefixByteAccount, PrefixByteUser:
- return nil
- }
- return ErrInvalidPrefixByte
- }
- func (p PrefixByte) String() string {
- switch p {
- case PrefixByteOperator:
- return "operator"
- case PrefixByteServer:
- return "server"
- case PrefixByteCluster:
- return "cluster"
- case PrefixByteAccount:
- return "account"
- case PrefixByteUser:
- return "user"
- case PrefixByteSeed:
- return "seed"
- case PrefixBytePrivate:
- return "private"
- }
- return "unknown"
- }
- func CompatibleKeyPair(kp KeyPair, expected ...PrefixByte) error {
- pk, err := kp.PublicKey()
- if err != nil {
- return err
- }
- pkType := Prefix(pk)
- for _, k := range expected {
- if pkType == k {
- return nil
- }
- }
- return ErrIncompatibleKey
- }
|