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
- Variables
- type Skykey
- func (sk *Skykey) CipherKey() (crypto.CipherKey, error)
- func (sk *Skykey) CipherType() crypto.CipherType
- func (sk *Skykey) DeriveSubkey(derivation []byte) (Skykey, error)
- func (sk *Skykey) FromString(s string) error
- func (sk *Skykey) GenerateFileSpecificSubkey() (Skykey, error)
- func (sk *Skykey) GenerateSkyfileEncryptionID() ([SkykeyIDLen]byte, error)
- func (sk Skykey) ID() (keyID SkykeyID)
- func (sk *Skykey) IsValid() error
- func (sk *Skykey) MatchesSkyfileEncryptionID(encryptionID, nonce []byte) (bool, error)
- func (sk *Skykey) Nonce() []byte
- func (sk *Skykey) SubkeyWithNonce(nonce []byte) (Skykey, error)
- func (sk Skykey) ToString() (string, error)
- type SkykeyID
- type SkykeyManager
- func (sm *SkykeyManager) AddKey(sk Skykey) error
- func (sm *SkykeyManager) CreateKey(name string, skykeyType SkykeyType) (Skykey, error)
- func (sm *SkykeyManager) DeleteKeyByID(id SkykeyID) error
- func (sm *SkykeyManager) DeleteKeyByName(name string) error
- func (sm *SkykeyManager) IDByName(name string) (SkykeyID, error)
- func (sm *SkykeyManager) KeyByID(id SkykeyID) (Skykey, error)
- func (sm *SkykeyManager) KeyByName(name string) (Skykey, error)
- func (sm *SkykeyManager) Skykeys() []Skykey
- func (sm *SkykeyManager) SupportsSkykeyType(skykeyType SkykeyType) bool
- type SkykeyType
Constants ¶
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 )
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 ¶
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") )
var ( // SkykeyFileMagic is the first piece of data found in a Skykey file. SkykeyFileMagic = types.NewSpecifier("SkykeyFile") // SkykeyPersistFilename is the name of the skykey persistence file. SkykeyPersistFilename = "skykeys.dat" )
Persistence constants
var ( // ErrNoSkykeysWithThatID indicates that the skykey manager doesn't have a key // with that ID. ErrNoSkykeysWithThatID = errors.New("No Skykey is associated with that ID") // 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") // 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") // ErrNoSkykeysWithThatName indicates that the skykey manager doesn't have // a key with that ID. ErrNoSkykeysWithThatName = errors.New("No Skykey with that name") )
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 ¶ added in v1.4.8
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 ¶ added in v1.4.8
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 ¶ added in v1.4.8
FromString decodes the base64 string into a Skykey.
func (*Skykey) GenerateFileSpecificSubkey ¶ added in v1.4.8
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 ¶ added in v1.5.0
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 ¶
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 ¶ added in v1.4.9
IsValid returns an nil if the skykey is valid and an error otherwise.
func (*Skykey) MatchesSkyfileEncryptionID ¶ added in v1.5.0
MatchesSkyfileEncryptionID returns true if and only if the skykey was the one used with this nonce to create the encryptionID.
func (*Skykey) SubkeyWithNonce ¶ added in v1.4.8
SubkeyWithNonce creates a new subkey with the same key data as this key, but with the given nonce.
type SkykeyID ¶
type SkykeyID [SkykeyIDLen]byte
SkykeyID is the identifier of a skykey.
func (*SkykeyID) FromString ¶ added in v1.4.8
FromString decodes the base64 string into a Skykey ID.
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) DeleteKeyByID ¶ added in v1.5.0
func (sm *SkykeyManager) DeleteKeyByID(id SkykeyID) error
DeleteKeyByID deletes the skykey with the given ID.
func (*SkykeyManager) DeleteKeyByName ¶ added in v1.5.0
func (sm *SkykeyManager) DeleteKeyByName(name string) error
DeleteKeyByName deletes the skykey with the given name.
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 ¶ added in v1.4.9
func (sm *SkykeyManager) Skykeys() []Skykey
Skykeys returns a slice containing each Skykey being stored.
func (*SkykeyManager) SupportsSkykeyType ¶ added in v1.4.9
func (sm *SkykeyManager) SupportsSkykeyType(skykeyType SkykeyType) bool
SupportsSkykeyType returns true if and only if the SkykeyManager supports skykeys with the given type.
type SkykeyType ¶ added in v1.4.9
type SkykeyType byte
SkykeyType encodes the encryption scheme and method used by the Skykey.
func (SkykeyType) CipherType ¶ added in v1.4.9
func (t SkykeyType) CipherType() crypto.CipherType
CipherType returns the crypto.CipherType used by this Skykey.
func (*SkykeyType) FromString ¶ added in v1.4.9
func (t *SkykeyType) FromString(s string) error
FromString reads a SkykeyType from a string.
func (SkykeyType) ToString ¶ added in v1.4.9
func (t SkykeyType) ToString() string
ToString returns the string representation of the ciphertype.