AWS IOT通過https獲取Shadow的簽名過程

AWS IOT通過https獲取Shadow的簽名過程

背景:由於公司之前的項目獲取iot shadow的時候是通過mqtt獲取,需要先訂閱才能獲得數據,實時性並不高,研究了一下aws的官方文檔發現還可以通過https的途徑獲取shadow信息,但是前提是需要對url進行簽名,簽名的過程比較繁瑣,而且官方文檔提供的信息太少,所以這裏提供一下通過iam認證簽名過程的源碼,供大家參考。

以下提供python版和java簽名過程的代碼

python版本

import hashlib, hmac
import requests
import datetime
import json

def sign(key, msg):
    signstr = hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
    return signstr

def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode("utf-8"), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, ('aws4_request'))
    return kSigning

def getResquestUri():    
	#這裏填你的accessKey,需要在aws後臺開一個管理員權限的iam用戶,然後拿到key和secret
    AccessKeyId = "*********";
    #這裏填你的secretKey
    SecretAccessKey = "*******“;
    method = 'GET'
     #TestDevices我給Ting起的名稱這裏換成你自己
    canonical_uri = "/things/TestDevice/shadow"
    protocol = 'https'
    service = 'iotdevicegateway'
    host = 'a2uwfjmcba1ne3-ats.iot.ap-northeast-1.amazonaws.com'
    region = 'ap-northeast-1'
    algorithm = 'AWS4-HMAC-SHA256'
    date_time = str(datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ"))
    date = date_time[0:8]
    # credentials = sts_mqtt(clientid, device_list)['Credentials']
    credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'
    canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm
    canonicalQuerystring += '&X-Amz-Credential=' + (AccessKeyId + '/' + credentialScope).replace("/",
                                                                                                                "%2F")
    canonicalQuerystring += '&X-Amz-Date=' + date_time
    canonicalQuerystring += '&X-Amz-Expires=3600'
    canonicalQuerystring += '&X-Amz-SignedHeaders=host'
    canonical_headers = 'host:' + host + '\n'
    payload_hash = hashlib.sha256('').hexdigest()
    canonical_request = method + '\n' + canonical_uri + '\n' + canonicalQuerystring + '\n' + canonical_headers + '\nhost\n' + payload_hash
    signing_key = getSignatureKey(SecretAccessKey, date, region, service)
    string_to_sign = algorithm + '\n' + date_time + '\n' + credentialScope + '\n' + hashlib.sha256(
        canonical_request).hexdigest()
    signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
    canonicalQuerystring += '&X-Amz-Signature=' + signature
    # canonicalQuerystring += '&X-Amz-Security-Token=' + quote(credentials['SessionToken'])
    requestUrl = protocol + '://' + host + canonical_uri + '?' + canonicalQuerystring
    return requestUrl
    
r = requests.get(getResquestUri())
print(getResquestUri())
print(r.json())

java版本

   public String getRequestUrl(){
        String requestUrl = "";
        try {
        String method = "GET";
        //TestDevices我給Ting起的名稱這裏換成你自己
        String canonical_uri = "/things/TestDevice/shadow";
        String protocol = "https";
        String service = "iotdevicegateway";
        String host = "a2uwfjmcba1ne3-ats.iot.ap-northeast-1.amazonaws.com";
        String region = "ap-northeast-1";
        String algorithm = "AWS4-HMAC-SHA256";
        //這裏填你的accessKey,需要在aws後臺開一個管理員權限的iam用戶,然後拿到key和secret
        String access_key = "********";
        //這裏填你的secretKey
        String secret_key = "********";
        TimeZone timeZone = TimeZone.getTimeZone("UTC");
// Create a date for headers and the credential string
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
        simpleDateFormat.setTimeZone(timeZone);
        String date_time = simpleDateFormat.format(new Date());
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyyMMdd");
        simpleDateFormat2.setTimeZone(timeZone);
        String date = simpleDateFormat2.format(new Date());

//    credentials = sts_mqtt(clientid, device_list)["Credentials"]
        String credentialScope = date + "/" + region + "/" + service + "/" + "aws4_request";
        String canonicalQuerystring = "X-Amz-Algorithm=" + algorithm;
        canonicalQuerystring += "&X-Amz-Credential=" + (access_key + "/" + credentialScope).replace("/", "%2F");
        canonicalQuerystring += "&X-Amz-Date=" + date_time;
        canonicalQuerystring += "&X-Amz-Expires=3600";
        canonicalQuerystring += "&X-Amz-SignedHeaders=host";
        String canonical_headers = "host:" + host + "\n";
        String payload_hash = getSHA256("");

        String canonical_request = method + "\n" + canonical_uri + "\n" + canonicalQuerystring + "\n" + canonical_headers + "\nhost\n" + payload_hash;
        byte[] signing_key = getSignatureKey(secret_key, date, region, service);
        String string_to_sign = algorithm + "\n" + date_time + "\n" + credentialScope + "\n" + getSHA256(canonical_request);

        String signature = byte2Hex(HmacSHA256(string_to_sign, signing_key));

        canonicalQuerystring += "&X-Amz-Signature=" + signature;

        requestUrl = protocol + "://" + host + canonical_uri + "?" + canonicalQuerystring;
        }catch (Exception e){
            e.printStackTrace();
        }

        return requestUrl;

    }



    /**
     *     * 利用java原生的類實現SHA256加密
     *     * @param str 加密後的報文
     *     * @return
     */
    public static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodestr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodestr;
    }

    /**
     *    * 將byte轉爲16進制
     *    * @param bytes
     *    * @return
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的進行補0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }


    static byte[] HmacSHA256(String data, byte[] key) throws Exception {
        String algorithm = "HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF-8"));
    }

    static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
        byte[] kDate = HmacSHA256(dateStamp, kSecret);
        byte[] kRegion = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256("aws4_request", kService);
        return kSigning;
    }

有疑問請聯繫郵箱 [email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章