package crypto
import (
"crypto/aes"
"fmt"
"io"
"github.com/go-faster/errors"
"github.com/gotd/ige"
"github.com/gotd/td/bin"
)
const BindAuthKeyInnerTypeID = 0x75a3f765
type BindAuthKeyInner struct {
Nonce int64
TempAuthKeyID int64
PermAuthKeyID int64
TempSessionID int64
ExpiresAt int
}
func (*BindAuthKeyInner ) TypeID () uint32 {
return BindAuthKeyInnerTypeID
}
func (m *BindAuthKeyInner ) Encode (b *bin .Buffer ) error {
if m == nil {
return fmt .Errorf ("can't encode bind_auth_key_inner#75a3f765 as nil" )
}
b .PutID (BindAuthKeyInnerTypeID )
b .PutLong (m .Nonce )
b .PutLong (m .TempAuthKeyID )
b .PutLong (m .PermAuthKeyID )
b .PutLong (m .TempSessionID )
b .PutInt (m .ExpiresAt )
return nil
}
func (m *BindAuthKeyInner ) Decode (b *bin .Buffer ) error {
if m == nil {
return fmt .Errorf ("can't decode bind_auth_key_inner#75a3f765 to nil" )
}
if err := b .ConsumeID (BindAuthKeyInnerTypeID ); err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: %w" , err )
}
{
value , err := b .Long ()
if err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: field nonce: %w" , err )
}
m .Nonce = value
}
{
value , err := b .Long ()
if err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: field temp_auth_key_id: %w" , err )
}
m .TempAuthKeyID = value
}
{
value , err := b .Long ()
if err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: field perm_auth_key_id: %w" , err )
}
m .PermAuthKeyID = value
}
{
value , err := b .Long ()
if err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: field temp_session_id: %w" , err )
}
m .TempSessionID = value
}
{
value , err := b .Int ()
if err != nil {
return fmt .Errorf ("unable to decode bind_auth_key_inner#75a3f765: field expires_at: %w" , err )
}
m .ExpiresAt = value
}
return nil
}
func EncryptBindMessage (rand io .Reader , permKey AuthKey , msgID int64 , inner *BindAuthKeyInner ) ([]byte , error ) {
if permKey .Zero () {
return nil , errors .New ("permanent key is zero" )
}
if rand == nil {
rand = DefaultRand ()
}
payload := &bin .Buffer {}
if err := payload .Encode (inner ); err != nil {
return nil , errors .Wrap (err , "encode bind_auth_key_inner" )
}
plaintext := &bin .Buffer {}
random := make ([]byte , 16 )
if _ , err := io .ReadFull (rand , random ); err != nil {
return nil , errors .Wrap (err , "generate random prefix" )
}
plaintext .Put (random )
plaintext .PutLong (msgID )
plaintext .PutInt32 (0 )
plaintext .PutInt32 (int32 (payload .Len ()))
plaintext .Put (payload .Buf )
msgKey := MessageKeyV1 (plaintext .Buf )
if rem := len (plaintext .Buf ) % aes .BlockSize ; rem != 0 {
paddingLen := aes .BlockSize - rem
offset := len (plaintext .Buf )
plaintext .Buf = append (plaintext .Buf , make ([]byte , paddingLen )...)
if _ , err := io .ReadFull (rand , plaintext .Buf [offset :]); err != nil {
return nil , errors .Wrap (err , "generate random padding" )
}
}
key , iv := KeysV1 (permKey .Value , msgKey )
block , err := aes .NewCipher (key [:])
if err != nil {
return nil , errors .Wrap (err , "create aes cipher" )
}
msg := EncryptedMessage {
AuthKeyID : permKey .ID ,
MsgKey : msgKey ,
EncryptedData : make ([]byte , len (plaintext .Buf )),
}
ige .EncryptBlocks (block , iv [:], msg .EncryptedData , plaintext .Buf )
encrypted := &bin .Buffer {}
if err := msg .Encode (encrypted ); err != nil {
return nil , errors .Wrap (err , "encode encrypted message" )
}
return append ([]byte (nil ), encrypted .Buf ...), nil
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .