Skip to content

Instantly share code, notes, and snippets.

@soulduse
Created April 11, 2019 08:24
Show Gist options
  • Save soulduse/dc25855b13462569f7f59b052b560fae to your computer and use it in GitHub Desktop.
Save soulduse/dc25855b13462569f7f59b052b560fae to your computer and use it in GitHub Desktop.
HmacGenerator for Coupang partners with Kotlin
import org.apache.commons.codec.binary.Hex
import java.nio.charset.Charset
import java.security.GeneralSecurityException
import java.text.SimpleDateFormat
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
object HmacGenerator {
private const val EXCEPTION_MESSAGE = "incorrect uri format"
private const val SPLIT_TEXT = "\\?"
private const val EMPTY_TEXT = ""
private const val DATE_FORMAT = "yyMMdd'T'HHmmss'Z'"
private const val ALGORITHM = "HmacSHA256"
private const val ALGORITHM_FORMAT = "CEA algorithm=%s, access-key=%s, signed-date=%s, signature=%s"
private val STANDARD_CHARSET = Charset.forName("UTF-8")
fun generate(method: String, uri: String, secretKey: String, accessKey: String): String {
val parts = uri.split(SPLIT_TEXT)
if (parts.size > 2) {
throw RuntimeException(EXCEPTION_MESSAGE)
}
val path = parts[0]
val query = if (parts.size == 2) parts[1] else EMPTY_TEXT
val dateFormatGmt = SimpleDateFormat(DATE_FORMAT).also { it.timeZone = TimeZone.getTimeZone("GMT") }
val datetime = dateFormatGmt.format(Date())
val message = datetime + method + path + query
val signature: String = try {
val signingKey = SecretKeySpec(secretKey.toByteArray(STANDARD_CHARSET), ALGORITHM)
val mac = Mac.getInstance(ALGORITHM).apply { init(signingKey) }
val rawHmac = mac.doFinal(message.toByteArray(STANDARD_CHARSET))
Hex.encodeHexString(rawHmac)
} catch (e: GeneralSecurityException) {
throw IllegalArgumentException()
}
return String.format(ALGORITHM_FORMAT, ALGORITHM, accessKey, datetime, signature)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment