|
package netease_music |
|
|
|
import ( |
|
"bytes" |
|
"crypto/aes" |
|
"crypto/cipher" |
|
"crypto/md5" |
|
"crypto/rsa" |
|
"crypto/x509" |
|
"encoding/base64" |
|
"encoding/hex" |
|
"encoding/pem" |
|
"math/big" |
|
"strings" |
|
|
|
"github.com/alist-org/alist/v3/pkg/utils" |
|
"github.com/alist-org/alist/v3/pkg/utils/random" |
|
) |
|
|
|
var ( |
|
linuxapiKey = []byte("rFgB&h#%2?^eDg:Q") |
|
eapiKey = []byte("e82ckenh8dichen8") |
|
iv = []byte("0102030405060708") |
|
presetKey = []byte("0CoJUm6Qyw8W8jud") |
|
publicKey = []byte("-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----") |
|
stdChars = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") |
|
) |
|
|
|
func aesKeyPending(key []byte) []byte { |
|
k := len(key) |
|
count := 0 |
|
switch true { |
|
case k <= 16: |
|
count = 16 - k |
|
case k <= 24: |
|
count = 24 - k |
|
case k <= 32: |
|
count = 32 - k |
|
default: |
|
return key[:32] |
|
} |
|
if count == 0 { |
|
return key |
|
} |
|
|
|
return append(key, bytes.Repeat([]byte{0}, count)...) |
|
} |
|
|
|
func pkcs7Padding(src []byte, blockSize int) []byte { |
|
padding := blockSize - len(src)%blockSize |
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding) |
|
return append(src, padtext...) |
|
} |
|
|
|
func aesCBCEncrypt(src, key, iv []byte) []byte { |
|
block, _ := aes.NewCipher(aesKeyPending(key)) |
|
src = pkcs7Padding(src, block.BlockSize()) |
|
dst := make([]byte, len(src)) |
|
|
|
mode := cipher.NewCBCEncrypter(block, iv) |
|
mode.CryptBlocks(dst, src) |
|
|
|
return dst |
|
} |
|
|
|
func aesECBEncrypt(src, key []byte) []byte { |
|
block, _ := aes.NewCipher(aesKeyPending(key)) |
|
|
|
src = pkcs7Padding(src, block.BlockSize()) |
|
dst := make([]byte, len(src)) |
|
|
|
ecbCryptBlocks(block, dst, src) |
|
|
|
return dst |
|
} |
|
|
|
func ecbCryptBlocks(block cipher.Block, dst, src []byte) { |
|
bs := block.BlockSize() |
|
|
|
for len(src) > 0 { |
|
block.Encrypt(dst, src[:bs]) |
|
src = src[bs:] |
|
dst = dst[bs:] |
|
} |
|
} |
|
|
|
func rsaEncrypt(buffer, key []byte) []byte { |
|
buffers := make([]byte, 128-16, 128) |
|
buffers = append(buffers, buffer...) |
|
block, _ := pem.Decode(key) |
|
pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes) |
|
pub := pubInterface.(*rsa.PublicKey) |
|
c := new(big.Int).SetBytes([]byte(buffers)) |
|
return c.Exp(c, big.NewInt(int64(pub.E)), pub.N).Bytes() |
|
} |
|
|
|
func getSecretKey() ([]byte, []byte) { |
|
key := make([]byte, 16) |
|
reversed := make([]byte, 16) |
|
for i := 0; i < 16; i++ { |
|
result := stdChars[random.RangeInt64(0, 62)] |
|
key[i] = result |
|
reversed[15-i] = result |
|
} |
|
return key, reversed |
|
} |
|
|
|
func weapi(data map[string]string) map[string]string { |
|
text, _ := utils.Json.Marshal(data) |
|
secretKey, reversedKey := getSecretKey() |
|
params := []byte(base64.StdEncoding.EncodeToString(aesCBCEncrypt(text, presetKey, iv))) |
|
return map[string]string{ |
|
"params": base64.StdEncoding.EncodeToString(aesCBCEncrypt(params, reversedKey, iv)), |
|
"encSecKey": hex.EncodeToString(rsaEncrypt(secretKey, publicKey)), |
|
} |
|
} |
|
|
|
func eapi(url string, data map[string]interface{}) map[string]string { |
|
text, _ := utils.Json.Marshal(data) |
|
msg := "nobody" + url + "use" + string(text) + "md5forencrypt" |
|
h := md5.New() |
|
h.Write([]byte(msg)) |
|
digest := hex.EncodeToString(h.Sum(nil)) |
|
params := []byte(url + "-36cd479b6b5-" + string(text) + "-36cd479b6b5-" + digest) |
|
return map[string]string{ |
|
"params": hex.EncodeToString(aesECBEncrypt(params, eapiKey)), |
|
} |
|
} |
|
|
|
func linuxapi(data map[string]interface{}) map[string]string { |
|
text, _ := utils.Json.Marshal(data) |
|
return map[string]string{ |
|
"eparams": strings.ToUpper(hex.EncodeToString(aesECBEncrypt(text, linuxapiKey))), |
|
} |
|
} |
|
|