Skip to content

Commit

Permalink
BITAU-98 Add EncryptionUtils helper functions to the bridge SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
ahaisting-livefront committed Sep 9, 2024
1 parent bef05d5 commit dcbc59e
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions bridge/src/main/java/com/bitwarden/bridge/util/EncryptionUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.bitwarden.bridge.util

import com.bitwarden.bridge.IBridgeService
import com.bitwarden.bridge.model.EncryptedSharedAccountData
import com.bitwarden.bridge.model.SharedAccountData
import com.bitwarden.bridge.model.SymmetricEncryptionKeyData
import com.bitwarden.bridge.model.toByteArrayContainer
import kotlinx.serialization.encodeToString
import java.security.MessageDigest
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.SecretKeySpec

/**
* Generate a symmetric [SecretKey] that will used for encrypting IPC traffic.
*
* This is intended to be used for implementing [IBridgeService.getSymmetricEncryptionKeyData].
*/
fun generateSecretKey(): SecretKey {
val keygen = KeyGenerator.getInstance("AES")
keygen.init(256, SecureRandom())
return keygen.generateKey()
}

/**
* Generate a fingerprint for the given symmetric key.
*
* This is intended to be used for implementing
* [IBridgeService.checkSymmetricEncryptionKeyFingerprint], which allows callers of the service
* to verify that they have the correct symmetric key without actually having to send the key.
*/
fun SymmetricEncryptionKeyData.toFingerprint(): ByteArray {
val messageDigest = MessageDigest.getInstance("SHA-256")
messageDigest.reset()
messageDigest.update(this.symmetricEncryptionKey.byteArray)
return messageDigest.digest()
}

/**
* Encrypt [SharedAccountData].
*
* This is intended to be used by the main Bitwarden app during a [IBridgeService.syncAccounts] call.
*
* TODO: consider what error handling should be involved here.
*/
fun SharedAccountData.toEncryptedSharedAccountData(
symmetricEncryptionKeyData: SymmetricEncryptionKeyData,
): EncryptedSharedAccountData {
val encodedKey = symmetricEncryptionKeyData.symmetricEncryptionKey.byteArray
val key = encodedKey.toSecretKey()
val cipher = generateCipher()
cipher.init(Cipher.ENCRYPT_MODE, key)
val jsonString = JSON.encodeToString(this)

val encryptedJsonString = cipher.doFinal(jsonString.encodeToByteArray()).toByteArrayContainer()
return EncryptedSharedAccountData(
initializationVector = cipher.iv.toByteArrayContainer(),
encryptedAccountsJson = encryptedJsonString,
)
}

/**
* Convert the given [ByteArray] to a [SecretKey].
*/
private fun ByteArray.toSecretKey(): SecretKey =
SecretKeySpec(this, 0, this.size, "AES")

/**
* Helper function for generating a [Cipher] that can be used for encrypting/decrypting using
* [SymmetricEncryptionKeyData].
*/
private fun generateCipher(): Cipher =
Cipher.getInstance("AES/CBC/PKCS5PADDING")

0 comments on commit dcbc59e

Please sign in to comment.