Last active
July 31, 2019 09:14
-
-
Save tuvshuud/d10dd34eee868427b68361df6da9d960 to your computer and use it in GitHub Desktop.
Java helper class to generate presigned url for AWS IoT MQTT device gateway
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.commons.codec.binary.Hex; | |
import javax.crypto.Mac; | |
import javax.crypto.spec.SecretKeySpec; | |
import java.io.UnsupportedEncodingException; | |
import java.net.URLEncoder; | |
import java.nio.charset.StandardCharsets; | |
import java.security.InvalidKeyException; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import java.text.SimpleDateFormat; | |
import java.util.*; | |
public class AWSHelper { | |
private String bytesToHex(byte[] bytes) { | |
StringBuffer result = new StringBuffer(); | |
for (byte byt : bytes) result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1)); | |
return result.toString(); | |
} | |
public byte[] sign(byte[] keyString, String msg) { | |
String algo = "HmacSHA256"; | |
byte[] digest = null; | |
try { | |
SecretKeySpec key = new SecretKeySpec(keyString, algo); | |
Mac mac = Mac.getInstance(algo); | |
mac.init(key); | |
digest = mac.doFinal(msg.getBytes("UTF-8")); | |
} catch (UnsupportedEncodingException e) { | |
} catch (InvalidKeyException e) { | |
} catch (NoSuchAlgorithmException e) { | |
} | |
return digest; | |
} | |
private byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Throwable{ | |
byte[] kDate = sign(("AWS4" + key).getBytes("UTF-8"), dateStamp); | |
byte[] kRegion = sign(kDate, regionName); | |
byte[] kService = sign(kRegion, serviceName); | |
byte[] kSigning = sign(kService, "aws4_request"); | |
return kSigning; | |
} | |
private String urlEncode(String txt){ | |
return URLEncoder.encode(txt, StandardCharsets.UTF_8); | |
} | |
public String generatePresignedUrlMqtt(String iotHost, String iotRegion, String accessKey, String secretKey) throws Throwable{ | |
String method = "GET"; | |
String service = "iotdevicegateway"; | |
String host = iotHost; | |
String region = iotRegion; | |
String canonicalUri = "/mqtt"; | |
// Create a date for headers and the credential string | |
SimpleDateFormat timestampFormat = new SimpleDateFormat("YMMdd'T'hhmmss'Z'"); | |
SimpleDateFormat dateFormat = new SimpleDateFormat("YMMdd"); | |
timestampFormat.setTimeZone(TimeZone.getTimeZone("UTC")); | |
String algorithm = "AWS4-HMAC-SHA256"; | |
String amzdate = timestampFormat.format(new Date()); | |
String datestamp = dateFormat.format(new Date()); | |
String credentialScope = datestamp + '/' + region + '/' + service + '/' + "aws4_request"; | |
StringBuilder canonicalQuerystring = new StringBuilder( | |
String.format("X-Amz-Algorithm=%s", algorithm)+ "&" | |
); | |
canonicalQuerystring.append( | |
String.format("X-Amz-Credential=%s", urlEncode(String.format("%s/%s", accessKey, credentialScope)))+ "&" | |
); | |
canonicalQuerystring.append( | |
String.format("X-Amz-Date=%s", amzdate) + "&" | |
); | |
canonicalQuerystring.append( | |
String.format("X-Amz-SignedHeaders=host") | |
); | |
String canonicalHeaders = "host:" + host + "\n"; | |
MessageDigest digest = MessageDigest.getInstance("SHA-256"); | |
String payloadHash = this.bytesToHex(digest.digest("".getBytes(StandardCharsets.UTF_8))); | |
String canonicalRequest = method + "\n" + canonicalUri + "\n" + canonicalQuerystring.toString() + '\n' + canonicalHeaders + "\nhost\n" + payloadHash; | |
String stringToSign = algorithm + "\n" + amzdate + "\n" + credentialScope + "\n" + this.bytesToHex(digest.digest(canonicalRequest.getBytes(StandardCharsets.UTF_8))); | |
byte[] signingKey = getSignatureKey(secretKey, datestamp, region, service); | |
String signature = Hex.encodeHexString(this.sign(signingKey, stringToSign)); | |
String signedUrl = "wss://" + host + canonicalUri + "?" + canonicalQuerystring.toString() +"&X-Amz-Signature=" + signature; | |
return signedUrl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment