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.
92 lines
2.6 KiB
92 lines
2.6 KiB
package tdesktop |
|
|
|
import ( |
|
"bytes" |
|
"crypto/aes" |
|
"crypto/sha1" // #nosec G505 |
|
"crypto/sha512" |
|
|
|
"github.com/go-faster/errors" |
|
"golang.org/x/crypto/pbkdf2" |
|
|
|
"github.com/gotd/ige" |
|
"github.com/gotd/td/bin" |
|
"github.com/gotd/td/internal/crypto" |
|
) |
|
|
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp#L322. |
|
func createLegacyLocalKey(passcode, salt []byte) (r crypto.Key) { |
|
iters := localEncryptNoPwdIterCount |
|
if len(passcode) > 0 { |
|
iters = localEncryptIterCount |
|
} |
|
|
|
key := pbkdf2.Key(passcode, salt, iters, len(r), sha1.New) |
|
copy(r[:], key) |
|
return r |
|
} |
|
|
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp#L300. |
|
func createLocalKey(passcode, salt []byte) (r crypto.Key) { |
|
iters := 1 |
|
if len(passcode) > 0 { |
|
iters = kStrongIterationsCount |
|
} |
|
|
|
h := sha512.New() |
|
_, _ = h.Write(salt) |
|
_, _ = h.Write(passcode) |
|
_, _ = h.Write(salt) |
|
|
|
key := pbkdf2.Key(h.Sum(nil), salt, iters, len(r), sha512.New) |
|
copy(r[:], key) |
|
return r |
|
} |
|
|
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp#L584. |
|
func decryptLocal(encrypted []byte, localKey crypto.Key) ([]byte, error) { |
|
if l := len(encrypted); l%aes.BlockSize != 0 { |
|
return nil, errors.Errorf("invalid length %d, must be padded to 16", l) |
|
} |
|
// Get encryptedKey. |
|
var msgKey bin.Int128 |
|
n := copy(msgKey[:], encrypted) |
|
encrypted = encrypted[n:] |
|
|
|
aesKey, aesIV := crypto.OldKeys(localKey, msgKey, crypto.Server) |
|
cipher, err := aes.NewCipher(aesKey[:]) |
|
if err != nil { |
|
return nil, errors.Wrap(err, "create cipher") |
|
} |
|
|
|
decrypted := make([]byte, len(encrypted)) |
|
ige.DecryptBlocks(cipher, aesIV[:], decrypted, encrypted) |
|
|
|
if h := sha1.Sum(decrypted); !bytes.Equal(h[:16], msgKey[:]) /* #nosec G401 */ { |
|
return nil, errors.New("msg_key mismatch") |
|
} |
|
return decrypted, nil |
|
} |
|
|
|
// encryptLocal code may panic |
|
func encryptLocal(decrypted []byte, localKey crypto.Key) ([]byte, error) { |
|
if l := len(decrypted); l%aes.BlockSize != 0 { |
|
return nil, errors.Errorf("invalid length %d, must be padded to 16", l) |
|
} |
|
// Compute encryptedKey. |
|
var msgKey bin.Int128 |
|
h := sha1.Sum(decrypted) // #nosec G401 |
|
copy(msgKey[:], h[:]) |
|
|
|
aesKey, aesIV := crypto.OldKeys(localKey, msgKey, crypto.Server) |
|
cipher, err := aes.NewCipher(aesKey[:]) |
|
if err != nil { |
|
return nil, errors.Wrap(err, "create cipher") |
|
} |
|
|
|
encrypted := make([]byte, 16+len(decrypted)) |
|
copy(encrypted, msgKey[:]) |
|
ige.EncryptBlocks(cipher, aesIV[:], encrypted[16:], decrypted) |
|
|
|
return encrypted, nil |
|
}
|
|
|