网易云音乐params和encSecKey生成原理

1.首先来个整体的解析

  • params:经过两次AES加密后的数据(128位,CBC,pkcs5padding)

第一加密:要加密的是真正要发送的明文数据(数据的具体格式,下面会讲),密钥固定为0CoJUm6Qyw8W8jud,iv为固定为0102030405060708

第二加密:先把第一次加密结果转base64格式后,再进行加密。密钥是在前端随机生成的(长度为16个字节),iv为也是固定为0102030405060708

  • encSecKey:经过RSA加密后的数据(1024位,ECB,nopadding)

上面提到的第二次AES加密的密钥是在前端随机生成的,服务器想要解密数据,必须知道这个密钥,但服务器是怎么知道这个随机密钥的呢?
这时encSecKey就派上用场了。用RSA加密AES密钥后,再发给服务器。没错,encSecKey就是RSA加密后的AES密钥

注意,在加密前,需要对明文反转处理,例如:如果加密的明文是aaaabbbbccccdddd,那你要把它转成ddddccccbbbbaaaa后再进行RSA加密

用到了RSA加密,那这个RSA的公钥是多少?很幸运,这个公钥是固定的。modulus和publicExponent如下(都是十进制):

modulus=157794750267131502212476817800345498121872783333389747424011531025366277535262539913701806290766479189477533597854989606803194253978660329941980786072432806427833685472618792592200595694346872951301770580765135349259590167490536138082469680638514416594216629258349130257685001248172188325316586707301643237607
publicExponent=65537



2.简化爬虫

上面提到过,params的第二次AES加密的密钥是在前端随机生成的,假如进行干预,让每次生成的密钥都一样,这样的话encSecKey每次也就一样了。

为了方便爬虫,让每次encSecKey都固定,我就让第二次AES加密密钥每次都是aaaabbbbccccdddd
然后进行按上面提到的规则进行RSA加密,生成encSecKey代码如下

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;


public class Test {


    public static void main(String[] args) throws Exception{
        String modulus ="157794750267131502212476817800345498121872783333389747424011531025366277535262539913701806290766479189477533597854989606803194253978660329941980786072432806427833685472618792592200595694346872951301770580765135349259590167490536138082469680638514416594216629258349130257685001248172188325316586707301643237607";
        String publicExponent = "65537";
        RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
        RSAPublicKey key = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(publicSpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/nopadding");
        cipher.init(Cipher.ENCRYPT_MODE,key);

        //注意,我这里已经进行字符串反转
        byte[] res = cipher.doFinal("ddddccccbbbbaaaa".getBytes(StandardCharsets.UTF_8));

        //把密文转成16进制字符串后输出
        System.out.print(longToHexString(res));
    }


    //这个函数是用来将二进制数据转成16进制字符串的
    static private String longToHexString(byte[] num) {
        StringBuffer hexString = new StringBuffer();

        for (int i=0;i<num.length;i++){

            if((num[i]&0xf0)==0){
                hexString.append("0"+Integer.toHexString(num[i]&0xff));
            }
            else{
                hexString.append(Integer.toHexString(num[i]&0xff));
            }
        }

        return  hexString.toString();
    }




}

输出encSecKey为:

814e4abf9c1c6a2af74a7ecca8843f3052626c5c054584352e3fd38a519bd659e687cf1c079e1aac5dd9d491af6b8abf92109862ada93dc7b0ef94a8ee79d557ff2a20512b87ce507e357861366b8542139c67896748852d4086104a8dfc99a2e2e0640b46a4357407b72407b2849b323425c6ed45a0222e69d551a2e59e15b7

到这里,已经简化了爬虫,即以后每次请求,encSecKey的值都是固定的,都是上面这个字符串。
params用到的加密密钥也固定了,
第一次是0CoJUm6Qyw8W8jud
第二次是aaaabbbbccccdddd
iv都是0102030405060708





3.网易云主要接口

既然我们知道了param和encSecKey的生成原理,下面我们就介绍一下基本接口:音乐搜索接口获取音乐文件接口

  1. 音乐搜索
    接口:https://music.163.com/weapi/cloudsearch/get/web
    请求方式:post
    求情数据:
参数备注
params数据{"ids" :"[193824]","br":128000,"csrf_token":""} 经过两次AES加密的密文,密钥第一次是0CoJUm6Qyw8W8jud 第二次是ddddccccbbbbaaaa iv都是0102030405060708世界第一等是要搜索的歌名,30是返回的结果数量
encSecKey固定为814e4abf9c1c6a2af74a7ecca8843f3052626c5c054584352e3fd38a519bd659e687cf1c079e1aac5dd9d491af6b8abf92109862ada93dc7b0ef94a8ee79d557ff2a20512b87ce507e357861366b8542139c67896748852d4086104a8dfc99a2e2e0640b46a4357407b72407b2849b323425c6ed45a0222e69d551a2e59e15b7此时的第二次AES加密密钥为固定为aaaabbbbccccdddd

返回格式:json格式,里面包含有歌曲的id数据,id用于获取歌曲文件链接


2. 获取音乐文件链接

接口:https://music.163.com/weapi/song/enhance/player/url

请求方式:post

请求数据:

参数备注
paramsjson数据{"hlpretag":"","hlposttag":"","s":"世界第一等","type":"1","offset":"0","total":"true","limit":"30","csrf_token":""} 经过两次AES加密的密文,密钥第一次是0CoJUm6Qyw8W8jud 第二次是ddddccccbbbbaaaa iv都是0102030405060708193824是要歌曲id
encSecKey固定为814e4abf9c1c6a2af74a7ecca8843f3052626c5c054584352e3fd38a519bd659e687cf1c079e1aac5dd9d491af6b8abf92109862ada93dc7b0ef94a8ee79d557ff2a20512b87ce507e357861366b8542139c67896748852d4086104a8dfc99a2e2e0640b46a4357407b72407b2849b323425c6ed45a0222e69d551a2e59e15b7此时的第二次AES加密密钥为固定为aaaabbbbccccdddd

返回数据示例:

{“data”:[{“id”:193824,“url”:“http://m10.music.126.net/20210826233706/5e405016288a201701153be3bc74b384/ymusic/369d/350a/1ee0/465d7f1ada6b28c4d8c83dcc37858e84.mp3”,“br”:128000,“size”:4091445,“md5”:“465d7f1ada6b28c4d8c83dcc37858e84”,“code”:200,“expi”:1200,“type”:“mp3”,“gain”:0.0,“fee”:0,“uf”:null,“payed”:0,“flag”:0,“canExtend”:false,“freeTrialInfo”:null,“level”:“standard”,“encodeType”:“mp3”,“freeTrialPrivilege”:{“resConsumable”:false,“userConsumable”:false},“freeTimeTrialPrivilege”:{“resConsumable”:false,“userConsumable”:false,“type”:0,“remainTime”:0},“urlSource”:0}],“code”:200}


黑体那个就是纯音乐文件,打开可以直接下载或者播放

4.代码示例

如果你看不懂上面的讲解也无大碍,看懂下面的代码就可以了
生成param的java代码:


     try {
            //明文数据,两次AES加密后再发送,请根据需求进行修改;172447为歌曲id
            String data ="{\"ids\":\"[570839692]\",\"br\":128000,\"csrf_token\":\"\"}";
            Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding");
            IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes(StandardCharsets.UTF_8));
    
            //第一次加密
            SecretKeySpec key1 = new SecretKeySpec("0CoJUm6Qyw8W8jud".getBytes(StandardCharsets.UTF_8),"AES");
            cipher.init(Cipher.ENCRYPT_MODE,key1,iv);
            byte[] res = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
    
            //第二次加密(注意:要先把第一次加密结果转成base64后再进行第一次加密)
            SecretKeySpec key2 = new SecretKeySpec("aaaabbbbccccdddd".getBytes(StandardCharsets.UTF_8),"AES");
            cipher.init(Cipher.ENCRYPT_MODE,key2,iv);
            byte[] base64 =Base64.getEncoder().encode(res);//转base64
            res=cipher.doFinal(base64);
            String params= URLEncoder.encode(Base64.getEncoder().encodeToString(res),StandardCharsets.UTF_8);
            System.out.println(params);
        }
        catch (Exception e){
            e.printStackTrace();
        }

输出params为:

v1UdMgiG2PgS146seSwrcuicidNtpVNCL9ogx4K1r4Bdjp3GboV9tyIKh8PmfUduQFNgqj%2BZfcvI5vHQDEbEA1tqM56zy5yiGFcisEnuWqoqm4UI00XeDExtyra3RFHc


生成encSecKey:
已经让它固定了,不需要每次再生成了,固定为下面

814e4abf9c1c6a2af74a7ecca8843f3052626c5c054584352e3fd38a519bd659e687cf1c079e1aac5dd9d491af6b8abf92109862ada93dc7b0ef94a8ee79d557ff2a20512b87ce507e357861366b8542139c67896748852d4086104a8dfc99a2e2e0640b46a4357407b72407b2849b323425c6ed45a0222e69d551a2e59e15b7

再次强调,encSecKey固定是因为我们让第二次AES加密的密钥固定了,也就是说现在这个固定的encSecKey是AES密钥aaaabbbbccccdddd的密文

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值