华为AKSK校验手写算法-JAVA

废话不多说上代码,手写华为AKSK的签名校验工具类:

package com.sungolden.daihai.utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

public class SignUtils {
    private final static String AK= "3D0ED054-7B0B-8BDE-E2EA-AD6F35B8C4A9";
    private final static String SK = "8E8EF629-FDF8-DCBA-1D94-6327E928C0EA";
    //GET\n/share-api/ds/surface-water-hour/\nITEM_CODE=w21011&MONITOR_TIME=2023-11-06&POINT_CODE=20231018120001&WATER_LEVEL=3\n
    // host:192.168.165.2:19064\nx-sdk-date:20231115T090856Z\n\nhost;x-sdk-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    public static String stringToSign(String method,String host,String uri,Map<String, String> parameters,String postData,String singerDate) throws UnsupportedEncodingException {
        method = method.toUpperCase(Locale.ROOT);

        if (method != "POST" && method != "PATCH" && method != "PUT")
        {
            postData = "";
        }
        if(StringUtils.isEmpty(postData)){
            postData = "";
        }
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH);
//        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//
//        String singerDate = sdf.format(new Date());
        String hex = toHex(hash(postData));
        if (uri.charAt(uri.length() - 1) != '/') {
            uri = uri.concat("/");
        }
        String signString = method+"\n"+uri+"\n"+getCanonicalizedQueryString(parameters)+"\nhost:"+host+"\nx-sdk-date:"+singerDate+"\n\n"+"host;x-sdk-date"+"\n"+hex;

        byte[] signingKey = SK.getBytes(StandardCharsets.UTF_8);
        String stringToSign = createStringToSign(signString, singerDate);
        byte[] signature = computeSignature(stringToSign, signingKey);
        String signatureResult = buildAuthorizationHeader(signature);
       return signatureResult;
    }


    private static String createStringToSign(String canonicalRequest, String singerDate) {
        return "SDK-HMAC-SHA256" + "\n" + singerDate + "\n" + toHex(hash(canonicalRequest));
    }




    private static String getCanonicalizedQueryString(Map<String, String> parameters) throws UnsupportedEncodingException {

        // 对map按照key进行排序
        Map<String, String> sortedMap = parameters.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
        StringJoiner joiner = new StringJoiner("&");
        sortedMap.forEach((key, value) -> joiner.add(key + "=" + value));
        String result = joiner.toString();
        return result;
    }

    private static  byte[] computeSignature(String stringToSign, byte[] signingKey) {
        return sign(stringToSign.getBytes(StandardCharsets.UTF_8), signingKey) ;
    }

    private static byte[] sign(byte[] data, byte[] key) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(key, "HmacSHA256"));
            return mac.doFinal(data);
        } catch (InvalidKeyException | NoSuchAlgorithmException var5) {
            return new byte[0];
        }
    }

    private static String buildAuthorizationHeader(byte[] signature) {
        String credential = "Access=" + AK;
        String signerHeaders = "SignedHeaders=" + "host;x-sdk-date";
        String signatureHeader = "Signature=" + toHex(signature);
        return "SDK-HMAC-SHA256" + " " + credential + ", " + signerHeaders + ", " + signatureHeader;
    }
    private static byte[] hash(String text) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(text.getBytes(StandardCharsets.UTF_8));
            return md.digest();
        } catch (NoSuchAlgorithmException var3) {
            return new byte[0];
        }
    }

    private static String toHex(byte[] data) {
        StringBuffer sbuff = new StringBuffer(data.length * 2);
        byte[] var2 = data;
        int var3 = data.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            byte bye = var2[var4];
            String hexStr = Integer.toHexString(bye);
            if (hexStr.length() == 1) {
                sbuff.append("0");
            } else if (hexStr.length() == 8) {
                hexStr = hexStr.substring(6);
            }

            sbuff.append(hexStr);
        }
        return sbuff.toString().toLowerCase(Locale.getDefault());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这段代码是干什么用的# -*- coding: utf-8 -*- import time import uuid import hashlib import base64 import ssl import urllib.request import hmac from hashlib import sha256 # 必填,请参考"开发准备"获取如下数据,替换为实际值 realUrl = 'https://rtcpns.cn-north-1.myhuaweicloud.com/rest/caas/relationnumber/partners/v1.0' #APP接入地址+接口访问URI APP_KEY = "a1********" #APP_Key APP_SECRET = "cfc8********" #APP_Secret ''' 选填,各参数要求请参考"AXB模式解绑接口" subscriptionId和relationNum为二选一关系,两者都携带时以subscriptionId为准 ''' subscriptionId = '****' #指定"AXB模式绑定接口"返回的绑定ID进行解绑 relationNum = '+86170****0001' #指定X号码(隐私号码)进行解绑 def buildAKSKHeader(appKey, appSecret): now = time.strftime('%Y-%m-%dT%H:%M:%SZ') #Created nonce = str(uuid.uuid4()).replace('-','') #Nonce digist = hmac.new(appSecret.encode(), (nonce + now).encode(), digestmod=sha256).digest() digestBase64 = base64.b64encode(digist).decode() #PasswordDigest return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now); def main(): # 请求URL参数 formData = urllib.parse.urlencode({ 'subscriptionId':subscriptionId, 'relationNum':relationNum }) #完整请求地址 fullUrl = realUrl + '?' + formData req = urllib.request.Request(url=fullUrl, method='DELETE') #请求方法为DELETE # 请求Headers参数 req.add_header('Authorization', 'AKSK realm="SDP",profile="UsernameToken",type="Appkey"') req.add_header('X-AKSK', buildAKSKHeader(APP_KEY, APP_SECRET)) req.add_header('Content-Type', 'application/json;charset=UTF-8') # 为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题 ssl._create_default_https_context = ssl._create_unverified_context try: print(formData) #打印请求数据 r = urllib.request.urlopen(req) #发送请求 print(r.read().decode('utf-8')) #打印响应结果 except urllib.error.HTTPError as e: print(e.code) print(e.read().decode('utf-8')) #打印错误信息 except urllib.error.URLError as e: print(e.reason) if __name__ == '__main__': main()
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值