import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public static class RequestParam {
public final byte[] body;
public final String method;
public final String path;
public final String host;
public final String contentType;
public final ArrayList<NameValuePair> queryList;
public RequestParam(byte[] body, String method, Date date, String path, String host, String contentType, ArrayList<NameValuePair> queryList) {
this.contentType = contentType;
this.queryList = queryList;
public static final String TIME_FORMAT_V4 = "yyyyMMdd'T'HHmmss'Z'";
private static final TimeZone tz = TimeZone.getTimeZone("UTC");
private static final String AK = "ak";
private static final String SK = "sk";
private static final String Service = "DNS";
private static final String Version = "2018-08-01";
private static final String Region = "cn-north-1";
private static final String Host = "dns.volcengineapi.com";
public static byte[] hmacSHA256(byte[] key, String content) {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256"));
return mac.doFinal(content.getBytes());
public static String hashSHA256(byte[] content) {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return Hex.encodeHexString(md.digest(content));
private static String getAppointFormatDate(Date date) {
DateFormat df = new SimpleDateFormat(TIME_FORMAT_V4);
public static byte[] request(String method, HashMap<String, String> query, HashMap<String, String> header, String ak, String sk, String action, byte[] body) throws URISyntaxException {
HashMap<String, String> credential = new HashMap() {
put("service", Service);
ArrayList<NameValuePair> nvps = new ArrayList<>();
for (Map.Entry<String, String> entry : query.entrySet()) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
nvps.add(new BasicNameValuePair("Action", action));
nvps.add(new BasicNameValuePair("Version", Version));
Collections.sort(nvps, new Comparator<NameValuePair>() {
public int compare(NameValuePair o1, NameValuePair o2) {
return o1.getName().compareTo(o2.getName());
RequestParam requestParam = new RequestParam(body, method, new Date(), "/", Host, "application/json", nvps);
URI uri = new URIBuilder().addParameters(requestParam.queryList).build();
String xDate = getAppointFormatDate(new Date());
String shortXDate = xDate.substring(0, 8);
String xContentSha256 = hashSHA256(body);
String[] headStr = {"content-type", "host", "x-content-sha256", "x-date"};
String signedHeadersStr = String.join(";", headStr);
String[] headStrSecond = {"content-type:" + requestParam.contentType, "host:" + requestParam.host, "x-content-sha256:" + xContentSha256, "x-date:" + xDate};
String preRequestStr = String.join("\n", headStrSecond);
String[] preCanonicalRequestStr = {requestParam.method, requestParam.path, uri.getRawQuery(), preRequestStr, "", signedHeadersStr, xContentSha256};
String canonicalRequestStr = String.join("\n", preCanonicalRequestStr);
String hashedCanonicalRequest = hashSHA256(canonicalRequestStr.getBytes());
String[] credentialStr = {shortXDate, credential.get("region"), credential.get("service"), "request"};
String credentialScope = String.join("/", credentialStr);
String[] preStringToSign = {"HMAC-SHA256", xDate, credentialScope, hashedCanonicalRequest};
String stringToSign = String.join("\n", preStringToSign);
byte[] kDate = hmacSHA256(credential.get("secretKeyId").getBytes(), shortXDate);
byte[] kRegion = hmacSHA256(kDate, credential.get("region"));
byte[] kService = hmacSHA256(kRegion, credential.get("service"));
byte[] kSigning = hmacSHA256(kService, "request");
String signature = Hex.encodeHexString(hmacSHA256(kSigning, stringToSign));
String authorization = String.format("HMAC-SHA256 Credential=%s, SignedHeaders=%s, Signature=%s", credential.get("accessKeyId") + "/" + credentialScope, signedHeadersStr, signature);
if("POST".equalsIgnoreCase(method)){
HttpPost httpPost = new HttpPost("https://" + requestParam.host + requestParam.path + "?" + uri.getRawQuery());
httpPost.setEntity(new ByteArrayEntity(body));
for (Map.Entry<String, String> entry : header.entrySet()) {
httpPost.setHeader(entry.getKey(), entry.getValue());
} else if("GET".equalsIgnoreCase(method)){
HttpGet httpGet = new HttpGet("https://" + requestParam.host + requestParam.path + "?" + uri.getRawQuery());
for (Map.Entry<String, String> entry : header.entrySet()) {
httpGet.setHeader(entry.getKey(), entry.getValue());
throw new UnsupportedOperationException();
request.setHeader("Host", requestParam.host);
request.setHeader("Content-Type", requestParam.contentType);
request.setHeader("X-Date", xDate);
request.setHeader("X-Content-Sha256", xContentSha256);
request.setHeader("Authorization", authorization);
CloseableHttpClient httpClient = HttpClients.createDefault();
byte[] responseBody = null;
CloseableHttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
responseBody = EntityUtils.toByteArray(entity);
EntityUtils.consume(entity);
} catch (IOException e) {
public static void main(String[] args) throws URISyntaxException {
HashMap<String, Object> requestBody = new HashMap<>();
requestBody.put("ZID", 100);
requestBody.put("Remark", "example");
byte[] updateZoneResult = request("POST", new HashMap<>(), new HashMap<>(), AK, SK, "UpdateZone", JSON.toJSONBytes(requestBody));
System.out.println("response body:");
if (updateZoneResult != null) {
System.out.println(new String(updateZoneResult, StandardCharsets.UTF_8));
System.out.println("null");
HashMap<String, String> query = new HashMap<>();
query.put("ZoneName", "example.com");
byte[] checkZoneResult = request("GET", query, new HashMap<>(), AK, SK, "CheckZone", new byte[]{});
System.out.println("response body:");
if (checkZoneResult != null) {
System.out.println(new String(checkZoneResult, StandardCharsets.UTF_8));
System.out.println("null");