fix(aliyundriver):x-device-id error code (#3390)
* fix(aliyundriver):x-drvice-id error code * fix(aliyunpan):session signature error * fix typo --------- Co-authored-by: Andy Hsu <i@nn.ci>
This commit is contained in:
@ -3,6 +3,7 @@ package aliyundrive
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
@ -31,6 +32,12 @@ type AliDrive struct {
|
||||
AccessToken string
|
||||
cron *cron.Cron
|
||||
DriveId string
|
||||
UserID string
|
||||
|
||||
signature string
|
||||
nonce int
|
||||
privateKey *ecdsa.PrivateKey
|
||||
cron2 *cron.Cron
|
||||
}
|
||||
|
||||
func (d *AliDrive) Config() driver.Config {
|
||||
@ -54,6 +61,7 @@ func (d *AliDrive) Init(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
d.DriveId = utils.Json.Get(res, "default_drive_id").ToString()
|
||||
d.UserID = utils.Json.Get(res, "user_id").ToString()
|
||||
d.cron = cron.NewCron(time.Hour * 2)
|
||||
d.cron.Do(func() {
|
||||
err := d.refreshToken()
|
||||
@ -61,6 +69,29 @@ func (d *AliDrive) Init(ctx context.Context) error {
|
||||
log.Errorf("%+v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// init deviceID
|
||||
if len(d.DeviceID) < 64 {
|
||||
d.DeviceID = utils.GetSHA256Encode(d.DeviceID)
|
||||
}
|
||||
|
||||
// init privateKey
|
||||
d.privateKey, _ = NewPrivateKey()
|
||||
|
||||
// init signature
|
||||
d.sign()
|
||||
d.createSession()
|
||||
d.cron2 = cron.NewCron(time.Minute * 5)
|
||||
d.cron2.Do(func() {
|
||||
d.nonce++
|
||||
d.sign()
|
||||
err := d.renewSession()
|
||||
if d.nonce >= 1073741823 || (err != nil && err.Error() == "device session signature error") {
|
||||
d.nonce = 0
|
||||
d.sign()
|
||||
d.createSession()
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -68,6 +99,9 @@ func (d *AliDrive) Drop(ctx context.Context) error {
|
||||
if d.cron != nil {
|
||||
d.cron.Stop()
|
||||
}
|
||||
if d.cron2 != nil {
|
||||
d.cron2.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
66
drivers/aliyundrive/help.go
Normal file
66
drivers/aliyundrive/help.go
Normal file
@ -0,0 +1,66 @@
|
||||
package aliyundrive
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
||||
"github.com/dustinxie/ecc"
|
||||
)
|
||||
|
||||
func NewPrivateKey() (*ecdsa.PrivateKey, error) {
|
||||
p256k1 := ecc.P256k1()
|
||||
return ecdsa.GenerateKey(p256k1, rand.Reader)
|
||||
}
|
||||
|
||||
func NewPrivateKeyFromHex(hex_ string) (*ecdsa.PrivateKey, error) {
|
||||
data, err := hex.DecodeString(hex_)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewPrivateKeyFromBytes(data), nil
|
||||
|
||||
}
|
||||
|
||||
func NewPrivateKeyFromBytes(priv []byte) *ecdsa.PrivateKey {
|
||||
p256k1 := ecc.P256k1()
|
||||
x, y := p256k1.ScalarBaseMult(priv)
|
||||
return &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: p256k1,
|
||||
X: x,
|
||||
Y: y,
|
||||
},
|
||||
D: new(big.Int).SetBytes(priv),
|
||||
}
|
||||
}
|
||||
|
||||
func PrivateKeyToHex(private *ecdsa.PrivateKey) string {
|
||||
return hex.EncodeToString(PrivateKeyToBytes(private))
|
||||
}
|
||||
|
||||
func PrivateKeyToBytes(private *ecdsa.PrivateKey) []byte {
|
||||
return private.D.Bytes()
|
||||
}
|
||||
|
||||
func PublicKeyToHex(public *ecdsa.PublicKey) string {
|
||||
return hex.EncodeToString(PublicKeyToBytes(public))
|
||||
}
|
||||
|
||||
func PublicKeyToBytes(public *ecdsa.PublicKey) []byte {
|
||||
x := public.X.Bytes()
|
||||
if len(x) < 32 {
|
||||
for i := 0; i < 32-len(x); i++ {
|
||||
x = append([]byte{0}, x...)
|
||||
}
|
||||
}
|
||||
|
||||
y := public.Y.Bytes()
|
||||
if len(y) < 32 {
|
||||
for i := 0; i < 32-len(y); i++ {
|
||||
y = append([]byte{0}, y...)
|
||||
}
|
||||
}
|
||||
return append(x, y...)
|
||||
}
|
@ -8,6 +8,7 @@ import (
|
||||
type Addition struct {
|
||||
driver.RootID
|
||||
RefreshToken string `json:"refresh_token" required:"true"`
|
||||
DeviceID string `json:"device_id" required:"true"`
|
||||
OrderBy string `json:"order_by" type:"select" options:"name,size,updated_at,created_at"`
|
||||
OrderDirection string `json:"order_direction" type:"select" options:"ASC,DESC"`
|
||||
RapidUpload bool `json:"rapid_upload"`
|
||||
|
@ -1,6 +1,8 @@
|
||||
package aliyundrive
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -8,9 +10,37 @@ import (
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/dustinxie/ecc"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (d *AliDrive) createSession() error {
|
||||
_, err, _ := d.request("https://api.aliyundrive.com/users/v1/users/device/create_session", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
"deviceName": "samsung",
|
||||
"modelName": "SM-G9810",
|
||||
"nonce": d.nonce,
|
||||
"pubKey": PublicKeyToHex(&d.privateKey.PublicKey),
|
||||
"refreshToken": d.RefreshToken,
|
||||
})
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *AliDrive) renewSession() error {
|
||||
_, err, _ := d.request("https://api.aliyundrive.com/users/v1/users/device/renew_session", http.MethodPost, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *AliDrive) sign() {
|
||||
secpAppID := "5dde4e1bdf9e4966b387ba58f4b3fdc3"
|
||||
singdata := fmt.Sprintf("%s:%s:%s:%d", secpAppID, d.DeviceID, d.UserID, d.nonce)
|
||||
hash := sha256.Sum256([]byte(singdata))
|
||||
data, _ := ecc.SignBytes(d.privateKey, hash[:], ecc.RecID|ecc.LowerS)
|
||||
d.signature = hex.EncodeToString(data)
|
||||
}
|
||||
|
||||
// do others that not defined in Driver interface
|
||||
|
||||
func (d *AliDrive) refreshToken() error {
|
||||
@ -39,9 +69,16 @@ func (d *AliDrive) refreshToken() error {
|
||||
|
||||
func (d *AliDrive) request(url, method string, callback base.ReqCallback, resp interface{}) ([]byte, error, RespErr) {
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeader("Authorization", "Bearer\t"+d.AccessToken)
|
||||
req.SetHeader("content-type", "application/json")
|
||||
req.SetHeader("origin", "https://www.aliyundrive.com")
|
||||
req.SetHeaders(map[string]string{
|
||||
"Authorization": "Bearer\t" + d.AccessToken,
|
||||
"content-type": "application/json",
|
||||
"origin": "https://www.aliyundrive.com",
|
||||
"Referer": "https://aliyundrive.com/",
|
||||
"X-Signature": d.signature,
|
||||
"x-request-id": uuid.NewString(),
|
||||
"X-Canary": "client=Android,app=adrive,version=v4.1.0",
|
||||
"X-Device-Id": d.DeviceID,
|
||||
})
|
||||
if callback != nil {
|
||||
callback(req)
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user