59 lines
1.6 KiB
Go
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
|
|
}
|