Przeglądaj źródła

feat: 书源兼容性

HapeLee 2 miesięcy temu
rodzic
commit
7fca23feca

+ 4 - 6
app/src/main/java/io/legado/app/help/crypto/CryptoUtils.kt

@@ -28,12 +28,10 @@ internal fun String.hexToByteArray(): ByteArray {
 internal fun ByteArray.toBase64(): String = Base64.Default.encode(this)
 internal fun ByteArray.toBase64(): String = Base64.Default.encode(this)
 
 
 internal fun String.base64ToByteArray(): ByteArray {
 internal fun String.base64ToByteArray(): ByteArray {
-    val normalized = replace("\\s".toRegex(), "")
-    return try {
-        Base64.Default.decode(normalized)
-    } catch (e: IllegalArgumentException) {
-        Base64.UrlSafe.decode(normalized)
-    }
+    // Hutool Base64.decode 对缺失 "=" 填充、url-safe(-/_)、空白等输入宽容,与 beta.17 之前
+    // 应用内统一走 Hutool 解码的行为逐字节一致。Kotlin kotlin.io.encoding.Base64 为严格填充,
+    // 会对未对齐 4 倍数的输入抛 "The padding option is set to PRESENT..."(见书源取章名回归)。
+    return cn.hutool.core.codec.Base64.decode(replace("\\s".toRegex(), ""))
 }
 }
 
 
 internal fun digest(algorithm: String, data: ByteArray): ByteArray =
 internal fun digest(algorithm: String, data: ByteArray): ByteArray =

+ 16 - 0
app/src/test/java/io/legado/app/help/crypto/CryptoCompatibilityTest.kt

@@ -45,6 +45,22 @@ class CryptoCompatibilityTest {
         assertTrue(bytes.contentEquals("AAF__0FC".base64ToByteArray()))
         assertTrue(bytes.contentEquals("AAF__0FC".base64ToByteArray()))
     }
     }
 
 
+    @Test
+    fun `base64 缺失填充字符与 Hutool 宽容解码一致`() {
+        // base64ToByteArray 委托 cn.hutool.core.codec.Base64.decode,允许省略 "=" 填充、url-safe(-/_)与空白。
+        // 回归:beta.17 引入 kotlin.io.encoding.Base64(严格填充) 后,这类输入在 bookSource 的
+        // aesBase64DecodeToString / decode() 解密时抛 "The padding option is set to PRESENT...",
+        // 导致获取目录失败。这里验证已恢复 Hutool 宽容行为。
+        assertEquals("test", String("dGVzdA".base64ToByteArray()))          // 缺 "=="
+        assertEquals("a", String("YQ".base64ToByteArray()))                  // 缺 "=="
+        assertEquals("abcd", String("YWJjZA".base64ToByteArray()))           // 缺 "=="
+        assertEquals("test", String("dGVzdA==".base64ToByteArray()))         // 有效填充不受影响
+        assertTrue(
+            byteArrayOf(0xfb.toByte(), 0x8f.toByte(), 0xbb.toByte(), 0xb4.toByte())
+                .contentEquals("-4-7tA".base64ToByteArray())                 // url-safe 缺填充
+        )
+    }
+
     @Test
     @Test
     fun `AES ECB 加密解密往返`() {
     fun `AES ECB 加密解密往返`() {
         val key = "1234567890123456".toByteArray()
         val key = "1234567890123456".toByteArray()