You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
1.9 KiB
71 lines
1.9 KiB
package tdesktop |
|
|
|
import ( |
|
"encoding/binary" |
|
|
|
"github.com/go-faster/errors" |
|
|
|
"github.com/gotd/td/internal/crypto" |
|
) |
|
|
|
type keyData struct { |
|
localKey crypto.Key |
|
accountsIDx []uint32 |
|
} |
|
|
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/storage/storage_domain.cpp#L119-L159. |
|
func readKeyData(tgf *tdesktopFile, passcode []byte) (_ keyData, rErr error) { |
|
salt, err := tgf.readArray() |
|
if err != nil { |
|
return keyData{}, errors.Wrap(err, "read salt") |
|
} |
|
if l := len(salt); l != localEncryptSaltSize { |
|
return keyData{}, errors.Errorf("invalid salt length %d", l) |
|
} |
|
|
|
passcodeKey := createLocalKey(passcode, salt) |
|
keyEncrypted, err := tgf.readArray() |
|
if err != nil { |
|
return keyData{}, errors.Wrap(err, "read keyEncrypted") |
|
} |
|
keyInnerData, err := decryptLocal(keyEncrypted, passcodeKey) |
|
if err != nil { |
|
return keyData{}, errors.Wrap(err, "decrypt keyEncrypted") |
|
} |
|
key, _, err := readArray(keyInnerData, binary.LittleEndian) |
|
if err != nil { |
|
return keyData{}, errors.Wrap(err, "read key") |
|
} |
|
|
|
if l := len(key); l < len(crypto.Key{}) { |
|
return keyData{}, errors.Errorf("key too small (%d)", l) |
|
} |
|
var localKey crypto.Key |
|
copy(localKey[:], key) |
|
|
|
infoEncrypted, err := tgf.readArray() |
|
if err != nil { |
|
return keyData{}, errors.Wrap(err, "read infoEncrypted") |
|
} |
|
infoDecrypted, err := decryptLocal(infoEncrypted, localKey) |
|
if err != nil { |
|
return keyData{}, ErrKeyInfoDecrypt |
|
} |
|
// Skip decrypted data length. |
|
infoDecrypted = infoDecrypted[4:] |
|
// Read count of accounts. |
|
count := int(binary.BigEndian.Uint32(infoDecrypted)) |
|
infoDecrypted = infoDecrypted[4:] |
|
|
|
// Preallocate accountsIDx. |
|
accountsIDx := make([]uint32, 0, count) |
|
for i := 0; i < count; i++ { |
|
idx := binary.BigEndian.Uint32(infoDecrypted[i*4:]) |
|
accountsIDx = append(accountsIDx, idx) |
|
} |
|
|
|
return keyData{ |
|
localKey: localKey, |
|
accountsIDx: accountsIDx, |
|
}, nil |
|
}
|
|
|