summaryrefslogtreecommitdiffstats
path: root/vendor/go.mau.fi/whatsmeow/mediaretry.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.mau.fi/whatsmeow/mediaretry.go')
-rw-r--r--vendor/go.mau.fi/whatsmeow/mediaretry.go73
1 files changed, 26 insertions, 47 deletions
diff --git a/vendor/go.mau.fi/whatsmeow/mediaretry.go b/vendor/go.mau.fi/whatsmeow/mediaretry.go
index 52b04608..e6e1fa8b 100644
--- a/vendor/go.mau.fi/whatsmeow/mediaretry.go
+++ b/vendor/go.mau.fi/whatsmeow/mediaretry.go
@@ -7,8 +7,6 @@
package whatsmeow
import (
- "crypto/aes"
- "crypto/cipher"
"crypto/rand"
"fmt"
@@ -18,6 +16,7 @@ import (
waProto "go.mau.fi/whatsmeow/binary/proto"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
+ "go.mau.fi/whatsmeow/util/gcmutil"
"go.mau.fi/whatsmeow/util/hkdfutil"
)
@@ -25,18 +24,6 @@ func getMediaRetryKey(mediaKey []byte) (cipherKey []byte) {
return hkdfutil.SHA256(mediaKey, nil, []byte("WhatsApp Media Retry Notification"), 32)
}
-func prepareMediaRetryGCM(mediaKey []byte) (cipher.AEAD, error) {
- block, err := aes.NewCipher(getMediaRetryKey(mediaKey))
- if err != nil {
- return nil, fmt.Errorf("failed to initialize AES cipher: %w", err)
- }
- gcm, err := cipher.NewGCM(block)
- if err != nil {
- return nil, fmt.Errorf("failed to initialize GCM: %w", err)
- }
- return gcm, nil
-}
-
func encryptMediaRetryReceipt(messageID types.MessageID, mediaKey []byte) (ciphertext, iv []byte, err error) {
receipt := &waProto.ServerErrorReceipt{
StanzaId: proto.String(messageID),
@@ -47,17 +34,12 @@ func encryptMediaRetryReceipt(messageID types.MessageID, mediaKey []byte) (ciphe
err = fmt.Errorf("failed to marshal payload: %w", err)
return
}
- var gcm cipher.AEAD
- gcm, err = prepareMediaRetryGCM(mediaKey)
- if err != nil {
- return
- }
iv = make([]byte, 12)
_, err = rand.Read(iv)
if err != nil {
panic(err)
}
- ciphertext = gcm.Seal(plaintext[:0], iv, plaintext, []byte(messageID))
+ ciphertext, err = gcmutil.Encrypt(getMediaRetryKey(mediaKey), iv, plaintext, []byte(messageID))
return
}
@@ -66,35 +48,35 @@ func encryptMediaRetryReceipt(messageID types.MessageID, mediaKey []byte) (ciphe
// This is mostly relevant when handling history syncs and getting a 404 or 410 error downloading media.
// Rough example on how to use it (will not work out of the box, you must adjust it depending on what you need exactly):
//
-// var mediaRetryCache map[types.MessageID]*waProto.ImageMessage
+// var mediaRetryCache map[types.MessageID]*waProto.ImageMessage
//
-// evt, err := cli.ParseWebMessage(chatJID, historyMsg.GetMessage())
-// imageMsg := evt.Message.GetImageMessage() // replace this with the part of the message you want to download
-// data, err := cli.Download(imageMsg)
-// if errors.Is(err, whatsmeow.ErrMediaDownloadFailedWith404) || errors.Is(err, whatsmeow.ErrMediaDownloadFailedWith410) {
-// err = cli.SendMediaRetryReceipt(&evt.Info, imageMsg.GetMediaKey())
-// // You need to store the event data somewhere as it's necessary for handling the retry response.
-// mediaRetryCache[evt.Info.ID] = imageMsg
-// }
+// evt, err := cli.ParseWebMessage(chatJID, historyMsg.GetMessage())
+// imageMsg := evt.Message.GetImageMessage() // replace this with the part of the message you want to download
+// data, err := cli.Download(imageMsg)
+// if errors.Is(err, whatsmeow.ErrMediaDownloadFailedWith404) || errors.Is(err, whatsmeow.ErrMediaDownloadFailedWith410) {
+// err = cli.SendMediaRetryReceipt(&evt.Info, imageMsg.GetMediaKey())
+// // You need to store the event data somewhere as it's necessary for handling the retry response.
+// mediaRetryCache[evt.Info.ID] = imageMsg
+// }
//
// The response will come as an *events.MediaRetry. The response will then have to be decrypted
// using DecryptMediaRetryNotification and the same media key passed here. If the media retry was successful,
// the decrypted notification should contain an updated DirectPath, which can be used to download the file.
//
-// func eventHandler(rawEvt interface{}) {
-// switch evt := rawEvt.(type) {
-// case *events.MediaRetry:
-// imageMsg := mediaRetryCache[evt.MessageID]
-// retryData, err := whatsmeow.DecryptMediaRetryNotification(evt, imageMsg.GetMediaKey())
-// if err != nil || retryData.GetResult != waProto.MediaRetryNotification_SUCCESS {
-// return
-// }
-// // Use the new path to download the attachment
-// imageMsg.DirectPath = retryData.DirectPath
-// data, err := cli.Download(imageMsg)
-// // Alternatively, you can use cli.DownloadMediaWithPath and provide the individual fields manually.
-// }
-// }
+// func eventHandler(rawEvt interface{}) {
+// switch evt := rawEvt.(type) {
+// case *events.MediaRetry:
+// imageMsg := mediaRetryCache[evt.MessageID]
+// retryData, err := whatsmeow.DecryptMediaRetryNotification(evt, imageMsg.GetMediaKey())
+// if err != nil || retryData.GetResult != waProto.MediaRetryNotification_SUCCESS {
+// return
+// }
+// // Use the new path to download the attachment
+// imageMsg.DirectPath = retryData.DirectPath
+// data, err := cli.Download(imageMsg)
+// // Alternatively, you can use cli.DownloadMediaWithPath and provide the individual fields manually.
+// }
+// }
func (cli *Client) SendMediaRetryReceipt(message *types.MessageInfo, mediaKey []byte) error {
ciphertext, iv, err := encryptMediaRetryReceipt(message.ID, mediaKey)
if err != nil {
@@ -136,15 +118,12 @@ func (cli *Client) SendMediaRetryReceipt(message *types.MessageInfo, mediaKey []
// See Client.SendMediaRetryReceipt for more info on how to use this.
func DecryptMediaRetryNotification(evt *events.MediaRetry, mediaKey []byte) (*waProto.MediaRetryNotification, error) {
var notif waProto.MediaRetryNotification
- var plaintext []byte
if evt.Error != nil && evt.Ciphertext == nil {
if evt.Error.Code == 2 {
return nil, ErrMediaNotAvailableOnPhone
}
return nil, fmt.Errorf("%w (code: %d)", ErrUnknownMediaRetryError, evt.Error.Code)
- } else if gcm, err := prepareMediaRetryGCM(mediaKey); err != nil {
- return nil, err
- } else if plaintext, err = gcm.Open(nil, evt.IV, evt.Ciphertext, []byte(evt.MessageID)); err != nil {
+ } else if plaintext, err := gcmutil.Decrypt(getMediaRetryKey(mediaKey), evt.IV, evt.Ciphertext, []byte(evt.MessageID)); err != nil {
return nil, fmt.Errorf("failed to decrypt notification: %w", err)
} else if err = proto.Unmarshal(plaintext, &notif); err != nil {
return nil, fmt.Errorf("failed to unmarshal notification (invalid encryption key?): %w", err)