Skip to content

Instantly share code, notes, and snippets.

@cm-kazup0n
Created March 17, 2023 08:29
Show Gist options
  • Save cm-kazup0n/bd4703b118ae865b030acb7813a316c5 to your computer and use it in GitHub Desktop.
Save cm-kazup0n/bd4703b118ae865b030acb7813a316c5 to your computer and use it in GitHub Desktop.
import java.security.MessageDigest
import java.text.SimpleDateFormat
import java.util.{Date, TimeZone}
object AwsV4Signer {
def sign(accessKey: String, secretKey: String, method: String, url: String, payload: String): Map[String, String] = {
val timestamp = getFormattedTimestamp()
val credentialsScope = getCredentialsScope(timestamp)
val canonicalRequest = getCanonicalRequest(method, url, payload, credentialsScope)
val hashedCanonicalRequest = hash(canonicalRequest)
val stringToSign = getStringToSign(timestamp, credentialsScope, hashedCanonicalRequest)
val signingKey = getSigningKey(secretKey, credentialsScope)
val signature = hmacSHA256(signingKey, stringToSign)
val authorizationHeader = getAuthorizationHeader(accessKey, credentialsScope, signature)
Map("Authorization" -> authorizationHeader, "X-Amz-Date" -> timestamp)
}
private def getFormattedTimestamp(): String = {
val dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'")
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"))
dateFormat.format(new Date())
}
private def getCredentialsScope(timestamp: String): String = {
val date = timestamp.substring(0, 8)
s"$date/us-east-1/s3/aws4_request"
}
private def getCanonicalRequest(method: String, url: String, payload: String, credentialsScope: String): String = {
val canonicalUri = getCanonicalUri(url)
val canonicalQueryString = getCanonicalQueryString(url)
val canonicalHeaders = getCanonicalHeaders(credentialsScope)
val payloadHash = hash(payload)
s"$method\n$canonicalUri\n$canonicalQueryString\n$canonicalHeaders\n$credentialsScope\n$payloadHash"
}
private def getCanonicalUri(url: String): String = {
val uri = new java.net.URI(url)
uri.getPath()
}
private def getCanonicalQueryString(url: String): String = {
val uri = new java.net.URI(url)
val query = uri.getQuery()
if (query == null) "" else query
}
private def getCanonicalHeaders(credentialsScope: String): String = {
s"host:s3.amazonaws.com\nx-amz-date:$timestamp\nx-amz-security-token:$securityToken\n"
}
private def getStringToSign(timestamp: String, credentialsScope: String, hashedCanonicalRequest: String): String = {
s"AWS4-HMAC-SHA256\n$timestamp\n$credentialsScope\n$hashedCanonicalRequest"
}
private def getSigningKey(secretKey: String, credentialsScope: String): Array[Byte] = {
val kDate = hmacSHA256(s"AWS4$secretKey", credentialsScope.substring(0, 8).getBytes("UTF-8"))
val kRegion = hmacSHA256(kDate, "us-east-1".getBytes("UTF-8"))
val kService = hmacSHA256(kRegion, "s3".getBytes("UTF-8"))
hmacSHA256(kService, "aws4_request".getBytes("UTF-8"))
}
private def getAuthorizationHeader(accessKey: String, credentialsScope: String, signature: String): String = {
s"AWS4-HMAC-SHA256 Credential=$accessKey/$credentialsScope, SignedHeaders
@cm-kazup0n
Copy link
Author

ScalaでAWS V4署名をするコード書いてください。ただしAWS SDKは使用しないでください。

以下はScalaでAWS V4署名をするコードの例です。この例では、アクセスキーとシークレットキー、リクエストのHTTPメソッド、エンドポイントURL、およびペイロードを使用して署名を生成します。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment