skykey

package
v1.4.13 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2021 License: MIT Imports: 15 Imported by: 0

README

Skykey Manager

The skykey package defines Skykeys used for encrypting files in Skynet and provides a way to persist Skykeys using a SkykeyManager that manages these keys in a file on-disk.

The file consists of a header which is: SkykeyFileMagic | SkykeyVersion | Length

The SkykeyFileMagic never changes. The version only changes when backwards-incompatible changes are made to the design of Skykeys or to the way this file is structured. The length refers to the number of bytes in the file.

When adding a Skykey to the file, a Skykey is unmarshaled and appended to the end of the file and the file is then synced. Then the length field in the header is updated to indicate the newly written bytes and the file is synced once again.

Skykeys

A Skykey is a key associated with a name to be used in Skynet to share encrypted files. Each key has a name and a unique identifier.

The Skykey format is one byte called the SkykeyType followed by rest of the data associated with that key.

Types

TypeInvalid represents an unusable, invalid key.

TypePublicID represents a skykey that uses the XChaCha20 cipher schemes and is currently used for encrypting skyfiles. In skyfile encryption the key ID is revealed in plaintext, therefore its name is TypePublicID Implicitly, this specifies the entropy length as the length of a key and nonce in that scheme. Its byte representation is 1 type byte and 56 entropy bytes.

TypePrivateID represents a skykey that uses the XChaCha20 cipher schemes and is can be used for encrypting skyfiles. Implicitly, this specifies the entropy length as the length of a key and nonce in that scheme. Its byte representation is 1 type byte and 56 entropy bytes. When used for skyfile encryption, the key ID is never revealed. Instead the Skykey is used to derive a file-specific key, which is then used to encrypt a known identifier. This means that without knowledge of the Skykey, you cannot tell which Skykeys were used for which skyfile and cannot even group together skyfiles encrypted with the same TypePrivateID Skykey. If you do have the Skykey, you can verify that fact by decrypting the identifier and checking against the known plaintext.

Encoding

Skykeys are meant to be shared using the string format which is a URI encoding with the optional skykey:" scheme and an optional name parameter including the skykey name. The key data (type and entropy) is stored as the base64-encoded path.

Some examples of valid encodings below:

  • (No URI scheme and no name): AT7-P751d_SEBhXvbOQTfswB62n2mqMe0Q89cQ911KGeuTIV2ci6GjG3Aj5CuVZUDS6hkG7pHXXZ
  • (No name): skykey:AT7-P751d_SEBhXvbOQTfswB62n2mqMe0Q89cQ911KGeuTIV2ci6GjG3Aj5CuVZUDS6hkG7pHXXZ
  • (No URI scheme): AT7-P751d_SEBhXvbOQTfswB62n2mqMe0Q89cQ911KGeuTIV2ci6GjG3Aj5CuVZUDS6hkG7pHXXZ?name=ExampleKey
  • (Includes URI scheme and name): skykey:AT7-P751d_SEBhXvbOQTfswB62n2mqMe0Q89cQ911KGeuTIV2ci6GjG3Aj5CuVZUDS6hkG7pHXXZ?name=ExampleKey

It is recommended that users include the URI scheme for maximum clarity, but the FromString method will be accept any strings of the above forms.

Usage

Skykeys are primarily used for encrypting skyfiles. Currently all skykeys are used with the XChaCha20 stream cipher. Key re-use is safe with this encryption scheme if we use random nonces for each message. This is safe until 2 << 96 messages are transmitted.

Key Derivation

The skykey manager stores only master skykeys. These skykeys are not used directly for encryption/decryption. Rather they are used to derive file-specific Skykeys. File-specific skykeys share the same key material as the master skykey they are derived from. They differ in the nonce value. This allows us to reuse the master skykey for multiple files, by using a new file-specific skykey for every new file.

The method GenerateFileSpecificSubkey is used to create new file-specific sub-keys from a master skykey.

Further levels of key derivation may be necessary and are supported by using the DeriveSubkey method.

Skyfile encryption

Two other types of subkeys are the ones actually used for encrypting skyfiles. There is a BaseSector derivation and a Fanout derivation which are used for encrypting the base sector and fanout of a skyfile respectively.

This is necessary because of the final level of key derivation used in the upload process of Sia. When splitting up files for redundancy, each (chunkIndex, pieceIndex) upload uses a different XChaCha20 nonce as well. To avoid re-using the same (chunkIndex, pieceIndex) derivation for the base sector and fanout sections, we just use a different nonce for each.

Documentation

Index

Constants

View Source
const (
	// SkykeyScheme is the URI scheme for encoded skykeys.
	SkykeyScheme = "skykey"

	// SkykeyIDLen is the length of a SkykeyID
	SkykeyIDLen = 16

	// MaxKeyNameLen is the maximum length of a skykey's name.
	MaxKeyNameLen = 128
)
View Source
const (
	// TypeInvalid represents an invalid skykey type.
	TypeInvalid = SkykeyType(0x00)

	// TypePublicID is a Skykey that uses XChaCha20. It reveals its
	// skykey ID in *every* skyfile it encrypts.
	TypePublicID = SkykeyType(0x01)

	// TypePrivateID is a Skykey that uses XChaCha20 that does not
	// reveal its skykey ID when encrypting Skyfiles. Instead, it marks the skykey
	// used for encryption by storing an encrypted identifier that can only be
	// successfully decrypted with the correct skykey.
	TypePrivateID = SkykeyType(0x02)
)

Define SkykeyTypes. Constants stated explicitly (instead of `SkykeyType(iota)`) to avoid re-ordering mistakes in the future.

Variables

View Source
var (
	// SkykeySpecifier is used as a prefix when hashing Skykeys to compute their
	// ID.
	SkykeySpecifier = types.NewSpecifier("Skykey")

	// ErrInvalidSkykeyType is returned when an invalid SkykeyType is being used.
	ErrInvalidSkykeyType = errors.New("Invalid skykey type")
)
View Source
var (

	// SkykeyFileMagic is the first piece of data found in a Skykey file.
	SkykeyFileMagic = types.NewSpecifier("SkykeyFile")

	// ErrSkykeyWithNameAlreadyExists indicates that a key cannot be created or added
	// because a key with the same name is already being stored.
	ErrSkykeyWithNameAlreadyExists = errors.New("Skykey name already used by another key.")

	// ErrSkykeyWithIDAlreadyExists indicates that a key cannot be created or
	// added because a key with the same ID (and therefore same key entropy) is
	// already being stored.
	ErrSkykeyWithIDAlreadyExists = errors.New("Skykey ID already exists.")

	// ErrNoSkykeysWithThatID indicates that the skykey manager doesn't have a key
	// with that ID.
	ErrNoSkykeysWithThatID = errors.New("No Skykey is associated with that ID")

	// SkykeyPersistFilename is the name of the skykey persistence file.
	SkykeyPersistFilename = "skykeys.dat"
)

Functions

This section is empty.

Types

type Skykey

type Skykey struct {
	Name    string
	Type    SkykeyType
	Entropy []byte
}

Skykey is a key used to encrypt/decrypt skyfiles.

func (*Skykey) CipherKey

func (sk *Skykey) CipherKey() (crypto.CipherKey, error)

CipherKey returns the crypto.CipherKey equivalent of this Skykey.

func (*Skykey) CipherType

func (sk *Skykey) CipherType() crypto.CipherType

CipherType returns the crypto.CipherType used by this Skykey.

func (*Skykey) DeriveSubkey

func (sk *Skykey) DeriveSubkey(derivation []byte) (Skykey, error)

DeriveSubkey is used to create Skykeys with the same key, but with a different nonce. This is used to create file-specific keys, and separate keys for Skyfile baseSector uploads and fanout uploads.

func (*Skykey) FromString

func (sk *Skykey) FromString(s string) error

FromString decodes the base64 string into a Skykey.

func (*Skykey) GenerateFileSpecificSubkey

func (sk *Skykey) GenerateFileSpecificSubkey() (Skykey, error)

GenerateFileSpecificSubkey creates a new subkey specific to a certain file being uploaded/downloaded. Skykeys can only be used once with a given nonce, so this method is used to generate keys with new nonces when a new file is uploaded.

func (*Skykey) GenerateSkyfileEncryptionID

func (sk *Skykey) GenerateSkyfileEncryptionID() ([SkykeyIDLen]byte, error)

GenerateSkyfileEncryptionID creates an encrypted identifier that is used for PrivateID encrypted files. NOTE: This method MUST only be called using a FileSpecificSkykey.

func (Skykey) ID

func (sk Skykey) ID() (keyID SkykeyID)

ID returns the ID for the Skykey. A master Skykey and all file-specific skykeys derived from it share the same ID because they only differ in nonce values, not key values. This fact is used to identify the master Skykey with which a Skyfile was encrypted.

func (*Skykey) IsValid

func (sk *Skykey) IsValid() error

IsValid returns an nil if the skykey is valid and an error otherwise.

func (*Skykey) MatchesSkyfileEncryptionID

func (sk *Skykey) MatchesSkyfileEncryptionID(encryptionID, nonce []byte) (bool, error)

MatchesSkyfileEncryptionID returns true if and only if the skykey was the one used with this nonce to create the encryptionID.

func (*Skykey) Nonce

func (sk *Skykey) Nonce() []byte

Nonce returns the nonce of this Skykey.

func (*Skykey) SubkeyWithNonce

func (sk *Skykey) SubkeyWithNonce(nonce []byte) (Skykey, error)

SubkeyWithNonce creates a new subkey with the same key data as this key, but with the given nonce.

func (Skykey) ToString

func (sk Skykey) ToString() (string, error)

ToString encodes the Skykey as a base64 string.

type SkykeyID

type SkykeyID [SkykeyIDLen]byte

SkykeyID is the identifier of a skykey.

func (*SkykeyID) FromString

func (id *SkykeyID) FromString(s string) error

FromString decodes the base64 string into a Skykey ID.

func (SkykeyID) ToString

func (id SkykeyID) ToString() string

ToString encodes the SkykeyID as a base64 string.

type SkykeyManager

type SkykeyManager struct {
	// contains filtered or unexported fields
}

SkykeyManager manages the creation and handling of new skykeys which can be referenced by their unique name or identifier.

func NewSkykeyManager

func NewSkykeyManager(persistDir string) (*SkykeyManager, error)

NewSkykeyManager creates a SkykeyManager for managing skykeys.

func (*SkykeyManager) AddKey

func (sm *SkykeyManager) AddKey(sk Skykey) error

AddKey adds the given Skykey to the skykey manager.

func (*SkykeyManager) CreateKey

func (sm *SkykeyManager) CreateKey(name string, skykeyType SkykeyType) (Skykey, error)

CreateKey creates a new Skykey under the given name and SkykeyType.

func (*SkykeyManager) IDByName

func (sm *SkykeyManager) IDByName(name string) (SkykeyID, error)

IDByName returns the ID associated with the given key name.

func (*SkykeyManager) KeyByID

func (sm *SkykeyManager) KeyByID(id SkykeyID) (Skykey, error)

KeyByID returns the Skykey associated with that ID.

func (*SkykeyManager) KeyByName

func (sm *SkykeyManager) KeyByName(name string) (Skykey, error)

KeyByName returns the Skykey associated with that key name.

func (*SkykeyManager) Skykeys

func (sm *SkykeyManager) Skykeys() []Skykey

Skykeys returns a slice containing each Skykey being stored.

func (*SkykeyManager) SupportsSkykeyType

func (sm *SkykeyManager) SupportsSkykeyType(skykeyType SkykeyType) bool

SupportsSkykeyType returns true if and only if the SkykeyManager supports skykeys with the given type.

type SkykeyType

type SkykeyType byte

SkykeyType encodes the encryption scheme and method used by the Skykey.

func (SkykeyType) CipherType

func (t SkykeyType) CipherType() crypto.CipherType

CipherType returns the crypto.CipherType used by this Skykey.

func (*SkykeyType) FromString

func (t *SkykeyType) FromString(s string) error

FromString reads a SkykeyType from a string.

func (SkykeyType) ToString

func (t SkykeyType) ToString() string

ToString returns the string representation of the ciphertype.

Jump to

Keyboard shortcuts

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