nkeys

package module
v0.4.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2023 License: Apache-2.0 Imports: 10 Imported by: 138

README

NKEYS

License Apache 2 Go Report Card Build Status GoDoc Coverage Status

A public-key signature system based on Ed25519 for the NATS ecosystem.

About

The NATS ecosystem will be moving to Ed25519 keys for identity, authentication and authorization for entities such as Accounts, Users, Servers and Clusters.

Ed25519 is fast and resistant to side channel attacks. Generation of a seed key is all that is needed to be stored and kept safe, as the seed can generate both the public and private keys.

The NATS system will utilize Ed25519 keys, meaning that NATS systems will never store or even have access to any private keys. Authentication will utilize a random challenge response mechanism.

Dealing with 32 byte and 64 byte raw keys can be challenging. NKEYS is designed to formulate keys in a much friendlier fashion and references work done in cryptocurrencies, specifically Stellar. Bitcoin and others used a form of Base58 (or Base58Check) to encode raw keys. Stellar utilized a more traditional Base32 with a CRC16 and a version or prefix byte. NKEYS utilizes a similar format where the prefix will be 1 byte for public and private keys and will be 2 bytes for seeds. The base32 encoding of these prefixes will yield friendly human readable prefixes, e.g. 'N' = server, 'C' = cluster, 'O' = operator, 'A' = account, and 'U' = user. 'P' is used for private keys. For seeds, the first encoded prefix is 'S', and the second character will be the type for the public key, e.g. "SU" is a seed for a user key pair, "SA" is a seed for an account key pair.

Installation

Use the go command:

$ go get github.com/nats-io/nkeys

nk - Command Line Utility

Located under the nk directory.

Basic API Usage


// Create a new User KeyPair
user, _ := nkeys.CreateUser()

// Sign some data with a full key pair user.
data := []byte("Hello World")
sig, _ := user.Sign(data)

// Verify the signature.
err = user.Verify(data, sig)

// Access the seed, the only thing that needs to be stored and kept safe.
// seed = "SUAKYRHVIOREXV7EUZTBHUHL7NUMHPMAS7QMDU3GTIUWEI5LDNOXD43IZY"
seed, _ := user.Seed()

// Access the public key which can be shared.
// publicKey = "UD466L6EBCM3YY5HEGHJANNTN4LSKTSUXTH7RILHCKEQMQHTBNLHJJXT"
publicKey, _ := user.PublicKey()

// Create a full User who can sign and verify from a private seed.
user, _ = nkeys.FromSeed(seed)

// Create a User who can only verify signatures via a public key.
user, _ = nkeys.FromPublicKey(publicKey)

// Create a User KeyPair with our own random data.
var rawSeed [32]byte
_, err := io.ReadFull(rand.Reader, rawSeed[:])  // Or some other random source.
user2, _ := nkeys.FromRawSeed(PrefixByteUser, rawSeed)

License

Unless otherwise noted, the NATS source files are distributed under the Apache Version 2.0 license found in the LICENSE file.

Documentation

Overview

Package nkeys is an Ed25519 based public-key signature system that simplifies keys and seeds and performs signing and verification. It also supports encryption via x25519 keys and is compatible with https://pkg.go.dev/golang.org/x/crypto/nacl/box.

Index

Constants

View Source
const (
	ErrInvalidPrefixByte        = nkeysError("nkeys: invalid prefix byte")
	ErrInvalidKey               = nkeysError("nkeys: invalid key")
	ErrInvalidPublicKey         = nkeysError("nkeys: invalid public key")
	ErrInvalidPrivateKey        = nkeysError("nkeys: invalid private key")
	ErrInvalidSeedLen           = nkeysError("nkeys: invalid seed length")
	ErrInvalidSeed              = nkeysError("nkeys: invalid seed")
	ErrInvalidEncoding          = nkeysError("nkeys: invalid encoded key")
	ErrInvalidSignature         = nkeysError("nkeys: signature verification failed")
	ErrCannotSign               = nkeysError("nkeys: can not sign, no private key available")
	ErrPublicKeyOnly            = nkeysError("nkeys: no seed or private key available")
	ErrIncompatibleKey          = nkeysError("nkeys: incompatible key")
	ErrInvalidChecksum          = nkeysError("nkeys: invalid checksum")
	ErrNoSeedFound              = nkeysError("nkeys: no nkey seed found")
	ErrInvalidNkeySeed          = nkeysError("nkeys: doesn't contain a seed nkey")
	ErrInvalidUserSeed          = nkeysError("nkeys: doesn't contain an user seed nkey")
	ErrInvalidRecipient         = nkeysError("nkeys: not a valid recipient public curve key")
	ErrInvalidSender            = nkeysError("nkeys: not a valid sender public curve key")
	ErrInvalidCurveKey          = nkeysError("nkeys: not a valid curve key")
	ErrInvalidCurveSeed         = nkeysError("nkeys: not a valid curve seed")
	ErrInvalidEncrypted         = nkeysError("nkeys: encrypted input is not valid")
	ErrInvalidEncVersion        = nkeysError("nkeys: encrypted input wrong version")
	ErrCouldNotDecrypt          = nkeysError("nkeys: could not decrypt input")
	ErrInvalidCurveKeyOperation = nkeysError("nkeys: curve key is not valid for sign/verify")
	ErrInvalidNKeyOperation     = nkeysError("nkeys: only curve key can seal/open")
	ErrCannotOpen               = nkeysError("nkeys: cannot open no private curve key available")
	ErrCannotSeal               = nkeysError("nkeys: cannot seal no private curve key available")
)

Errors

View Source
const Version = "0.4.7"

Version is our current version

View Source
const XKeyVersionV1 = "xkv1"

Only version for now, but could add in X3DH in the future, etc.

Variables

This section is empty.

Functions

func CompatibleKeyPair added in v0.1.2

func CompatibleKeyPair(kp KeyPair, expected ...PrefixByte) error

CompatibleKeyPair returns an error if the KeyPair doesn't match expected PrefixByte(s)

func Decode

func Decode(expectedPrefix PrefixByte, src []byte) ([]byte, error)

Decode will decode the base32 string and check crc16 and enforce the prefix is what is expected.

func Encode

func Encode(prefix PrefixByte, src []byte) ([]byte, error)

Encode will encode a raw key or seed with the prefix and crc16 and then base32 encoded.

func EncodeSeed

func EncodeSeed(public PrefixByte, src []byte) ([]byte, error)

EncodeSeed will encode a raw key with the prefix and then seed prefix and crc16 and then base32 encoded. `src` must be 32 bytes long (ed25519.SeedSize).

func IsValidEncoding

func IsValidEncoding(src []byte) bool

IsValidEncoding will tell you if the encoding is a valid key.

func IsValidPublicAccountKey

func IsValidPublicAccountKey(src string) bool

IsValidPublicAccountKey will decode and verify the string is a valid encoded Public Account Key.

func IsValidPublicClusterKey

func IsValidPublicClusterKey(src string) bool

IsValidPublicClusterKey will decode and verify the string is a valid encoded Public Cluster Key.

func IsValidPublicCurveKey added in v0.4.0

func IsValidPublicCurveKey(src string) bool

IsValidPublicCurveKey will decode and verify the string is a valid encoded Public Curve Key.

func IsValidPublicKey

func IsValidPublicKey(src string) bool

IsValidPublicKey will decode and verify that the string is a valid encoded public key.

func IsValidPublicOperatorKey

func IsValidPublicOperatorKey(src string) bool

IsValidPublicOperatorKey will decode and verify the string is a valid encoded Public Operator Key.

func IsValidPublicServerKey

func IsValidPublicServerKey(src string) bool

IsValidPublicServerKey will decode and verify the string is a valid encoded Public Server Key.

func IsValidPublicUserKey

func IsValidPublicUserKey(src string) bool

IsValidPublicUserKey will decode and verify the string is a valid encoded Public User Key.

func ParseDecoratedJWT added in v0.2.0

func ParseDecoratedJWT(contents []byte) (string, error)

ParseDecoratedJWT takes a creds file and returns the JWT portion.

Types

type KeyPair

type KeyPair interface {
	Seed() ([]byte, error)
	PublicKey() (string, error)
	PrivateKey() ([]byte, error)
	// Sign is only supported on Non CurveKeyPairs
	Sign(input []byte) ([]byte, error)
	// Verify is only supported on Non CurveKeyPairs
	Verify(input []byte, sig []byte) error
	Wipe()
	// Seal is only supported on CurveKeyPair
	Seal(input []byte, recipient string) ([]byte, error)
	// SealWithRand is only supported on CurveKeyPair
	SealWithRand(input []byte, recipient string, rr io.Reader) ([]byte, error)
	// Open is only supported on CurveKey
	Open(input []byte, sender string) ([]byte, error)
}

KeyPair provides the central interface to nkeys.

func CreateAccount

func CreateAccount() (KeyPair, error)

CreateAccount will create an Account typed KeyPair.

func CreateCluster

func CreateCluster() (KeyPair, error)

CreateCluster will create a Cluster typed KeyPair.

func CreateCurveKeys added in v0.4.0

func CreateCurveKeys() (KeyPair, error)

CreateCurveKeys will create a Curve typed KeyPair.

func CreateCurveKeysWithRand added in v0.4.0

func CreateCurveKeysWithRand(rr io.Reader) (KeyPair, error)

CreateCurveKeysWithRand will create a Curve typed KeyPair with specified rand source.

func CreateOperator

func CreateOperator() (KeyPair, error)

CreateOperator will create an Operator typed KeyPair.

func CreatePair

func CreatePair(prefix PrefixByte) (KeyPair, error)

CreatePair will create a KeyPair based on the rand entropy and a type/prefix byte.

func CreatePairWithRand added in v0.4.0

func CreatePairWithRand(prefix PrefixByte, rr io.Reader) (KeyPair, error)

CreatePair will create a KeyPair based on the rand reader and a type/prefix byte. rand can be nil.

func CreateServer

func CreateServer() (KeyPair, error)

CreateServer will create a Server typed KeyPair.

func CreateUser

func CreateUser() (KeyPair, error)

CreateUser will create a User typed KeyPair.

func FromCurveSeed added in v0.4.0

func FromCurveSeed(seed []byte) (KeyPair, error)

Will create a curve key pair from seed.

func FromPublicKey

func FromPublicKey(public string) (KeyPair, error)

FromPublicKey will create a KeyPair capable of verifying signatures.

func FromRawSeed

func FromRawSeed(prefix PrefixByte, rawSeed []byte) (KeyPair, error)

FromRawSeed will create a KeyPair from the raw 32 byte seed for a given type.

func FromSeed

func FromSeed(seed []byte) (KeyPair, error)

FromSeed will create a KeyPair capable of signing and verifying signatures.

func ParseDecoratedNKey added in v0.2.0

func ParseDecoratedNKey(contents []byte) (KeyPair, error)

ParseDecoratedNKey takes a creds file, finds the NKey portion and creates a key pair from it.

func ParseDecoratedUserNKey added in v0.2.0

func ParseDecoratedUserNKey(contents []byte) (KeyPair, error)

ParseDecoratedUserNKey takes a creds file, finds the NKey portion and creates a key pair from it. Similar to ParseDecoratedNKey but fails for non-user keys.

type PrefixByte

type PrefixByte byte

PrefixByte is a lead byte representing the type.

const (
	// PrefixByteSeed is the version byte used for encoded NATS Seeds
	PrefixByteSeed PrefixByte = 18 << 3 // Base32-encodes to 'S...'

	// PrefixBytePrivate is the version byte used for encoded NATS Private keys
	PrefixBytePrivate PrefixByte = 15 << 3 // Base32-encodes to 'P...'

	// PrefixByteServer is the version byte used for encoded NATS Servers
	PrefixByteServer PrefixByte = 13 << 3 // Base32-encodes to 'N...'

	// PrefixByteCluster is the version byte used for encoded NATS Clusters
	PrefixByteCluster PrefixByte = 2 << 3 // Base32-encodes to 'C...'

	// PrefixByteOperator is the version byte used for encoded NATS Operators
	PrefixByteOperator PrefixByte = 14 << 3 // Base32-encodes to 'O...'

	// PrefixByteAccount is the version byte used for encoded NATS Accounts
	PrefixByteAccount PrefixByte = 0 // Base32-encodes to 'A...'

	// PrefixByteUser is the version byte used for encoded NATS Users
	PrefixByteUser PrefixByte = 20 << 3 // Base32-encodes to 'U...'

	// PrefixByteCurve is the version byte used for encoded CurveKeys (X25519)
	PrefixByteCurve PrefixByte = 23 << 3 // Base32-encodes to 'X...'

	// PrefixByteUnknown is for unknown prefixes.
	PrefixByteUnknown PrefixByte = 25 << 3 // Base32-encodes to 'Z...'
)

func DecodeSeed

func DecodeSeed(src []byte) (PrefixByte, []byte, error)

DecodeSeed will decode the base32 string and check crc16 and enforce the prefix is a seed and the subsequent type is a valid type.

func Prefix

func Prefix(src string) PrefixByte

Prefix returns PrefixBytes of its input

func (PrefixByte) String

func (p PrefixByte) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL