简悦音乐播放器用到的相关技术点都在这里了(二):音乐API加密算法实现

关于某云音乐API接口加密算法的实现,网上已经有很多实现的例子,这里用dart代码实现一遍,以某云音乐搜索接口为例,核心参数为:paramsencSecKey

{
    's': keyword, // 搜索的关键字
    'type': 1,// 搜索的类型
    'limit': 30,//当前页的条数
    'total': 'true',
    'offset': 0 // 分页页码
}

其中params参数是将以上参数通过aes-cbc-128算法两次加密所得,这里用到插件Cipher2,此插件暂时不支持mac,修改后做了个兼容。

  static const String nonce = '0CoJUm6Qyw8W8jud';
  static const String iv = "0102030405060708";
  static const String randomString =
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  /// 参数 queryData:就是上面的json数据
  static Future<Map<String, dynamic>> aesEncrypt(String queryData) async {
    
    // 调用createSecretKey()返回一个16位的随机数
    String key = createSecretKey();

    // 兼容一下MAC上的加密
    if (Device.isDesktop) {
      String encryptedString = await Cipher2Mac.encryptAesCbc128Padding7ForMac(
          queryData, NeteaseEncryptUtil.nonce, NeteaseEncryptUtil.iv);
      String value = await Cipher2Mac.encryptAesCbc128Padding7ForMac(
          encryptedString, key, NeteaseEncryptUtil.iv);
      return {"params": value, 'encSecKey': rsaEncrypt(key)};
    }

    // 第一次加密,用到的 nonce 和 iv,这两个是固定的
    String encryptedString = await Cipher2.encryptAesCbc128Padding7(
        queryData, NeteaseEncryptUtil.nonce, NeteaseEncryptUtil.iv);

    // 第二次加密,key:是上面生成的随机数,iv:是固定值
    String value = await Cipher2.encryptAesCbc128Padding7(
        encryptedString, key, NeteaseEncryptUtil.iv);

    // 调用 rsaEncrypt 函数得到 encSecKey的值
    return {"params": value, 'encSecKey': rsaEncrypt(key)};
  }

  // 对 randomString 随机返回一个16位的数
  static String createSecretKey() => List.generate(
      16,
      (index) => NeteaseEncryptUtil.randomString[
          Random().nextInt(NeteaseEncryptUtil.randomString.length)]).join();

encSecKey参数则是将createSecretKey()返回的随机数通过调用static rsaEncrypt(String text)函数和返回得到,下面该函数的实现:

    
  static const String pubKey = "010001";
  static const String modulus =
      "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7";

  static rsaEncrypt(String text) {
    // 字符串反转
    text = reverse(text);

    // 将16进制字符串转成 BigInt 类型
    BigInt biText = BigInt.parse(strToHex(text), radix: 16);

    // 将上面固定值 pubKey 转成 BigInt 类型
    BigInt biEx = BigInt.parse(NeteaseEncryptUtil.pubKey, radix: 16);

    // 将上面固定值 modulus 转成 BigInt 类型
    BigInt biMod = BigInt.parse(NeteaseEncryptUtil.modulus, radix: 16);

    // 幂次求模:biText 的 biEx 次幂,再对 biMod 求模。
    // 如:a.modPow(3,5) 先进行逆运算再求模运算,对a进行3次方后除以5取余数。
    BigInt biRet = biText.modPow(biEx, biMod);

    // zFill函数作用是长度不满足256补0
    return zFill(biRet.toRadixString(16));
  }
  
  // 转成16进制字符串
  static strToHex(String text) {
    String res = "";
    for (int i = 0; i < text.length; i++) {
      res = res + text.codeUnitAt(i).toRadixString(16);
    }
    return res;
  }
  
  // 长度不满足256补0
  static String zFill(String str) {
    while (str.length < 256) {
      str = "0" + str;
    }
    return str;
  }

接下来测试一下加密算法是否正确,

// 这个是抽取的工具类,为调用入口
NetUtil.search("旧梦一场", AudioSource.netease);

具体调用实现,这是为了方便展示,将limit设置默认为1条数据。

  Future<List<Map<String, dynamic>>?> search(String keyword,
      {int limit = 1, int type = 1, int page = 0}) async {
    RequestOptions options = RequestOptions(
        path: "http://music.163.com/weapi/cloudsearch/pc", method: "post");
    Map queryData = {
      's': keyword,
      'type': type,
      'limit': limit,
      'total': 'true',
      'offset': page
    };
    // NeteaseEncryptUtil 加密算法实现的工具类
    // 具体实现:https://github.com/joedrm/weapon/blob/master/lib/net/netease_encrypt_util.dart
    options.queryParameters =
        await NeteaseEncryptUtil.aesEncrypt(json.encode(queryData));
    var result = await dio.fetch(options);
    print(result.data);
  }

成功返回的json数据

{"result":{"searchQcReminder":null,"songs":[{"name":"旧梦一场","id":1450163801,"pst":0,"t":0,"ar":[{"id":35264840,"name":"钟意","tns":[],"alias":[]}],"alia":[],"pop":100.0,"st":0,"rt":"","fee":8,"v":13,"crbt":null,"cf":"","al":{"id":89819948,"name":"旧梦一场","picUrl":"http://p4.music.126.net/IZBZ5GpCJFTShxMcJrKTzw==/109951165008690592.jpg","tns":[],"pic_str":"109951165008690592","pic":109951165008690592},"dt":174915,"h":{"br":320000,"fid":0,"size":6999405,"vd":-41240.0,"sr":48000},"m":{"br":192000,"fid":0,"size":4199661,"vd":-38649.0,"sr":48000},"l":{"br":128000,"fid":0,"size":2799789,"vd":-36967.0,"sr":48000},"sq":{"br":979427,"fid":0,"size":21414694,"vd":-41237.0,"sr":48000},"hr":{"br":1750048,"fid":0,"size":38263929,"vd":-41229.0,"sr":48000},"a":null,"cd":"01","no":1,"rtUrl":null,"ftype":0,"rtUrls":[],"djId":0,"copyright":0,"s_id":0,"mark":536879104,"originCoverType":1,"originSongSimpleData":null,"tagPicList":null,"resourceState":true,"version":13,"songJumpInfo":null,"entertainmentTags":null,"single":0,"noCopyrightRcmd":null,"rtype":0,"rurl":null,"mst":9,"cp":1416832,"mv":0,"publishTime":0,"privilege":{"id":1450163801,"fee":8,"payed":0,"st":0,"pl":128000,"dl":0,"sp":7,"cp":1,"subp":1,"cs":false,"maxbr":999000,"fl":128000,"toast":false,"flag":4,"preSell":false,"playMaxbr":999000,"downloadMaxbr":999000,"maxBrLevel":"hires","playMaxBrLevel":"hires","downloadMaxBrLevel":"hires","plLevel":"standard","dlLevel":"none","flLevel":"standard","rscl":null,"freeTrialPrivilege":{"resConsumable":false,"userConsumable":false,"listenType":null},"chargeInfoList":[{"rate":128000,"chargeUrl":null,"chargeMessage":null,"chargeType":0},{"rate":192000,"chargeUrl":null,"chargeMessage":null,"chargeType":1},{"rate":320000,"chargeUrl":null,"chargeMessage":null,"chargeType":1},{"rate":999000,"chargeUrl":null,"chargeMessage":null,"chargeType":1},{"rate":1999000,"chargeUrl":null,"chargeMessage":null,"chargeType":1}]}}],"songCount":300},"code":200}

界面上的搜索效果:
在这里插入图片描述

完整实现在这里github

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值