Skip to content

Commit b6ff99c

Browse files
committed
Skip credential decryption when the IV is missing
decryptAPIRestCredentials bailed only when the ciphertext columns were empty; a row with ciphertext but a blank IV would reach decrypt(ciphertext, "") and throw on read. Also short-circuit when either IV is empty, treating the malformed row as having no credentials.
1 parent 283607c commit b6ff99c

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

libs/fluxc/src/main/java/org/wordpress/android/fluxc/persistence/SiteSqlUtils.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,11 @@ class SiteSqlUtils
705705
if (!apiRestUsernamePlain.isNullOrEmpty() && !apiRestPasswordPlain.isNullOrEmpty()) {
706706
return this
707707
}
708-
// If the encrypted credentials are empty, there's nothing to decrypt
709-
if (apiRestUsernameEncrypted.isNullOrEmpty() || apiRestPasswordEncrypted.isNullOrEmpty()) {
708+
// If the encrypted credentials — or the IVs required to decrypt them — are empty, there's nothing to
709+
// safely decrypt. The ciphertext/IV pairs are always written together, so a row missing any one is
710+
// treated as having no decryptable credentials rather than risking a decrypt failure on a blank IV.
711+
if (apiRestUsernameEncrypted.isNullOrEmpty() || apiRestPasswordEncrypted.isNullOrEmpty() ||
712+
apiRestUsernameIV.isNullOrEmpty() || apiRestPasswordIV.isNullOrEmpty()) {
710713
return this
711714
}
712715
apiRestUsernamePlain = encryptionUtils.decrypt(apiRestUsernameEncrypted, apiRestUsernameIV)

libs/fluxc/src/test/java/org/wordpress/android/fluxc/persistence/SiteSqlUtilsTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,25 @@ class SiteSqlUtilsTest {
191191
assertThat(stored.apiRestPasswordIV).isEmpty()
192192
}
193193

194+
@Test
195+
fun `reading a site with credential ciphertext but a blank IV does not attempt decryption`() {
196+
// A row carrying credential ciphertext without its IV is malformed — decrypting it would fail. The
197+
// read path must treat it as having no decryptable credentials instead of throwing. Both ciphertexts
198+
// are present here so only the blank-IV guard (not the empty-ciphertext one) can short-circuit.
199+
WellSql.insert(SiteModel().apply {
200+
url = "https://example.test"
201+
apiRestUsernameEncrypted = "enc_user"
202+
apiRestUsernameIV = ""
203+
apiRestPasswordEncrypted = "enc_pass"
204+
apiRestPasswordIV = "iv_pass"
205+
}).execute()
206+
207+
val stored = siteSqlUtils.getSites().single()
208+
209+
assertThat(stored.apiRestUsernamePlain).isNullOrEmpty()
210+
assertThat(stored.apiRestPasswordPlain).isNullOrEmpty()
211+
}
212+
194213
@Test
195214
fun `updateXmlRpcUrl writes the column and leaves other fields alone`() {
196215
WellSql.insert(SiteModel().apply {

0 commit comments

Comments
 (0)