refactor to mautrix 0.17.x; update deps

This commit is contained in:
Aine
2024-02-11 20:47:04 +02:00
parent 0a9701f4c9
commit dd0ad4c245
237 changed files with 9091 additions and 3317 deletions

View File

@@ -0,0 +1,96 @@
package cipher
import (
"bytes"
"io"
"maunium.net/go/mautrix/crypto/goolm/crypto"
)
// derivedAESKeys stores the derived keys for the AESSHA256 cipher
type derivedAESKeys struct {
key []byte
hmacKey []byte
iv []byte
}
// deriveAESKeys derives three keys for the AESSHA256 cipher
func deriveAESKeys(kdfInfo []byte, key []byte) (*derivedAESKeys, error) {
hkdf := crypto.HKDFSHA256(key, nil, kdfInfo)
keys := &derivedAESKeys{
key: make([]byte, 32),
hmacKey: make([]byte, 32),
iv: make([]byte, 16),
}
if _, err := io.ReadFull(hkdf, keys.key); err != nil {
return nil, err
}
if _, err := io.ReadFull(hkdf, keys.hmacKey); err != nil {
return nil, err
}
if _, err := io.ReadFull(hkdf, keys.iv); err != nil {
return nil, err
}
return keys, nil
}
// AESSha512BlockSize resturns the blocksize of the cipher AESSHA256.
func AESSha512BlockSize() int {
return crypto.AESCBCBlocksize()
}
// AESSHA256 is a valid cipher using AES with CBC and HKDFSha256.
type AESSHA256 struct {
kdfInfo []byte
}
// NewAESSHA256 returns a new AESSHA256 cipher with the key derive function info (kdfInfo).
func NewAESSHA256(kdfInfo []byte) *AESSHA256 {
return &AESSHA256{
kdfInfo: kdfInfo,
}
}
// Encrypt encrypts the plaintext with the key. The key is used to derive the actual encryption key (32 bytes) as well as the iv (16 bytes).
func (c AESSHA256) Encrypt(key, plaintext []byte) (ciphertext []byte, err error) {
keys, err := deriveAESKeys(c.kdfInfo, key)
if err != nil {
return nil, err
}
ciphertext, err = crypto.AESCBCEncrypt(keys.key, keys.iv, plaintext)
if err != nil {
return nil, err
}
return ciphertext, nil
}
// Decrypt decrypts the ciphertext with the key. The key is used to derive the actual encryption key (32 bytes) as well as the iv (16 bytes).
func (c AESSHA256) Decrypt(key, ciphertext []byte) (plaintext []byte, err error) {
keys, err := deriveAESKeys(c.kdfInfo, key)
if err != nil {
return nil, err
}
plaintext, err = crypto.AESCBCDecrypt(keys.key, keys.iv, ciphertext)
if err != nil {
return nil, err
}
return plaintext, nil
}
// MAC returns the MAC for the message using the key. The key is used to derive the actual mac key (32 bytes).
func (c AESSHA256) MAC(key, message []byte) ([]byte, error) {
keys, err := deriveAESKeys(c.kdfInfo, key)
if err != nil {
return nil, err
}
return crypto.HMACSHA256(keys.hmacKey, message), nil
}
// Verify checks the MAC of the message using the key against the givenMAC. The key is used to derive the actual mac key (32 bytes).
func (c AESSHA256) Verify(key, message, givenMAC []byte) (bool, error) {
mac, err := c.MAC(key, message)
if err != nil {
return false, err
}
return bytes.Equal(givenMAC, mac[:len(givenMAC)]), nil
}

View File

@@ -0,0 +1,17 @@
// cipher provides the methods and structs to do encryptions for olm/megolm.
package cipher
// Cipher defines a valid cipher.
type Cipher interface {
// Encrypt encrypts the plaintext.
Encrypt(key, plaintext []byte) (ciphertext []byte, err error)
// Decrypt decrypts the ciphertext.
Decrypt(key, ciphertext []byte) (plaintext []byte, err error)
//MAC returns the MAC of the message calculated with the key.
MAC(key, message []byte) ([]byte, error)
//Verify checks the MAC of the message calculated with the key against the givenMAC.
Verify(key, message, givenMAC []byte) (bool, error)
}

View File

@@ -0,0 +1,58 @@
package cipher
import (
"fmt"
"maunium.net/go/mautrix/crypto/goolm"
)
const (
kdfPickle = "Pickle" //used to derive the keys for encryption
pickleMACLength = 8
)
// PickleBlockSize returns the blocksize of the used cipher.
func PickleBlockSize() int {
return AESSha512BlockSize()
}
// Pickle encrypts the input with the key and the cipher AESSHA256. The result is then encoded in base64.
func Pickle(key, input []byte) ([]byte, error) {
pickleCipher := NewAESSHA256([]byte(kdfPickle))
ciphertext, err := pickleCipher.Encrypt(key, input)
if err != nil {
return nil, err
}
mac, err := pickleCipher.MAC(key, ciphertext)
if err != nil {
return nil, err
}
ciphertext = append(ciphertext, mac[:pickleMACLength]...)
encoded := goolm.Base64Encode(ciphertext)
return encoded, nil
}
// Unpickle decodes the input from base64 and decrypts the decoded input with the key and the cipher AESSHA256.
func Unpickle(key, input []byte) ([]byte, error) {
pickleCipher := NewAESSHA256([]byte(kdfPickle))
ciphertext, err := goolm.Base64Decode(input)
if err != nil {
return nil, err
}
//remove mac and check
verified, err := pickleCipher.Verify(key, ciphertext[:len(ciphertext)-pickleMACLength], ciphertext[len(ciphertext)-pickleMACLength:])
if err != nil {
return nil, err
}
if !verified {
return nil, fmt.Errorf("decrypt pickle: %w", goolm.ErrBadMAC)
}
//Set to next block size
targetCipherText := make([]byte, int(len(ciphertext)/PickleBlockSize())*PickleBlockSize())
copy(targetCipherText, ciphertext)
plaintext, err := pickleCipher.Decrypt(key, targetCipherText)
if err != nil {
return nil, err
}
return plaintext, nil
}