77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
// sas provides the means to do SAS between keys
|
|
package sas
|
|
|
|
import (
|
|
"io"
|
|
|
|
"maunium.net/go/mautrix/crypto/goolm"
|
|
"maunium.net/go/mautrix/crypto/goolm/crypto"
|
|
)
|
|
|
|
// SAS contains the key pair and secret for SAS.
|
|
type SAS struct {
|
|
KeyPair crypto.Curve25519KeyPair
|
|
Secret []byte
|
|
}
|
|
|
|
// New creates a new SAS with a new key pair.
|
|
func New() (*SAS, error) {
|
|
kp, err := crypto.Curve25519GenerateKey(nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s := &SAS{
|
|
KeyPair: kp,
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// GetPubkey returns the public key of the key pair base64 encoded
|
|
func (s SAS) GetPubkey() []byte {
|
|
return goolm.Base64Encode(s.KeyPair.PublicKey)
|
|
}
|
|
|
|
// SetTheirKey sets the key of the other party and computes the shared secret.
|
|
func (s *SAS) SetTheirKey(key []byte) error {
|
|
keyDecoded, err := goolm.Base64Decode(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sharedSecret, err := s.KeyPair.SharedSecret(keyDecoded)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.Secret = sharedSecret
|
|
return nil
|
|
}
|
|
|
|
// GenerateBytes creates length bytes from the shared secret and info.
|
|
func (s SAS) GenerateBytes(info []byte, length uint) ([]byte, error) {
|
|
byteReader := crypto.HKDFSHA256(s.Secret, nil, info)
|
|
output := make([]byte, length)
|
|
if _, err := io.ReadFull(byteReader, output); err != nil {
|
|
return nil, err
|
|
}
|
|
return output, nil
|
|
}
|
|
|
|
// calculateMAC returns a base64 encoded MAC of input.
|
|
func (s *SAS) calculateMAC(input, info []byte, length uint) ([]byte, error) {
|
|
key, err := s.GenerateBytes(info, length)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mac := crypto.HMACSHA256(key, input)
|
|
return goolm.Base64Encode(mac), nil
|
|
}
|
|
|
|
// CalculateMACFixes returns a base64 encoded, 32 byte long MAC of input.
|
|
func (s SAS) CalculateMAC(input, info []byte) ([]byte, error) {
|
|
return s.calculateMAC(input, info, 32)
|
|
}
|
|
|
|
// CalculateMACLongKDF returns a base64 encoded, 256 byte long MAC of input.
|
|
func (s SAS) CalculateMACLongKDF(input, info []byte) ([]byte, error) {
|
|
return s.calculateMAC(input, info, 256)
|
|
}
|