My question consists of two parts: 1) How to sign a string using a private key; 2) How to sign a JWT token.
- It is necessary to sign the string with a private key using the SHA256withRSA/PSS algorithm. I looked at a lot of materials on the Internet and implemented the code that is given below. But the problem is that the result obtained when executing the code does not coincide with what should actually be. More precisely, they match, but only the first few characters. Therefore, I wanted to find out how to sign a string correctly using a private key?
fun signStr(strToSign: String): String {
val PRIVATE_KEY = "" +
"-----BEGIN RSA PRIVATE KEY-----" +
"SOME_PRIVATE_KEY" +
"-----END RSA PRIVATE KEY-----" +
""
val privateKeyString = String(PRIVATE_KEY)
.replace("-----BEGIN RSA PRIVATE KEY-----\n", "")
.replace("\n-----END RSA PRIVATE KEY-----", "")
.replace("\n", "")
// Generate a PrivateKey object from the private key bytes using a KeyFactory and a PKCS8EncodedKeySpec
val privateKeyBytes: ByteArray = Base64.decode(privateKeyString, Base64.DEFAULT)
val keyFactory = KeyFactory.getInstance("RSA")
val privateKeySpec = PKCS8EncodedKeySpec(privateKeyBytes)
val privateKey = keyFactory.generatePrivate(privateKeySpec)
// Create a Signature object using the getInstance() method with the algorithm name
val signature: Signature = Signature.getInstance("SHA256withRSA/PSS")
// Initialize the Signature object with the private key using the initSign() method
signature.initSign(privateKey)
// Update the Signature object with the plain text bytes using the update() method
signature.update(strToSign.toByteArray())
// Call the sign() method to generate the digital signature, which is returned as a byte array
val signatureBytes = signature.sign()
return String(signatureBytes)
}
- The second part of the question concerns the correct signing of the JWT token. Do I understand correctly that JWT is signed as follows:
fun signJWT(header: String, payload: String): String {
val headerAndPayloadInBase64Url = header.convertToBase64URL() + "." + payload.convertToBase64URL()
return headerAndPayloadInBase64Url + "." + signStr(headerAndPayloadInBase64Url).convertToBase64URL()
}
I also wanted to know your advice, maybe there are good libraries in Kotlin or Java designed for the above two purposes?
You seem to have got confused about text blocks:
That is just simple string concatenation. There are no newlines in your string. In fact, it has the same value as if you wrote it like this:
So when you call
replace, it doesn't replace anything because there are no newlines in your original string, so there's no match.Try using multiline strings: