| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import * as crypto from 'crypto'
- import * as https from 'https'
- import * as http from 'http'
- import { URL } from 'url'
- /**
- * 鉴权加密
- * @param {*} params
- * @returns
- */
- export function getEncodeHeader(params = {}, appKey, appSecret) {
- const timestamp = parseInt(Date.now() / 1000 + '')
- const nonce = parseInt(Math.random() * 100000 + '') + timestamp
- const header = {
- 'x-bili-accesskeyid': appKey,
- 'x-bili-content-md5': getMd5Content(JSON.stringify(params)),
- 'x-bili-signature-method': 'HMAC-SHA256',
- 'x-bili-signature-nonce': nonce + '',
- 'x-bili-signature-version': '1.0',
- 'x-bili-timestamp': timestamp
- }
- const data = []
- for (const key in header) {
- data.push(`${key}:${header[key]}`)
- }
- const signature = crypto.createHmac('sha256', appSecret).update(data.join('\n')).digest('hex')
- return {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...header,
- Authorization: signature
- }
- }
- /**
- * MD5加密
- * @param {*} str
- * @returns
- */
- export function getMd5Content(str) {
- return crypto.createHash('md5').update(str).digest('hex')
- }
- /**
- * MD5 加密
- * @param str 待加密的字符串
- * @param length 输出长度(16 或 32,默认 32 位)
- * @param isUpperCase 是否返回大写字母(默认小写)
- * @returns 加密后的 MD5 字符串
- */
- export function getMd5DetailContent(str: string, length: 16 | 32 = 32, isUpperCase: boolean = false): string {
- const hash = crypto.createHash('md5').update(str).digest('hex')
- const result = length === 16 ? hash.substring(8, 24) : hash
- return isUpperCase ? result.toUpperCase() : result
- }
- /**
- * 根据 URL 获取文件并计算 MD5 值
- * @param fileUrl 文件的网络地址
- * @returns 文件的 MD5 值(32 位字符串)
- */
- export function getFileMd5FromUrl(fileUrl: string): Promise<string> {
- return new Promise((resolve, reject) => {
- try {
- const url = new URL(fileUrl);
- // 根据协议选择模块
- const client = url.protocol === 'https:' ? https : http;
- const request = client.get(url, (response) => {
- if (response.statusCode !== 200) {
- reject(new Error(`请求失败,状态码: ${response.statusCode}`));
- response.resume(); // 消耗响应数据以释放内存
- return;
- }
- const hash = crypto.createHash('md5'); // 创建 MD5 哈希对象
- response.on('data', (chunk) => hash.update(chunk)); // 更新哈希
- response.on('end', () => resolve(hash.digest('hex'))); // 返回 32 位 MD5 字符串
- });
- request.on('error', (error) => {
- reject(new Error(`网络请求出错: ${error.message}`));
- });
- } catch (error) {
- reject(new Error(`解析 URL 出错: ${error.message}`));
- }
- });
- }
- /**
- * RSA 加密,支持大数据分块加密
- * @param data 待加密的数据
- * @param publicKey 公钥字符串
- * @param maxEncryptBlock RSA 最大加密块大小(默认 53 字节,适用于 512 位 RSA 密钥)
- * @returns Base64 编码的加密结果
- */
- export function encryptData(data: string, publicKey: string, maxEncryptBlock: number = 53): string {
- try {
- const buffer = Buffer.from(data, 'utf8')
- const dataLength = buffer.length
- let offset = 0
- const encryptedBuffers: Buffer[] = []
- while (offset < dataLength) {
- const chunkSize = Math.min(maxEncryptBlock, dataLength - offset)
- const chunk = buffer.subarray(offset, offset + chunkSize)
- const encryptedChunk = crypto.publicEncrypt(
- {
- key: publicKey,
- padding: crypto.constants.RSA_PKCS1_PADDING
- },
- chunk
- )
- encryptedBuffers.push(encryptedChunk)
- offset += chunkSize
- }
- const encryptedBuffer = Buffer.concat(encryptedBuffers)
- return encryptedBuffer.toString('base64')
- } catch (error) {
- console.error('RSA 加密失败:', error)
- throw error
- }
- }
|