File tree Expand file tree Collapse file tree
main/java/org/wordpress/android/fluxc/persistence
test/java/org/wordpress/android/fluxc/persistence Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -708,14 +708,17 @@ class SiteSqlUtils
708708 return this .map { it.decryptAPIRestCredentials() }
709709 }
710710
711- @Suppress(" ReturnCount" )
711+ @Suppress(" ReturnCount" , " ComplexCondition " )
712712 private fun SiteModel.decryptAPIRestCredentials (): SiteModel {
713713 // If already decrypted, do nothing
714714 if (! apiRestUsernamePlain.isNullOrEmpty() && ! apiRestPasswordPlain.isNullOrEmpty()) {
715715 return this
716716 }
717- // If the encrypted credentials are empty, there's nothing to decrypt
718- if (apiRestUsernameEncrypted.isNullOrEmpty() || apiRestPasswordEncrypted.isNullOrEmpty()) {
717+ // If the encrypted credentials — or the IVs required to decrypt them — are empty, there's nothing to
718+ // safely decrypt. The ciphertext/IV pairs are always written together, so a row missing any one is
719+ // treated as having no decryptable credentials rather than risking a decrypt failure on a blank IV.
720+ if (apiRestUsernameEncrypted.isNullOrEmpty() || apiRestPasswordEncrypted.isNullOrEmpty() ||
721+ apiRestUsernameIV.isNullOrEmpty() || apiRestPasswordIV.isNullOrEmpty()) {
719722 return this
720723 }
721724 apiRestUsernamePlain = encryptionUtils.decrypt(apiRestUsernameEncrypted, apiRestUsernameIV)
Original file line number Diff line number Diff 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 {
You can’t perform that action at this time.
0 commit comments