-
Notifications
You must be signed in to change notification settings - Fork 844
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BITAU-98 Add EncryptionUtils helper functions to the bridge SDK
- Loading branch information
1 parent
bef05d5
commit dcbc59e
Showing
1 changed file
with
76 additions
and
0 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
bridge/src/main/java/com/bitwarden/bridge/util/EncryptionUtils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
|