AWS V4加密

news/2024/9/21 0:45:04

1.加密工具类

package com.ota.V7;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;/*** AWS V4 签名处理工具** 参考链接:https://docs.aws.amazon.com/zh_cn/general/latest/gr/sigv4_signing.html*/
public class AWSV4Auth {private AWSV4Auth() {}public static class Builder {private String accessKeyID;private String secretAccessKey;private String regionName;private String serviceName;private String httpMethodName;private String canonicalURI;private TreeMap<String, String> queryParametes;private TreeMap<String, String> awsHeaders;private String payload;private boolean debug = false;public Builder(String accessKeyID, String secretAccessKey) {this.accessKeyID = accessKeyID;this.secretAccessKey = secretAccessKey;}public Builder regionName(String regionName) {this.regionName = regionName;return this;}public Builder serviceName(String serviceName) {this.serviceName = serviceName;return this;}public Builder httpMethodName(String httpMethodName) {this.httpMethodName = httpMethodName;return this;}public Builder canonicalURI(String canonicalURI) {this.canonicalURI = canonicalURI;return this;}public Builder queryParametes(TreeMap<String, String> queryParametes) {this.queryParametes = queryParametes;return this;}public Builder awsHeaders(TreeMap<String, String> awsHeaders) {this.awsHeaders = awsHeaders;return this;}public Builder payload(String payload) {this.payload = payload;return this;}public Builder debug() {this.debug = true;return this;}public AWSV4Auth build() {return new AWSV4Auth(this);}}private String accessKeyID;private String secretAccessKey;private String regionName;private String serviceName;private String httpMethodName;private String canonicalURI;private TreeMap<String, String> queryParametes;private TreeMap<String, String> awsHeaders;private String payload;private boolean debug = false;/* Other variables */private final String HMACAlgorithm = "AWS4-HMAC-SHA256";private final String aws4Request = "aws4_request";private String strSignedHeader;private String xAmzDate;private String currentDate;private AWSV4Auth(Builder builder) {accessKeyID = builder.accessKeyID;secretAccessKey = builder.secretAccessKey;regionName = builder.regionName;serviceName = builder.serviceName;httpMethodName = builder.httpMethodName;canonicalURI = builder.canonicalURI;queryParametes = builder.queryParametes;awsHeaders = builder.awsHeaders;payload = builder.payload;debug = builder.debug;/* Get current timestamp value.(UTC) */xAmzDate = getTimeStamp();currentDate = getDate();}/*** 任务 1:针对签名版本 4 创建规范请求** @return*/private String prepareCanonicalRequest() {StringBuilder canonicalURL = new StringBuilder("");/* Step 1.1 以HTTP方法(GET, PUT, POST, etc.)开头, 然后换行. */canonicalURL.append(httpMethodName).append("\n");/* Step 1.2 添加URI参数,换行. */canonicalURI = canonicalURI == null || canonicalURI.trim().isEmpty() ? "/" : canonicalURI;canonicalURL.append(canonicalURI).append("\n");/* Step 1.3 添加查询参数,换行. */StringBuilder queryString = new StringBuilder("");if (queryParametes != null && !queryParametes.isEmpty()) {for (Map.Entry<String, String> entrySet : queryParametes.entrySet()) {String key = entrySet.getKey();String value = entrySet.getValue();queryString.append(key).append("=").append(encodeParameter(value)).append("&");}queryString.deleteCharAt(queryString.lastIndexOf("&"));queryString.append("\n");} else {queryString.append("\n");}canonicalURL.append(queryString);/* Step 1.4 添加headers, 每个header都需要换行. */StringBuilder signedHeaders = new StringBuilder("");if (awsHeaders != null && !awsHeaders.isEmpty()) {for (Map.Entry<String, String> entrySet : awsHeaders.entrySet()) {String key = entrySet.getKey();String value = entrySet.getValue();signedHeaders.append(key).append(";");canonicalURL.append(key).append(":").append(value).append("\n");}canonicalURL.append("\n");} else {canonicalURL.append("\n");}/* Step 1.5 添加签名的headers并换行. */strSignedHeader = signedHeaders.substring(0, signedHeaders.length() - 1); // 删掉最后的 ";"canonicalURL.append(strSignedHeader).append("\n");/* Step 1.6 对HTTP或HTTPS的body进行SHA256处理. */payload = payload == null ? "" : payload;canonicalURL.append(generateHex(payload));if (debug) {System.out.println("##Canonical Request:\n" + canonicalURL.toString());}return canonicalURL.toString();}/*** 任务 2:创建签名版本 4 的待签字符串** @param canonicalURL* @return*/private String prepareStringToSign(String canonicalURL) {String stringToSign = "";/* Step 2.1 以算法名称开头,并换行. */stringToSign = HMACAlgorithm + "\n";/* Step 2.2 添加日期,并换行. */stringToSign += xAmzDate + "\n";/* Step 2.3 添加认证范围,并换行. */stringToSign += currentDate + "/" + regionName + "/" + serviceName + "/" + aws4Request + "\n";/* Step 2.4 添加任务1返回的规范URL哈希处理结果,然后换行. */stringToSign += generateHex(canonicalURL);if (debug) {System.out.println("##String to sign:\n" + stringToSign);}return stringToSign;}/*** 任务 3:为 AWS Signature 版本 4 计算签名** @param stringToSign* @return*/private String calculateSignature(String stringToSign) {try {/* Step 3.1 生成签名的key */byte[] signatureKey = getSignatureKey(secretAccessKey, currentDate, regionName, serviceName);/* Step 3.2 计算签名. */byte[] signature = HmacSHA256(signatureKey, stringToSign);/* Step 3.2.1 对签名编码处理 */String strHexSignature = bytesToHex(signature);return strHexSignature;} catch (Exception ex) {ex.printStackTrace();}return null;}/***任务 4:将签名信息添加到请求并返回headers** @return*/public Map<String, String> getHeaders() {awsHeaders.put("x-amz-date", xAmzDate);/* 执行任务 1: 创建aws v4签名的规范请求字符串. */String canonicalURL = prepareCanonicalRequest();/* 执行任务 2: 创建用来认证的字符串 4. */String stringToSign = prepareStringToSign(canonicalURL);/* 执行任务 3: 计算签名. */String signature = calculateSignature(stringToSign);if (signature != null) {Map<String, String> header = new HashMap<String, String>(0);header.put("x-amz-date", xAmzDate);header.put("Authorization", buildAuthorizationString(signature));if (debug) {System.out.println("##Signature:\n" + signature);System.out.println("##Header:");for (Map.Entry<String, String> entrySet : header.entrySet()) {System.out.println(entrySet.getKey() + " = " + entrySet.getValue());}System.out.println("================================");}return header;} else {if (debug) {System.out.println("##Signature:\n" + signature);}return null;}}/*** 连接前几步处理的字符串生成Authorization header值.** @param strSignature* @return*/private String buildAuthorizationString(String strSignature) {return HMACAlgorithm + " "+ "Credential=" + accessKeyID + "/" + getDate() + "/" + regionName + "/" + serviceName + "/" + aws4Request + ", "+ "SignedHeaders=" + strSignedHeader + ", "+ "Signature=" + strSignature;}public static Map<String, String> getauth(String uri, String method, TreeMap<String, String> params, String data,String session_id,String access_id,String secret_key,String region,String service){TreeMap<String, String> awsHeaders = new TreeMap<String, String>();awsHeaders.put("cache-control", "no-cache");
//        awsHeaders.put("content-type", "application/json; charset=utf-8");awsHeaders.put("host", "api.volotea.com");awsHeaders.put("x-api-key", "9797bcb6b2f5439ba68d021328-mobile");awsHeaders.put("x-backend-version","6.33.1");//awsHeaders.put("x-app-version","3.91.1");awsHeaders.put("x-client-session", session_id);awsHeaders.put("x-client-type", "xamarin-android");return new Builder(access_id, secret_key).regionName(region).serviceName(service).httpMethodName(method).canonicalURI(uri).queryParametes(params).awsHeaders(awsHeaders)
//                .payload(data)
//                .debug().build().getHeaders();}public static Map<String, String> webgetauth(String uri, String method, TreeMap<String, String> params, String data,String session_id,String access_id,String secret_key,String region,String service){TreeMap<String, String> awsHeaders = new TreeMap<String, String>();awsHeaders.put("accept", "application/json");awsHeaders.put("host","api.volotea.com");
//        awsHeaders.put("content-type", "application/json; charset=utf-8");awsHeaders.put("x-api-key", "e94ab0cb5c614fc3b1ce49d89f6a-spa");return new Builder(access_id, secret_key).regionName(region).serviceName(service).httpMethodName(method).canonicalURI(uri).queryParametes(params).awsHeaders(awsHeaders)
//                .payload(data)
//                .debug().build().getHeaders();}public static Map<String, String> webauth(String uri, String method, TreeMap<String, String> params, String data,String session_id,String access_id,String secret_key,String region,String service){TreeMap<String, String> awsHeaders = new TreeMap<String, String>();awsHeaders.put("accept", "application/json");awsHeaders.put("x-api-key", "e94ab0cb5c614fc3b1ce49d89f6a-spa");awsHeaders.put("host","api.volotea.com");
//        awsHeaders.put("Content-Length",data.length()+"");
//        awsHeaders.put("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36");
//        awsHeaders.put("content-Type","application/json");
//        awsHeaders.put("Origin","https://book.volotea.com");
//        awsHeaders.put("Referer","https://book.volotea.com/");
//        awsHeaders.put("Accept-Encoding","gzip, deflate, br");
//        awsHeaders.put("Accept-Language","zh-CN,zh;q=0.9");//        awsHeaders.put("x-backend-version", "5.126.19");
//        awsHeaders.put("x-client-session", session_id);
//        awsHeaders.put("x-client-type", "xamarin-iphone");return new Builder(access_id, secret_key).regionName(region).serviceName(service).httpMethodName(method).canonicalURI(uri).queryParametes(params).awsHeaders(awsHeaders).payload(data)
//                .debug().build().getHeaders();}public static Map<String, String> auth(String uri, String method, TreeMap<String, String> params, String data,String session_id,String access_id,String secret_key,String region,String service){TreeMap<String, String> awsHeaders = new TreeMap<String, String>();
//        awsHeaders.put("cache-control", "no-cache");
//        awsHeaders.put("content-length", data.length()+"");
//        awsHeaders.put("content-type", "application/json");String amzDate = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));awsHeaders.put("accept", "application/json");awsHeaders.put("host", "api.volotea.com");awsHeaders.put("x-amz-date", amzDate);awsHeaders.put("x-api-key", "e94ab0cb5c614fc3b1ce49d89f6a-spa");System.out.println(amzDate);
//        awsHeaders.put("x-backend-version","6.33.1");
//        awsHeaders.put("x-app-version","3.91.1");
//        awsHeaders.put("x-client-session", session_id);//        awsHeaders.put("x-client-type","xamarin-android");return new Builder(access_id, secret_key).regionName(region).serviceName(service).httpMethodName(method).canonicalURI(uri).queryParametes(params).awsHeaders(awsHeaders).payload(data)
//                .debug().build().getHeaders();}/*** 将字符串16进制化.** @param data* @return*/private String generateHex(String data) {MessageDigest messageDigest;try {messageDigest = MessageDigest.getInstance("SHA-256");messageDigest.update(data.getBytes("UTF-8"));byte[] digest = messageDigest.digest();return String.format("%064x", new java.math.BigInteger(1, digest));} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {e.printStackTrace();}return null;}/*** 以给定的key应用HmacSHA256算法处理数据.** @param data* @param key* @return* @throws Exception* @reference:* http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java*/private byte[] HmacSHA256(byte[] key, String data) throws Exception {String algorithm = "HmacSHA256";Mac mac = Mac.getInstance(algorithm);mac.init(new SecretKeySpec(key, algorithm));return mac.doFinal(data.getBytes("UTF8"));}/*** 生成AWS 签名** @param key* @param date* @param regionName* @param serviceName* @return* @throws Exception* @reference* http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java*/private byte[] getSignatureKey(String key, String date, String regionName, String serviceName) throws Exception {byte[] kSecret = ("AWS4" + key).getBytes("UTF8");byte[] kDate = HmacSHA256(kSecret, date);byte[] kRegion = HmacSHA256(kDate, regionName);byte[] kService = HmacSHA256(kRegion, serviceName);byte[] kSigning = HmacSHA256(kService, aws4Request);return kSigning;}final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();/*** 将字节数组转换为16进制字符串** @param bytes* @return*/private String bytesToHex(byte[] bytes) {char[] hexChars = new char[bytes.length * 2];for (int j = 0; j < bytes.length; j++) {int v = bytes[j] & 0xFF;hexChars[j * 2] = hexArray[v >>> 4];hexChars[j * 2 + 1] = hexArray[v & 0x0F];}return new String(hexChars).toLowerCase();}/*** 获取yyyyMMdd'T'HHmmss'Z'格式的当前时间** @return*/public static String getTimeStamp() {DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//server timezonereturn dateFormat.format(new Date());}/*** 获取yyyyMMdd格式的当前日期** @return*/public static String getDate() {DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//server timezonereturn dateFormat.format(new Date());}/*** UTF-8编码* @param param* @return*/private String encodeParameter(String param){try {return URLEncoder.encode(param, "UTF-8");} catch (Exception e) {return URLEncoder.encode(param);}}
}

2.使用

这里我们使用一个post请求来做示例,首先分析Authorization的结构,

AWS4-HMAC-SHA256 Credential=AKIATLNGK7P7OIQKOYM4/20240919/eu-west-1/execute-api/aws4_request, SignedHeaders=accept;host;x-amz-date;x-api-key, Signature=b4ecf8deb72cbf54acabfd072f4e614adb3469e253d8ca7200c129b70372e072
  • AKIATLNGK7P7OIQKOYM4 代表access_id
  • eu-west-1 代表区域
  • execute-api 代表service
  • SignedHeaders 代表签名请求头
  • Signature 是通过 请求路径、方法、请求头、请求体、密钥等参数计算出来的

SignedHeaders的顺序要保持一致,如下图,我对accept;``host;``x-amz-date;``x-api-key进行签名

image

测试

    String entity="[{\"passengerKey\":\"MCFBRFQ-\",\"name\":{\"first\":\"SHUAIYIN\",\"last\":\"LAI\",\"title\":\"MR\"},\"passengerType\":\"ADT\",\"addAsFriend\":false,\"contactDetails\":{\"email\":\"flyoneu2@163.com\",\"phone\":{\"prefix\":\"+44\",\"nationalNumber\":\"13525659648\"}},\"hasPRM\":false}]";Map<String, String> auth = AWSV4Auth.auth("/api/spa/voe/v1/passengers", "POST", null, entity, "19202f7517c.4d619202f7517c.315-19202f7517b.27d19202f7517e.112", "AKIATLNGK7P7OIQKOYM4", "Aen88bM77IeAx2Llv/vsb+qdt8fm6eSm5aAv4SUF", "eu-west-1", "execute-api");System.out.println(auth.get("Authorization"));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/62017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

想要轻松生成音乐吗?Brev.ai让创作变得前所未有的简单!

Brev.ai 是一款免费在线AI音乐生成器,只需输入简单的文本描述,它便能快速生成高质量的音乐作品,非常适合用于视频、社交媒体内容以及更多应用场景。摘要:Brev.ai 是一款免费在线AI音乐生成器,只需输入简单的文本描述,它便能快速生成高质量的音乐作品,非常适合用于视频、…

vivo 全链路多版本开发测试环境落地实践

测试环境全链路多版本部署,解决多测试环境资源争抢等问题。作者:来自 vivo 互联网研发效能团队- Wang Kang测试环境全链路多版本部署,解决多测试环境资源争抢等问题。 一、背景介绍 软件系统中全链路指的是从用户请求发起,到最终返回响应的整个过程中所涉及到的所有环节和组…

易优cms网站模板目录各文件说明

易优CMS的模板结构非常清晰,主要分为电脑端(PC)和移动端(mobile)。以下是详细的目录结构和文件说明: 目录结构template ├── PC --- 电脑端 │ ├── skin --- 存放样式、JS、网站基础图片等 │ │ ├── css --- 样式.css文件目录 │ │ ├─…

易优cms网站验证码不显示是什么情况

当您在使用易优CMS时遇到验证码不显示的问题,可能的原因有很多。以下是一些可能的情况及解决办法: 可能的情况及解决办法 1. CMS版本太低下载修复包:访问易优CMS的官方网站或修复包下载页面(如易优CMS日志),下载最新的修复包。 解压缩修复包,并将其中的文件上传覆盖到网…

Flink-cdc丢失数据排查

一、获取任务信息 任务id:i01f51582-d8be-4262-aefa-000000 任务名称:ods_test1234 丢失的数据时间:2024-09-16 09:28:47二、数据同步查看日志 1、筛选日志 筛选2024-09-16 09:28:47 到 5分钟后数据 2、查找快照id,筛选内容Committed snapshot 7258609197164498019 (BaseRo…

纷享销客“子流程”创新——企业流程管理的革新之选

Jack是一家电子商务企业的销售经理,近期他的公司订单量激增,但随之而来的退货流程却成了一个棘手的问题。每天,成百上千的退货请求涌向客服部门,而退货流程的每一步:从接收退货申请、物流派单、商品检验入库,到最终的财务退款,都至关重要,却也复杂繁琐。任何一步的延误…

易优cms网站错误提示{msg:u5199u5165u8868ey_ad_positionu8bb0u5f55u5931u8d25uff0cu8bf7u5c1du8bd5F5u5237u65b0!}

根据错误提示和处理步骤,我们可以按部就班地解决这个问题。以下是详细的步骤说明: 1. 准备SQL文件 首先,需要准备一个包含两条更新语句的SQL文件。 步骤一:创建SQL文件打开文本编辑器(如Notepad++、VSCode等)。将以下两条SQL语句复制并粘贴到文本编辑器中:UPDATE `ey_ad…

易优cms网站无法安装,数据库文件版本号(v1.3.5)与CMS源码版本号(v1.3.6)不一致,点击查看!

当您在安装易优CMS时遇到“数据库文件版本号与CMS源码版本号不一致”的问题时,通常是因为后台升级后没有备份数据库就进行了打包搬家。以下是一步步的解决方法: 解决步骤本地备份数据库 删除安装锁文件 重命名安装目录 清理运行时目录 打包并上传扫码添加技术【解决问题】专注…