Files
postmoogle/vendor/maunium.net/go/mautrix/crypto/goolm/cipher/pickle.go
2024-02-11 20:47:04 +02:00

59 lines
1.6 KiB
Go

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
}