| 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))), | |
| } | |
| } | |