diff options
Diffstat (limited to 'vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go')
-rw-r--r-- | vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go b/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go new file mode 100644 index 00000000..0a5125df --- /dev/null +++ b/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go @@ -0,0 +1,127 @@ +// Package chain provides chain keys used in double ratchet sessions. +package chain + +import ( + "crypto/hmac" + "crypto/sha256" + "go.mau.fi/libsignal/kdf" + "go.mau.fi/libsignal/keys/message" +) + +var messageKeySeed = []byte{0x01} +var chainKeySeed = []byte{0x02} + +// NewKey returns a new chain key with the given kdf, key, and index +func NewKey(kdf kdf.HKDF, key []byte, index uint32) *Key { + chainKey := Key{ + kdf: kdf, + key: key, + index: index, + } + + return &chainKey +} + +// NewKeyFromStruct will return a chain key built from the given structure. +func NewKeyFromStruct(structure *KeyStructure, kdf kdf.HKDF) *Key { + return NewKey( + kdf, + structure.Key, + structure.Index, + ) +} + +// NewStructFromKey will return a chain key structure for serialization. +func NewStructFromKey(key *Key) *KeyStructure { + return &KeyStructure{ + Key: key.key, + Index: key.index, + } +} + +// KeyStructure is a serializeable structure for chain keys. +type KeyStructure struct { + Key []byte + Index uint32 +} + +// Key is used for generating message keys. This key "ratchets" every time a +// message key is generated. Every time the chain key ratchets forward, its index +// increases by one. +type Key struct { + kdf kdf.HKDF + key []byte + index uint32 // Index's maximum size: 4,294,967,295 +} + +// Current returns the current ChainKey struct. +func (c *Key) Current() *Key { + return c +} + +// Key returns the ChainKey's key material. +func (c *Key) Key() []byte { + return c.key +} + +// SetKey will set the ChainKey's key material. +func (c *Key) SetKey(key []byte) { + c.key = key +} + +// Index returns how many times the ChainKey has been "ratcheted" forward. +func (c *Key) Index() uint32 { + return c.index +} + +// SetIndex sets how many times the ChainKey has been "ratcheted" forward. +func (c *Key) SetIndex(index uint32) { + c.index = index +} + +// NextKey uses the key derivation function to generate a new ChainKey. +func (c *Key) NextKey() *Key { + nextKey := c.BaseMaterial(chainKeySeed) + return NewKey(c.kdf, nextKey, c.index+1) +} + +// MessageKeys returns message keys, which includes the cipherkey, mac, iv, and index. +func (c *Key) MessageKeys() *message.Keys { + inputKeyMaterial := c.BaseMaterial(messageKeySeed) + keyMaterialBytes, _ := c.kdf(inputKeyMaterial, nil, []byte(message.KdfSalt), message.DerivedSecretsSize) + keyMaterial := newKeyMaterial(keyMaterialBytes) + + // Use the key material returned from the key derivation function for our cipherkey, mac, and iv. + messageKeys := message.NewKeys( + keyMaterial.CipherKey, // Use the first 32 bytes of the key material for the CipherKey + keyMaterial.MacKey, // Use bytes 32-64 of the key material for the MacKey + keyMaterial.IV, // Use the last 16 bytes for the IV. + c.Index(), // Attach the chain key's index to the message keys. + ) + + return messageKeys +} + +// BaseMaterial uses hmac to derive the base material used in the key derivation function for a new key. +func (c *Key) BaseMaterial(seed []byte) []byte { + mac := hmac.New(sha256.New, c.key[:]) + mac.Write(seed) + + return mac.Sum(nil) +} + +// NewKeyMaterial takes an 80-byte slice derived from a key derivation function and splits +// it into the cipherkey, mac, and iv. +func newKeyMaterial(keyMaterialBytes []byte) *kdf.KeyMaterial { + cipherKey := keyMaterialBytes[:32] // Use the first 32 bytes of the key material for the CipherKey + macKey := keyMaterialBytes[32:64] // Use bytes 32-64 of the key material for the MacKey + iv := keyMaterialBytes[64:80] // Use the last 16 bytes for the IV. + + keyMaterial := kdf.KeyMaterial{ + CipherKey: cipherKey, + MacKey: macKey, + IV: iv, + } + + return &keyMaterial +} |