Monday 2 August 2021

Intermittently corrupted data with Google Tink encryption

Im investigating the use of com.google.crypto.tink:tink-android:1.6.1 in my current Android project.

The data I am encrypting includes the OAuth2 Access Token/Refresh Token I employ for my remote API calls, e.g. Access Token is my Bearer token for the Authorisation HTTP header.

Im concerned I have made an error in my encryption/decryption logic as I am experiencing an intermittent problem where I cannot Refresh the Token. The error from the server

{"error_description":"unknown, invalid, or expired refresh token","error":"invalid_grant"}

The refresh token cannot be expired as it lasts 24 hours.

My code that initialises Tink resembles this:-

private fun manageTink() {
    try {
        AeadConfig.register()
        authenticatedEncryption = generateNewKeysetHandle().getPrimitive(Aead::class.java)
    } catch (e: GeneralSecurityException) {
        throw RuntimeException(e)
    } catch (e: IOException) {
        throw RuntimeException(e)
    }
}

@Throws(IOException::class, GeneralSecurityException::class)
private fun generateNewKeysetHandle(): KeysetHandle =
    AndroidKeysetManager
        .Builder()
        .withSharedPref(this, TINK_KEYSET_NAME, PREF_FILE_NAME)
        .withKeyTemplate(KeyTemplates.get("AES256_GCM"))
        .withMasterKeyUri(MASTER_KEY_URI)
        .build()
        .keysetHandle

Here is my code for encryption/decryption

import android.util.Base64
import com.google.crypto.tink.Aead
import javax.inject.Inject

const val BASE64_ENCODE_SETTINGS = Base64.NO_WRAP or Base64.NO_PADDING

data class Security @Inject constructor(private val authenticatedEncryption: Aead) {

    fun conceal(plainText: String, associatedData: String): String {
        val plain64 = Base64.encode(plainText.encodeToByteArray(), BASE64_ENCODE_SETTINGS)
        val associated64 = Base64.encode(associatedData.encodeToByteArray(), BASE64_ENCODE_SETTINGS)
        val encrypted: ByteArray? = authenticatedEncryption.encrypt(plain64, associated64)

        return Base64.encodeToString(encrypted, BASE64_ENCODE_SETTINGS)
    }

    fun reveal(encrypted64: String, associatedData: String): String {
        val encrypted = Base64.decode(encrypted64.encodeToByteArray(), BASE64_ENCODE_SETTINGS)
        val associated64 = Base64.encode(associatedData.encodeToByteArray(), BASE64_ENCODE_SETTINGS)
        val decrypted: ByteArray? = authenticatedEncryption.decrypt(encrypted, associated64)

        return String(Base64.decode(decrypted, BASE64_ENCODE_SETTINGS))
    }
}

Could the use of Base64 encode/decode be the issue? Where is my mistake?



from Intermittently corrupted data with Google Tink encryption

No comments:

Post a Comment