tencentcloud-sdk-nodejs-intl-en
Version:
125 lines (108 loc) • 4.31 kB
JavaScript
const TencentCloudSDKHttpException = require("./exception/tencent_cloud_sdk_exception");
const crypto = require('crypto');
const { URL } = require('url')
/**
* @inner
*/
class Sign {
static sign(secretKey, signStr, signMethod) {
let signMethodMap = {
HmacSHA1: "sha1",
HmacSHA256: "sha256"
};
if (!signMethodMap.hasOwnProperty(signMethod)) {
throw new TencentCloudSDKHttpException("signMethod invalid, signMethod only support (HmacSHA1, HmacSHA256)");
}
let hmac = crypto.createHmac(signMethodMap[signMethod], secretKey || "");
return hmac.update(Buffer.from(signStr, 'utf8')).digest('base64')
}
static sign3({
method = 'POST',
url = '',
payload,
timestamp,
service,
secretId,
secretKey,
multipart,
boundary,
headers: configHeaders = {},
}) {
const urlObj = new URL(url)
const contentType = configHeaders["Content-Type"]
// 通用头部
let headers = ''
let signedHeaders = ''
if (method === 'GET') {
signedHeaders = 'content-type'
headers = `content-type:${contentType}\n`
} else if (method === 'POST') {
signedHeaders = 'content-type'
if (multipart) {
headers = `content-type:multipart/form-data; boundary=${boundary}\n`
} else {
headers = `content-type:${contentType}\n`
}
}
headers += `host:${urlObj.hostname}\n`
signedHeaders += ';host'
const path = urlObj.pathname
const querystring = urlObj.search.slice(1)
let payload_hash = ''
if (multipart) {
const hash = crypto.createHash('sha256')
hash.update(`--${boundary}`)
for (let key in payload) {
const content = payload[key]
if (Buffer.isBuffer(content)) {
hash.update(`\r\nContent-Disposition: form-data; name="${key}"\r\nContent-Type: application/octet-stream\r\n\r\n`)
hash.update(content)
hash.update('\r\n')
} else if (typeof content === 'string') {
hash.update(`\r\nContent-Disposition: form-data; name="${key}"\r\n\r\n`)
hash.update(`${content}\r\n`)
}
hash.update(`--${boundary}`)
}
hash.update(`--\r\n`)
payload_hash = hash.digest('hex')
} else {
const hashMessage = Buffer.isBuffer(payload) ? payload : JSON.stringify(payload)
payload_hash = payload ? getHash(hashMessage) : getHash('')
}
const canonicalRequest =
method + '\n' +
path + '\n' +
querystring + '\n' +
headers + '\n' +
signedHeaders + '\n' +
payload_hash
const date = getDate(timestamp)
const StringToSign =
'TC3-HMAC-SHA256' + '\n' +
timestamp + '\n' +
`${date}/${service}/tc3_request` + '\n' +
getHash(canonicalRequest)
const kDate = sha256(date, 'TC3' + secretKey)
const kService = sha256(service, kDate)
const kSigning = sha256('tc3_request', kService)
const signature = sha256(StringToSign, kSigning, 'hex')
return `TC3-HMAC-SHA256 Credential=${secretId}/${date}/${service}/tc3_request, SignedHeaders=${signedHeaders}, Signature=${signature}`
}
}
function sha256(message, secret = '', encoding) {
const hmac = crypto.createHmac('sha256', secret)
return hmac.update(message).digest(encoding)
}
function getHash(message, encoding = 'hex') {
const hash = crypto.createHash('sha256')
return hash.update(message).digest(encoding)
}
function getDate(timestamp) {
const date = new Date(timestamp * 1000)
const year = date.getUTCFullYear()
const month = ('0' + (date.getUTCMonth() + 1)).slice(-2)
const day = ('0' + date.getUTCDate()).slice(-2)
return `${year}-${month}-${day}`
}
module.exports = Sign;