Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined #524

Closed
catlair opened this issue Oct 29, 2022 · 16 comments
Closed

undefined #524

catlair opened this issue Oct 29, 2022 · 16 comments
Labels
账号相关/Account 接口:账号或登录 新增/Add 添加或修改新的内容

Comments

@catlair
Copy link
Contributor

catlair commented Oct 29, 2022

No description provided.

@SocialSisterYi
Copy link
Owner

感谢提供

@SocialSisterYi SocialSisterYi added the 新增/Add 添加或修改新的内容 label Oct 29, 2022
@SocialSisterYi
Copy link
Owner

这个wasm的具体实现有人研究过吗,是加密还是hash还是编码呢?

@SocialSisterYi SocialSisterYi added the 账号相关/Account 接口:账号或登录 label Nov 4, 2022
@z0z0r4
Copy link
Collaborator

z0z0r4 commented Dec 26, 2022

更新 Cookie 中的 source 从哪里获得呢?

@Nemo2011
Copy link
Contributor

await wasmInit.default();
const correspondPath = wasmInit.encrypt({
  data: convertToHex(`refresh_${timestamp}`),
  digest: 'SHA256',
});

const 目标URL = 'https://www.bilibili.com/correspond/1/' + correspondPath;

function convertToHex(str: string) {
  return str.split('').reduce((i, t) => i + t.charCodeAt(0).toString(16), '');
}

这里的 timestamp 是指秒还是毫秒?

@catlair
Copy link
Contributor Author

catlair commented Jan 20, 2023

await wasmInit.default();
const correspondPath = wasmInit.encrypt({
  data: convertToHex(`refresh_${timestamp}`),
  digest: 'SHA256',
});

const 目标URL = 'https://www.bilibili.com/correspond/1/' + correspondPath;

function convertToHex(str: string) {
  return str.split('').reduce((i, t) => i + t.charCodeAt(0).toString(16), '');
}

这里的 timestamp 是指秒还是毫秒?

这是上下文介绍过的

image

@catlair
Copy link
Contributor Author

catlair commented Jan 24, 2023

wasm 使用 rust 写的,用到了 wasm-bindgen https://github.com/rustwasm/wasm-bindgen。这样打包除了生成 wasm 文件,还会生成一个 js 文件,wasm_ras_umd.js 应该就是那个文件再压缩和 umd 化得到的(原js是esm的)。

@My-Responsitories
Copy link

wasm 使用 rust 写的,用到了 wasm-bindgen https://github.com/rustwasm/wasm-bindgen。这样打包除了生成 wasm 文件,还会生成一个 js 文件,wasm_ras_umd.js 应该就是那个文件再压缩和 umd 化得到的(原js是esm的)。

删除_umd即可获取esm版的js: wasm_ras.js

@KudouRan
Copy link

KudouRan commented Jan 25, 2023

虽然还没有大佬提供直接的方案,不过直接使用它的wasm也行。浏览器可以直接使用,无需处理。node 按照自己的情况更改,比如可能需要把 chrome 请求的代码删除,TextEncode 从 util 导入(低版本),url 补全 https 协议等。

这里是放在 github 的一个 node/浏览器 demo。

https://wasm-rsa.vercel.app/api/rsa?t=1123

python 等语言可以把 wasm_ras.js 胶水代码转为 py 也可以直接利用 wasm

@0f-0b
Copy link
Contributor

0f-0b commented May 7, 2023

逆向 Wasm 发现是 RSA-OAEP 加密,用 Web Crypto 重实现如下。

const publicKey = await crypto.subtle.importKey(
  "jwk",
  {
    kty: "RSA",
    n: "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
    e: "AQAB",
  },
  { name: "RSA-OAEP", hash: "SHA-256" },
  true,
  ["encrypt"],
);

async function getCorrespondURL(timestamp) {
  const data = new TextEncoder().encode(`refresh_${timestamp}`);
  const encrypted = new Uint8Array(
    await crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data),
  );
  return `https://www.bilibili.com/correspond/1/${
    encrypted.reduce((str, c) => str + c.toString(16).padStart(2, "0"), "")
  }`;
}

console.log(await getCorrespondURL(Date.now()));

@SocialSisterYi
Copy link
Owner

相关内容已经在此 commit 中完成 a46f140

详见 https://github.com/SocialSisterYi/bilibili-API-collect/blob/a46f140fde73530868ce9db5f613deed8d5c645e/docs/login/cookie_refresh.md

感谢你们提供的研究报告以及逆向工程(抱

@SocialSisterYi SocialSisterYi unpinned this issue May 19, 2023
@Ladtor
Copy link

Ladtor commented Aug 15, 2023

按照教程接入之后,一直得到86095结果,有遇到相同问题的同学吗?

@Ladtor
Copy link

Ladtor commented Aug 15, 2023

import binascii
import re
import time

import requests
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA

key = RSA.importKey('''\
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----''')


def getCorrespondPath():
    ts = round(time.time() * 1000)
    cipher = PKCS1_OAEP.new(key, SHA256)
    encrypted = cipher.encrypt(f'refresh_{ts}'.encode())
    return binascii.b2a_hex(encrypted).decode()


def get_refresh_csrf(correspond_path, cookie_dict):
    response = requests.get(url=f'https://www.bilibili.com/correspond/1/{correspond_path}', cookies=cookie_dict)
    if response.status_code != 200:
        raise Exception(f'correspondPath错误或过期 {response.status_code}')
    html = response.text
    pattern = r'<div\s+id="1-name">\s*(.*?)\s*</div>'
    match = re.search(pattern, html)
    if match:
        div_contents = match.group(1)
        return div_contents
    else:
        raise Exception(f'未获取到 refresh_csrf {html}')


def get_new_cookie(refresh_token, refresh_csrf, cookie_dict):
    data = {'csrf': cookie_dict['bili_jct'], 'refresh_csrf': refresh_csrf, 'source': 'main_web', 'refresh_token': refresh_token}
    response = requests.post('https://passport.bilibili.com/x/passport-login/web/cookie/refresh', data=data, headers={'Content-Type': 'application/x-www-form-urlencoded'},
                             cookies=cookie_dict)
    json = response.json()
    if json['code'] == 0:
        refresh_token = json['data']['refresh_token']
        cookies_dict = []
        for name, value in response.cookies.items():
            cookies_dict[name] = value
        return refresh_token, cookies_dict
    elif json['code'] == 86095:
        raise Exception(f'refresh_csrf 错误或 refresh_token 与 cookie 不匹配')
    else:
        raise Exception(f'刷新cookie失败 {json}')


def confirm_refresh(refresh_token_old, cookie_dict):
    data = {'csrf': cookie_dict['bili_jct'], 'refresh_token': refresh_token_old}
    response = requests.post('https://passport.bilibili.com/x/passport-login/web/confirm/refresh', data=data, headers={'Content-Type': 'application/x-www-form-urlencoded'},
                             cookies=cookie_dict)
    json = response.json()
    if json['code'] != 0:
        raise Exception(f'确认刷新cookie失败 {json}')


def check_login_user_info(cookie_dict):
    response = requests.get('https://api.bilibili.com/x/web-interface/nav', cookies=cookie_dict)
    json = response.json()
    if json['code'] != 0:
        raise Exception(f'新cookie检测异常 {json} {cookie_dict}')


# https://socialsisteryi.github.io/bilibili-API-collect/docs/login/cookie_refresh.html
# refresh_token: localStorage 中的ac_time_value
def refresh_cookie(refresh_token, cookie_dict):
    correspond_path = getCorrespondPath()
    refresh_csrf = get_refresh_csrf(correspond_path, cookie_dict)
    refresh_token_old = refresh_token
    new_refresh_token, new_cookie_dict = get_new_cookie(refresh_token_old, refresh_csrf, cookie_dict)
    confirm_refresh(refresh_token_old, new_cookie_dict)  # 这一步需要新的 Cookie 以及旧的 refresh_token
    check_login_user_info(new_cookie_dict)
    return new_refresh_token, new_cookie_dict

@catlair
Copy link
Contributor Author

catlair commented Aug 15, 2023

按照教程接入之后,一直得到86095结果,有遇到相同问题的同学吗?

我认为你应该新建一个 issue

@alphadoiy
Copy link

请问localStorage 中的ac_time_value怎么获取

@z0z0r4
Copy link
Collaborator

z0z0r4 commented Oct 4, 2023

请问localStorage 中的ac_time_value怎么获取

https://nemo2011.github.io/bilibili-api/#/get-credential

@catlair catlair changed the title web 端 cookie 刷新方式 undefined Dec 17, 2023
@JueShiBaWangLong
Copy link

虽然还没有大佬提供直接的方案,不过直接使用它的wasm也行。浏览器可以直接使用,无需处理。node 按照自己的情况更改,比如可能需要把 chrome 请求的代码删除,TextEncode 从 util 导入(低版本),url 补全 https 协议等。

这里是放在 github 的一个 node/浏览器 demo。

https://wasm-rsa.vercel.app/api/rsa?t=1123

python 等语言可以把 wasm_ras.js 胶水代码转为 py 也可以直接利用 wasm

大佬有没有Java版的代码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
账号相关/Account 接口:账号或登录 新增/Add 添加或修改新的内容
Projects
None yet
Development

No branches or pull requests

10 participants