金山云KS3 V4签名 get 文件 Python脚本 demo

https://docs.ksyun.com/documents/6890

V4签名计算:

  1. 签名信息放在请求头中(纯脚本,非面向对象)
    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    #  @Time: 2021/7/2 21:04
    #  @Author:zhangmingda
    #  @File: test_v4_signature_get.py
    #  @Software: PyCharm
    #  Description:
    
    from urllib.request import quote
    import hashlib
    import hmac
    import datetime
    import requests
    
    '''
    CanonicalRequest = HTTPRequestMethod + '\n'
            + CanonicalURI + '\n'
            + CanonicalQueryString + '\n'
            + CanonicalHeaders + '\n'
            + SignedHeaders + '\n'
            + HexEncode(Sha256Hash(RequestPayload))
    '''
    
    now_utc = datetime.datetime.utcnow()
    datetime_utc = now_utc.strftime('%Y%m%dT%H%M%SZ')
    date_utc = now_utc.strftime('%Y%m%d')
    
    hosts = {
        'BEIJING': "ks3-cn-beijing.ksyun.com"
    }
    
    region = 'BEIJING'
    bucket = 'zhangmingda'
    ks3key = 'life-bbs/测试.txt'
    service = 'ks3'
    method = 'GET'
    
    host = hosts.get(region)
    
    
    #  生成标准化请求头
    def generate_canonical_headers(**headers):
        '''
        :param headers: 所有用来签名的请求头
        :return: 返回小写请求头排序后的key:value 字符串,每个key:value 之间\n换行
        '''
        sorted_headers = ''                                         # 准备标准请求头key+value字符串
        sorted_signed_headers = ''                                  # 准备签名的请求头key组合字符串
        header_keys = headers.keys()                                # 获取请求头所有key
        lower_headers = {}                                          # 准备存放小写请求头和值的字典
        for header in header_keys:                                  # 把大写请求头字典都转换为小写请求头字典
            lower_headers[header.lower()] = headers.get(header)
        sorted_lower_header_keys = sorted(lower_headers.keys())     # 把签名的请求头排序
    
        '''排序后的请求头和值进行组合字符串'''
        for lower_header in sorted_lower_header_keys:
            sorted_headers += lower_header + ':' + str(lower_headers[lower_header]).strip() + '\n'
            sorted_signed_headers += lower_header + ";"
        # print("============请求头排序==============")
        # print(sorted_headers)
        # print('------被签名的请求头----')
        # print(sorted_signed_headers)
        # print("==========请求头排序end============")
        sorted_lower_headers = {
            'sorted_headers': sorted_headers,               # 签名的请求头key 和 value
            'signed_headers': sorted_signed_headers[:-1]    # 被签名的请求头字符串组合,最后一个分号; 不要
        }
        return sorted_lower_headers
    
    # 创建规范化请求查询字符串
    def generate_canonical_querystring(**params):
        '''
        :param params: 查询字符串字典
        :return: url编码后的查询字符串key1=value1&key2=value2 ...
        '''
        sorted_params = ''
        sorted_param_keys = sorted(params.keys())
        for param in sorted_param_keys:
            sorted_params += quote(param) + '=' + quote(params.get(param), safe='') + '&'  # 查询字符串中的值任何字符串都进行URL编码
        return sorted_params[:-1]
    
    
    # 十六进制请求体Sha256Hash值--->请求体用
    def binary_data_sha256_hex(binary_data=''.encode()):
        '''
        :param args:
        :param forms:
        :return: 返回请求体内容的sha256 哈希值
        '''
        sha256 = hashlib.sha256()
        sha256.update(binary_data)
        return sha256.hexdigest().lower()
    
    
    # 构建被签名字符串,把标准请求canonical_request 哈希取16进制用
    def str_sha256_hex(string=''):
        '''
        :param string:
        :return: 字符串的sha256哈希值
        '''
        sha256 = hashlib.sha256()
        sha256.update(string.encode())
        return sha256.hexdigest()
    
    
    # 第二步构建签名key用
    def encode_string_to_hmac_256_digest(encode_salt, msg, digestmod=hashlib.sha256):
        '''
        :param encode_salt: 盐
        :param msg: 字符串信息
        :param digestmod: 摘要算法
        :return: HMAC-SHA256 加盐哈希后的字节
        '''
        digest_maker = hmac.new(encode_salt, msg.encode(), digestmod=digestmod)
        return digest_maker.digest()
    
    
    '''========================= 1. 准备被签名字符串 StringToSign计算=============================='''
    '''======== 1.1 规范化请求变量准备 =========='''
    sign_method = method                                    # 1.1.1 HTTP方法
    canonical_uri = '/' + bucket + '/' + ks3key             # 1.1.2 资源URI
    encode_uri = quote(canonical_uri, safe=";/?:@&=+$,")    # 将URL编码成%字符串格式
    query_params = {}
    canonical_querystring = generate_canonical_querystring(**query_params)  # 1.1.3 查询字符串
    payload_sha256_hex = binary_data_sha256_hex()          # 1.1.5 请求体sha256 十六进制HASH值
    signature_headers = {
        # 'x-kss-content-sha256': 'UNSIGNED-PAYLOAD',       # 请求体不参与鉴权的时候,如此传参
        'x-kss-content-sha256': payload_sha256_hex,
        'Host': host,
        # 'X-kss-date': datetime_utc                        # 如果请求头含Date 字段,这里日期可以不参与签名计算,注释即可
    }
    sorted_lower_headers = generate_canonical_headers(**signature_headers)
    canonical_headers = sorted_lower_headers.get('sorted_headers')  # 1.1.4 小写排序后的请求头key:value
    signed_headers = sorted_lower_headers.get('signed_headers')     # 1.1.5 小写排序后的签名头
    
    ''' 1.1 规范化请求CanonicalRequest计算方法'''
    canonical_request = method + '\n'\
                        + encode_uri + '\n' \
                        + canonical_querystring + '\n' \
                        + canonical_headers + '\n' \
                        + signed_headers + '\n' \
                        + payload_sha256_hex    # 请求体不参与签名 时 : + 'UNSIGNED-PAYLOAD'
    print("==========================规范化化请求=================================")
    print(canonical_request)
    print("==========================规范化请求done=================================")
    
    # 1.2 StringToSign
    algorithm = 'KSS4-HMAC-SHA256'
    requestdatetime = datetime_utc
    credentialscope = date_utc + "/" + region + "/" + service + "/kss4_request"
    canonical_request_sha256_hex = str_sha256_hex(canonical_request)
    string_tosign = algorithm + '\n'\
                    + requestdatetime + '\n'\
                    + credentialscope + '\n'\
                    + canonical_request_sha256_hex
    print('================被签名的字符串======================')
    print(string_tosign)
    print('================被签名的字符串done======================')
    #  =========================第二步准备签名KEY=================================
    '''
    kSecret = your Secret Key 
    kDate = HMAC("KSS4" + kSecret, Date)
    kRegion = HMAC(kDate, Region)
    kService = HMAC(kRegion, Service)
    kSigning = HMAC(kService, "kss4_request")
    '''
    
    
    # 创建签名KEY的方法
    def generate_signing_key(sk, date_utc, region, service, termchar='kss4_request'):
        k_secret = "KSS4" + sk
        k_date = encode_string_to_hmac_256_digest(k_secret.encode(), date_utc)
        k_region = encode_string_to_hmac_256_digest(k_date, region)
        k_service = encode_string_to_hmac_256_digest(k_region, service)
        k_signing = encode_string_to_hmac_256_digest(k_service, termchar)
        return k_signing
    
    
    # 创建签名的方法
    def generate_signature(signing_key, string_tosign):
        digest_maker = hmac.new(signing_key, string_tosign.encode(), digestmod=hashlib.sha256)
        hex_signature = digest_maker.hexdigest()
        # print('hex_signature:', digest_maker.hexdigest())
        return hex_signature
    
    if __name__ == '__main__':
        ak = 'XXXXXXXXXXXX'
        sk = 'XXXXXXXXXXXXXXXX'
        signing_key = generate_signing_key(sk, date_utc, region, service)
        signature = generate_signature(signing_key, string_tosign)
        request_headers = {
            'Authorization': "KSS4-HMAC-SHA256 Credential="
                             + ak + '/'
                             + credentialscope + ", "
                             + "SignedHeaders="
                             + signed_headers + ', '
                             + 'Signature=' + signature,
            'Date': datetime_utc
        }
        request_headers.update(signature_headers)
        # 通过通过标准的 HTTP Authorization 头发送签名请求
        url1 = "http://" + host + '/' + bucket + '/' + ks3key
        req = requests.get(url1, headers=request_headers)
        print(req.status_code)
        print(req.text)
        print(req.content.decode('GB2312'))

    金山云KS3 V4签名 get 文件 Python脚本  demo

     

     

  2. 签名信息放在URL 查询字符串中(纯脚本,非面向对象)
    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    #  @Time: 2021/7/2 21:04
    #  @Author:zhangmingda
    #  @File: test_v4_signature_get.py
    #  @Software: PyCharm
    #  Description:
    
    from urllib.request import quote
    import hashlib
    import hmac
    import datetime
    import requests
    
    '''
    CanonicalRequest = HTTPRequestMethod + '\n'
            + CanonicalURI + '\n'
            + CanonicalQueryString + '\n'
            + CanonicalHeaders + '\n'
            + SignedHeaders + '\n'
            + HexEncode(Sha256Hash(RequestPayload))
    '''
    
    now_utc = datetime.datetime.utcnow()
    datetime_utc = now_utc.strftime('%Y%m%dT%H%M%SZ')
    date_utc = now_utc.strftime('%Y%m%d')
    
    regions = {
        'ks3-cn-beijing.ksyun.com': "BEIJING"
    }
    
    endpoint = 'ks3-cn-beijing.ksyun.com'
    host = endpoint
    region = regions.get(host)
    bucket = 'zhangmingda'
    ks3key = 'life-bbs/测试.txt'
    service = 'ks3'
    method = 'GET'
    ak = 'AKLTdwZzHs8UTY6ZiLcqCmJL1w'
    
    #  生成标准化请求头
    def generate_canonical_headers(**headers):
        '''
        :param headers: 所有用来签名的请求头
        :return: 返回小写请求头排序后的key:value 字符串,每个key:value 之间\n换行
        '''
        sorted_headers = ''                                         # 准备标准请求头key+value字符串
        sorted_signed_headers = ''                                  # 准备签名的请求头key组合字符串
        header_keys = headers.keys()                                # 获取请求头所有key
        lower_headers = {}                                          # 准备存放小写请求头和值的字典
        for header in header_keys:                                  # 把大写请求头字典都转换为小写请求头字典
            lower_headers[header.lower()] = headers.get(header)
        sorted_lower_header_keys = sorted(lower_headers.keys())     # 把签名的请求头排序
    
        '''排序后的请求头和值进行组合字符串'''
        for lower_header in sorted_lower_header_keys:
            sorted_headers += lower_header + ':' + str(lower_headers[lower_header]).strip() + '\n'
            sorted_signed_headers += lower_header + ";"
        # print("============请求头排序==============")
        # print(sorted_headers)
        # print('------被签名的请求头----')
        # print(sorted_signed_headers)
        # print("==========请求头排序end============")
        sorted_lower_headers = {
            'sorted_headers': sorted_headers,               # 签名的请求头key 和 value
            'signed_headers': sorted_signed_headers[:-1]    # 被签名的请求头字符串组合,最后一个分号; 不要
        }
        return sorted_lower_headers
    
    
    # 创建规范化请求查询字符串
    def generate_canonical_querystring(**params):
        '''
        :param params: 查询字符串字典
        :return: url编码后的查询字符串key1=value1&key2=value2 ...
        '''
        sorted_params = ''
        sorted_param_keys = sorted(params.keys())
        for param in sorted_param_keys:
            sorted_params += quote(param) + '=' + quote(params.get(param), safe='') + '&'  # 查询字符串中的值任何字符串都进行URL编码
        return sorted_params[:-1]
    
    
    # 十六进制请求体Sha256Hash值--->请求体用
    def binary_data_sha256_hex(binary_data=''.encode()):
        '''
        :param args:
        :param forms:
        :return: 返回请求体内容的sha256 哈希值
        '''
        sha256 = hashlib.sha256()
        sha256.update(binary_data)
        return sha256.hexdigest().lower()
    
    
    # 构建被签名字符串,把标准请求canonical_request 哈希取16进制用
    def str_sha256_hex(string=''):
        '''
        :param string:
        :return: 字符串的sha256哈希值
        '''
        sha256 = hashlib.sha256()
        sha256.update(string.encode())
        return sha256.hexdigest()
    
    
    # 第二步构建签名key用
    def encode_string_to_hmac_256_digest(encode_salt, msg, digestmod=hashlib.sha256):
        '''
        :param encode_salt: 盐
        :param msg: 字符串信息
        :param digestmod: 摘要算法
        :return: HMAC-SHA256 加盐哈希后的字节
        '''
        digest_maker = hmac.new(encode_salt, msg.encode(), digestmod=digestmod)
        return digest_maker.digest()
    
    
    '''========================= 1. 准备被签名字符串 StringToSign计算=============================='''
    '''======== 1.1 规范化请求变量准备 =========='''
    sign_method = method                                    # 1.1.1 HTTP方法
    canonical_uri = '/' + bucket + '/' + ks3key             # 1.1.2 资源URI
    encode_uri = quote(canonical_uri, safe="/")    # 1.1.2 将URI编码成%字符串格式 不包含? 后的url查询参数
    payload_sha256_hex = binary_data_sha256_hex()          # 1.1.5 请求体sha256 十六进制HASH值
    signature_headers = {
        'Host': host,
        'x-kss-content-sha256': payload_sha256_hex,
    }
    sorted_lower_headers = generate_canonical_headers(**signature_headers)
    canonical_headers = sorted_lower_headers.get('sorted_headers')                  # 1.1.4 小写排序后的请求头key:value
    signed_headers = sorted_lower_headers.get('signed_headers')                     # 1.1.5 小写排序后的签名头
    credentialscope = date_utc + "/" + region + "/" + service + "/kss4_request"
    
    query_params = {
        'X-Kss-Algorithm': "KSS4-HMAC-SHA256",
        'X-Kss-Credential': ak + '/' + credentialscope,
        'X-Kss-Date': datetime_utc,
        'X-Kss-Expires': '3600',
        'X-Kss-SignedHeaders': signed_headers,
    }
    canonical_querystring = generate_canonical_querystring(**query_params)        # 1.1.3 查询字符串
    
    ''' 1.1 规范化请求CanonicalRequest计算方法'''
    canonical_request = method + '\n'\
                        + encode_uri + '\n' \
                        + canonical_querystring + '\n' \
                        + canonical_headers + '\n' \
                        + signed_headers + '\n' \
                        + payload_sha256_hex    # 请求体不参与签名 时 : + 'UNSIGNED-PAYLOAD'
    print("==========================规范化化请求=================================")
    print(canonical_request)
    print("==========================规范化请求done=================================")
    canonical_request_sha256_hex = str_sha256_hex(canonical_request)  # 规范化请求的256哈希值
    
    # 1.2 StringToSign
    algorithm = 'KSS4-HMAC-SHA256'
    requestdatetime = datetime_utc
    string_tosign = algorithm + '\n'\
                    + requestdatetime + '\n'\
                    + credentialscope + '\n'\
                    + canonical_request_sha256_hex
    print('================被签名的字符串======================')
    print(string_tosign)
    print('================被签名的字符串done======================')
    #  =========================第二步准备签名KEY=================================
    '''
    kSecret = your Secret Key 
    kDate = HMAC("KSS4" + kSecret, Date)
    kRegion = HMAC(kDate, Region)
    kService = HMAC(kRegion, Service)
    kSigning = HMAC(kService, "kss4_request")
    '''
    
    
    # 创建签名KEY的方法
    def generate_signing_key(sk, date_utc, region, service, termchar='kss4_request'):
        k_secret = "KSS4" + sk
        k_date = encode_string_to_hmac_256_digest(k_secret.encode(), date_utc)
        k_region = encode_string_to_hmac_256_digest(k_date, region)
        k_service = encode_string_to_hmac_256_digest(k_region, service)
        k_signing = encode_string_to_hmac_256_digest(k_service, termchar)
        return k_signing
    
    
    # 创建签名的方法
    def generate_signature(signing_key, string_tosign):
        digest_maker = hmac.new(signing_key, string_tosign.encode(), digestmod=hashlib.sha256)
        hex_signature = digest_maker.hexdigest()
        # print('hex_signature:', digest_maker.hexdigest())
        return hex_signature
    
    if __name__ == '__main__':
    
        sk = 'OAXDdJoILGG2tD3tXDD8EVIiP7sOueqp2ylgBrg+nF/au0btfHcGF/Br80j4JFAiMQ=='
        signing_key = generate_signing_key(sk, date_utc, region, service)
        signature = generate_signature(signing_key, string_tosign)
        request_headers = signature_headers
        request_query_params = {
            'X-Kss-Signature': signature
        }
        request_query_params.update(query_params)
        print(request_query_params)
    
        # 通过 URL QueryString 发送签名
        # requests 用法1
        url1 = "http://" + host + '/' + bucket + '/' + ks3key + '?' + generate_canonical_querystring(**request_query_params)
        print(url1)
        response = requests.get(url1, headers=request_headers)
        print(response.status_code)
        print(response.content.decode('gb2312'))
        # requests 用法2
        url2 = "http://" + host + '/' + bucket + '/' + ks3key
        response2 = requests.get(url2, params=request_query_params, headers=request_headers)
        print(response2.status_code)
        print(response2.url)

    输出:

    D:\Python3_study\tornado1\Scripts\python.exe C:/Users/ZHANGMINGDA/Desktop/kingsoft/KS3/test_v4_signature_in_url_get.py
    ==========================规范化化请求=================================
    GET
    /zhangmingda/life-bbs/%E6%B5%8B%E8%AF%95.txt
    X-Kss-Algorithm=KSS4-HMAC-SHA256&X-Kss-Credential=AKLTdwZzHs8UTY6ZiLcqCmJL1w%2F20210704%2FBEIJING%2Fks3%2Fkss4_request&X-Kss-Date=20210704T010302Z&X-Kss-Expires=3600&X-Kss-SignedHeaders=host%3Bx-kss-content-sha256
    host:ks3-cn-beijing.ksyun.com
    x-kss-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    
    host;x-kss-content-sha256
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    ==========================规范化请求done=================================
    ================被签名的字符串======================
    KSS4-HMAC-SHA256
    20210704T010302Z
    20210704/BEIJING/ks3/kss4_request
    d4f17877ff6ced3b1df5fb7fbebef9933aa8d0698de653127a5d64ec92e523b1
    ================被签名的字符串done======================
    {'X-Kss-Signature': 'a0a071ae8fb5f6a9018fa2583bf082bea08acad6fbdb395a0a3f6bd69601fd80', 'X-Kss-Algorithm': 'KSS4-HMAC-SHA256', 'X-Kss-Credential': 'AKLTdwZzHs8UTY6ZiLcqCmJL1w/20210704/BEIJING/ks3/kss4_request', 'X-Kss-Date': '20210704T010302Z', 'X-Kss-Expires': '3600', 'X-Kss-SignedHeaders': 'host;x-kss-content-sha256'}
    http://ks3-cn-beijing.ksyun.com/zhangmingda/life-bbs/测试.txt?X-Kss-Algorithm=KSS4-HMAC-SHA256&X-Kss-Credential=AKLTdwZzHs8UTY6ZiLcqCmJL1w%2F20210704%2FBEIJING%2Fks3%2Fkss4_request&X-Kss-Date=20210704T010302Z&X-Kss-Expires=3600&X-Kss-Signature=a0a071ae8fb5f6a9018fa2583bf082bea08acad6fbdb395a0a3f6bd69601fd80&X-Kss-SignedHeaders=host%3Bx-kss-content-sha256
    200
    test
    测试
    200
    http://ks3-cn-beijing.ksyun.com/zhangmingda/life-bbs/%E6%B5%8B%E8%AF%95.txt?X-Kss-Signature=a0a071ae8fb5f6a9018fa2583bf082bea08acad6fbdb395a0a3f6bd69601fd80&X-Kss-Algorithm=KSS4-HMAC-SHA256&X-Kss-Credential=AKLTdwZzHs8UTY6ZiLcqCmJL1w%2F20210704%2FBEIJING%2Fks3%2Fkss4_request&X-Kss-Date=20210704T010302Z&X-Kss-Expires=3600&X-Kss-SignedHeaders=host%3Bx-kss-content-sha256
    
    Process finished with exit code 0

     

 

上一篇:C++ SHA256代码实现


下一篇:Docker镜像