-
-
Notifications
You must be signed in to change notification settings - Fork 143
/
Copy pathcipher_decrypt.go
73 lines (60 loc) · 1.92 KB
/
cipher_decrypt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package crypto
import (
"crypto/aes"
"golang.org/x/xerrors"
"github.com/gotd/ige"
"github.com/gotd/td/bin"
)
// DecryptFromBuffer decodes EncryptedMessage and decrypts it.
func (c Cipher) DecryptFromBuffer(k AuthKey, buf *bin.Buffer) (*EncryptedMessageData, error) {
msg := &EncryptedMessage{}
if err := msg.Decode(buf); err != nil {
return nil, err
}
return c.Decrypt(k, msg)
}
// Decrypt decrypts data from encrypted message using AES-IGE.
func (c Cipher) Decrypt(k AuthKey, encrypted *EncryptedMessage) (*EncryptedMessageData, error) {
plaintext, err := c.DecryptMessage(k, encrypted)
if err != nil {
return nil, err
}
side := c.encryptSide.DecryptSide()
// Checking SHA256 hash value of msg_key
msgKey := MessageKey(k.Value, plaintext, side)
if msgKey != encrypted.MsgKey {
return nil, xerrors.Errorf("msg_key is invalid")
}
msg := &EncryptedMessageData{}
if err := msg.Decode(&bin.Buffer{Buf: plaintext}); err != nil {
return nil, err
}
{
// Checking that padding of decrypted message is not too big.
const maxPadding = 1024
n := int(msg.MessageDataLen)
paddingLen := len(msg.MessageDataWithPadding) - n
if paddingLen > maxPadding {
return nil, xerrors.Errorf("padding %d of message is too big", paddingLen)
}
}
return msg, nil
}
// DecryptMessage decrypts data from encrypted message using AES-IGE.
func (c Cipher) DecryptMessage(k AuthKey, encrypted *EncryptedMessage) ([]byte, error) {
if k.ID != encrypted.AuthKeyID {
return nil, xerrors.New("unknown auth key id")
}
if len(encrypted.EncryptedData)%16 != 0 {
return nil, xerrors.New("invalid encrypted data padding")
}
key, iv := Keys(k.Value, encrypted.MsgKey, c.encryptSide.DecryptSide())
cipher, err := aes.NewCipher(key[:])
if err != nil {
return nil, err
}
plaintext := make([]byte, len(encrypted.EncryptedData))
d := ige.NewIGEDecrypter(cipher, iv[:])
d.CryptBlocks(plaintext, encrypted.EncryptedData)
return plaintext, nil
}