签名算法

最近更新时间:2018-11-20 11:10:20

查看pdf

签名鉴权

为什么需要鉴权?

业务端购买腾讯云(对象存储)服务,来作为其业务组成的一部分(云存储或内容分发加速),并最终提供给用户。所以当用户访问腾讯云服务时,需要先征得业务端的“许可”。那么,用户如何才能向腾讯云证明自己已经得到“访问许可”了呢?

简单的说,腾讯云和业务端约定了一套规则,通过这套规则,业务端可以产生一个“钥匙”。当用户需要访问业务端购买的腾讯云服务时,业务端会将这个钥匙传递给用户,然后用户拿着这个钥匙去向腾讯云“证明”自己已经拿到了“访问许可”。腾讯云收到用户的请求后,会先鉴别“钥匙”是否有效,若有效,则允许访问云服务,若无效,则返回 Authorization 错误消息。

这套规则,就是腾讯云的“鉴权系统”,这把“钥匙”,就是下文要解释的“签名”。

签名有哪几种?

签名本质上是一个加密的字符串,目前在腾讯云中,分为多次有效签名单次有效签名

多次有效签名:签名中部分不绑定文件 fileid ,部分绑定文件 fileid ,开启token防盗链的下载、文件简单上传、文件分片上传可以绑定fileid,同时支持前缀匹配。多次有效签名需要设置一个大于当前时间的有效期,有效期内此签名可多次使用,有效期最长可设置三个月。

单次有效签名:签名中绑定文件 fileid ,有效期必须设置为0,此签名只可使用一次,且只能应用于被绑定的文件或文件夹操作。

哪些场景需要用到签名?

腾讯云对象存储(COS)对签名的适用场景做了如下限制:

场景 适用签名 签名中是否需要绑定 fileid
下载(不开启 token 防盗链) 不验证签名 ——
下载(开启 token 防盗链) 多次有效签名 可选
简单上传文件 多次有效签名 可选
分片上传文件 多次有效签名 可选
查询目录、文件属性 多次有效签名
创建目录 多次有效签名
删除目录、文件 单次有效签名
更新文件属性 单次有效签名
移动(重命名)文件 单次有效签名

如何使用签名来完成鉴权?

腾讯云对象存储通过签名来验证请求的合法性。业务端通过将签名授权给用户端,使其具备上传下载及管理指定资源的权限。

当用户使用 RESTful API 对腾讯云对象存储资源进行操作时,必须要在每个 Http/Https 请求的 Header 中填写 Host 和 Authorization,其中的 Authorization 参数,即为“签名算法”最终得到的 sign 字符串。

参数名称 必选 类型 描述
Host String 文件云服务器域名,固定为[region].file.myqcloud.com
Authorization String 用户的有效签名,用于鉴权

腾讯云对象存储目前提供了 COS 签名工具 供用户生成签名,如有需要可前往使用。

签名算法

腾讯云的各类 SDK 已经提供了标准的签名计算方法,业务端只需填写相关参数,即可得到签名字符串。用户也可以根据 RESTful API 自行计算签名。

对于签名的计算过程,可简单分为如下三个步骤:获取签名所需信息,拼接明文字符串,将明文字符串转化为签名

获取签名所需信息

生成签名所需信息包括项目 ID(App Id),空间名称(Bucket,文件资源的组织管理单元),项目的 Secret ID 和 Secret Key。获取这些信息的方法如下:

1) 登录腾讯云对象存储,进入对象存储空间;

2) 如开发者未创建空间,可添加空间,空间名称(Bucket)由用户自行输入;

3) 单击【获取 API 密钥】,获取 App Id,Secret ID 和 Secret Key。

拼接明文字符串 Original

明文字符串 Original 按照签名的类型可划分为“多次”和“单次”有效签名。

拼接多次有效签名串 multi_effect_signature :

Original = "a=[appid]&b=[bucket]&k=[SecretID]&e=[expiredTime]&t=[currentTime]&r=[rand]&f="

拼接单次有效签名串 once_signature :

Original = "a=[appid]&b=[bucket]&k=[SecretID]&e=[expiredTime]&t=[currentTime]&r=[rand]&f=[fileid]"

签名串中各字段含义如下:

字段 解释
a 开发者的项目 ID,接入对象存储服务创建空间时系统生成的唯一标识项目的 ID,即 App Id
b 空间名称 Bucket
k 项目的 Secret ID
t 当前时间戳,是一个符合 Unix Epoch 时间戳规范的数值,单位为秒
e 多次有效签名时,e 为签名的失效时刻,是一个符合Unix Epoch时间戳规范的数值,单位为秒。e 的计算方式为 e = t + 签名有效时长。签名有效时长最大取值为7776000(90天);单次签名时,e 必须设置为0
r 随机串,无符号10进制整数,用户需自行生成,最长 10 位
f fileid ,唯一标识存储资源的相对路径。格式为 /appid/bucketname/dirname/[filename],并且需要对其中非 '/' 字符进行 UrlEncode 编码。 当操作对象为 文件夹时,filename 缺省。filename 中要包含文件后缀名。

注意:

当签名类型需要绑定 fileid 时,f 字段请按要求赋值。

拼接单次有效签名的签名串时,过期时间 e 必须设置为0,以保证此签名只能针对固定资源使用一次;

拼接多次有效签名的签名串时,过期时间 e 的单位为秒,不同编程语言获得的系统 Unix 时间戳单位可能有所差异(比如 Java 是毫秒),但都请转化为秒。

多次/单次有效签名的具体适用场景参见 哪些场景需要用到签名?

将明文字符串转化为签名

拼接好签名的明文字符串 Original 后,用已经获取的 SecretKey 对明文串进行 HMAC-SHA1 加密,得到 SignTmp:

SignTmp = HMAC-SHA1(SecretKey, Original)

将密文串 SignTmp 放在明文串 Origin 前面,拼接后进行 Base64Encode 算法,得到最终的签名 Sign:

Sign = Base64 (append(SignTmp, Original))

注 1:此处使用的是标准的 Base64 编码,不是 urlsafe 的 Base64 编码。

注 2:由于使用了 HMAC 算法,计算 SignTmp 的结果为二进制字符串,因此建议将算法写在同一函数中实现。单独输出 SignTmp 可能导致拼接后的字串有误。

示例

本节介绍生成签名的算法实例,实例中使用 PHP 语言(若开发者使用其他开发语言,请使用对应的函数)。

获取签名所需信息

获取得到的签名所需信息如下

项目 ID:200001

空间名称 Bucket:newbucket

Secret ID:AKIDUfLUEUigQiXqm7CVSspKJnuaiIKtxqAv

Secret Key:bLcPnl88WU30VY57ipRhSePfPdOfSruK

拼接签名串

拼接的多次有效签名串 multi_effect_signature 如下:

a=200001&b=newbucket&k=AKIDUfLUEUigQiXqm7CVSspKJnuaiIKtxqAv&e=1437995704&t=1437995644&r=2081660421&f=

拼接的单次有效签名串 once_signature 如下:

a=200001&b=newbucket&k=AKIDUfLUEUigQiXqm7CVSspKJnuaiIKtxqAv&e=0&t=1437995645&r=1166710792&f=/200001/newbucket/tencent_test.jpg

$appid = "200001";
$bucket = "newbucket";
$secret_id = "AKIDUfLUEUigQiXqm7CVSspKJnuaiIKtxqAv";
$secret_key = "bLcPnl88WU30VY57ipRhSePfPdOfSruK";
$expired = time() + 60;
$onceExpired = 0;
$current = time();
$rdm = rand();
$fileid = "/200001/newbucket/tencent_test.jpg";

$multi_effect_signature = 'a='.$appid.'&b='.$bucket.'&k='.$secret_id.'&e='.$expired.'&t='.$current.'&r='.$rdm.'&f=';

$once_signature=
'a='.$appid.'&b='.$bucket.'&k='.$secret_id.'&e='.$onceExpired.'&t='.$current.'&r='.$rdm.'&f='.$fileid;

生成签名

$multi_effect_signature = base64_encode(hash_hmac('SHA1', $multi_effect_signature, $secret_key, true).$multi_effect_signature);

$once_signature = base64_encode(hash_hmac('SHA1',$once_signature,$secret_key, true).$once_signature);

echo $multi_effect_signature."\n"; 

echo $once_signature."\n";

最终得到的多次有效签名为:

v6+um3VE3lxGz97PmnSg6+/V9PZhPTIwMDAwMSZiPW5ld2J1Y2tldCZrPUFLSURVZkxVRVVpZ1FpWHFtN0NWU3NwS0pudWFpSUt0eHFBdiZlPTE0NzA3MzcwMDAmdD0xNDcwNzM2OTQwJnI9NDkwMjU4OTQzJmY9

单次有效签名为:

CkZ0/gWkHy3f76ER7k6yXgzq7w1hPTIwMDAwMSZiPW5ld2J1Y2tldCZrPUFLSURVZkxVRVVpZ1FpWHFtN0NWU3NwS0pudWFpSUt0eHFBdiZlPTAmdD0xNDcwNzM2OTQwJnI9NDkwMjU4OTQzJmY9LzIwMDAwMS9uZXdidWNrZXQvdGVuY2VudF90ZXN0LmpwZw==

如果有其他疑问,您也可以在问答社区中寻求帮助。前往问答社区 >