@@ -390,7 +390,7 @@ class BitwardenSyncService(
390390 val totp = decryptString(login.totp, symmetricKey) ? : " "
391391 val parsedUris = parseLoginUris(login.uris, symmetricKey)
392392 val customFields = parsePasswordCustomFieldMap(cipher.fields, symmetricKey)
393- val encryptedPassword = securityManager.encryptData (password)
393+ val encryptedPassword = encryptBitwardenPasswordForOfflineDisplay (password, cipher.id )
394394
395395 return PasswordEntry (
396396 title = name,
@@ -454,7 +454,9 @@ class BitwardenSyncService(
454454 val name = decryptString(cipher.name, symmetricKey) ? : entry.title
455455 val username = decryptString(login.username, symmetricKey) ? : entry.username
456456 val decryptedPassword = decryptString(login.password, symmetricKey)
457- val encryptedPassword = decryptedPassword?.let { securityManager.encryptData(it) } ? : entry.password
457+ val encryptedPassword = decryptedPassword?.let {
458+ encryptBitwardenPasswordForOfflineDisplay(it, cipher.id)
459+ } ? : entry.password
458460 val notes = decryptString(cipher.notes, symmetricKey) ? : entry.notes
459461 val totp = decryptString(login.totp, symmetricKey) ? : entry.authenticatorKey
460462 val parsedUris = parseLoginUris(login.uris, symmetricKey)
@@ -1251,6 +1253,45 @@ class BitwardenSyncService(
12511253 }
12521254 return candidate
12531255 }
1256+
1257+ /* *
1258+ * Bitwarden 密码需要支持“服务器暂时不可用时的本地查看”。
1259+ * 若主路径加密后的密文当前无法立即读回,则降级为兼容密文,避免详情页出现空密码。
1260+ */
1261+ private fun encryptBitwardenPasswordForOfflineDisplay (
1262+ plainPassword : String ,
1263+ cipherId : String
1264+ ): String {
1265+ val primaryEncrypted = securityManager.encryptData(plainPassword)
1266+ val primaryReadable = runCatching { securityManager.decryptData(primaryEncrypted) }
1267+ .getOrNull()
1268+ ?.let { it == plainPassword }
1269+ ? : false
1270+ if (primaryReadable) {
1271+ return primaryEncrypted
1272+ }
1273+
1274+ android.util.Log .w(
1275+ TAG ,
1276+ " Bitwarden password payload is not immediately readable; fallback to legacy V1, cipherId=$cipherId "
1277+ )
1278+
1279+ val legacyEncrypted = securityManager.encryptDataLegacyCompat(plainPassword)
1280+ val legacyReadable = runCatching { securityManager.decryptData(legacyEncrypted) }
1281+ .getOrNull()
1282+ ?.let { it == plainPassword }
1283+ ? : false
1284+
1285+ return if (legacyReadable) {
1286+ legacyEncrypted
1287+ } else {
1288+ android.util.Log .w(
1289+ TAG ,
1290+ " Legacy fallback is still unreadable; keep primary encrypted payload, cipherId=$cipherId "
1291+ )
1292+ primaryEncrypted
1293+ }
1294+ }
12541295}
12551296
12561297// ========== 同步结果 ==========
0 commit comments