Skip to content

Commit 56f9615

Browse files
committed
fix
1 parent b9c52ba commit 56f9615

File tree

3 files changed

+102
-163
lines changed

3 files changed

+102
-163
lines changed

BUILD_INSTRUCTIONS.md

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -152,64 +152,29 @@ Could not resolve: org.bouncycastle:bcpg-jdk15on
152152

153153
## 调试技巧
154154

155-
### 查看详细日志
155+
### 查看日志
156156

157157
```bash
158-
# Flutter日志
159-
flutter run --verbose
160-
161158
# Android日志
162159
adb logcat | grep PGPEncryptionHelper
163-
adb logcat | grep Flutter
164160
```
165161

166-
### 清理构建缓存
162+
### 清理构建
167163

168164
```bash
169-
# 清理Flutter构建
170165
flutter clean
171-
172-
# 清理Gradle缓存
173-
cd android
174-
./gradlew clean
175-
cd ..
176-
177-
# 清理所有
178-
rm -rf build/
179-
rm -rf android/.gradle/
180-
rm -rf android/app/build/
181-
```
182-
183-
### 检查依赖
184-
185-
```bash
186-
# 检查Flutter依赖
187-
flutter pub outdated
188-
189-
# 检查Android依赖
190-
cd android
191-
./gradlew dependencies
166+
flutter pub get
192167
```
193168

194169
## 性能优化
195170

196171
### 减小APK大小
197172

198-
1. **启用代码混淆**(已配置)
199-
2. **启用资源压缩**(已配置)
200-
3. **使用Split APKs**(可选)
201-
202173
```bash
203174
# 构建Split APKs(按ABI)
204175
flutter build apk --split-per-abi
205176
```
206177

207-
### 构建时间优化
208-
209-
1. **启用Gradle缓存**
210-
2. **使用Gradle Daemon**
211-
3. **配置代理加速下载**
212-
213178
## 签名配置(可选)
214179

215180
如果需要发布到应用商店,需要配置签名:
@@ -253,30 +218,11 @@ adb install -r build/app/outputs/flutter-apk/app-release.apk
253218

254219
## 环境变量(可选)
255220

256-
可以设置以下环境变量加速构建:
257-
258221
```bash
259-
# Gradle JVM参数
260-
export GRADLE_OPTS="-Xmx2048m -XX:MaxPermSize=512m"
261-
262-
# Android SDK路径
263222
export ANDROID_HOME=$HOME/Library/Android/sdk
264223
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
265224
```
266225

267-
## 故障排除检查清单
268-
269-
- [ ] Flutter SDK版本正确(3.0+)
270-
- [ ] Java版本正确(11+)
271-
- [ ] Android SDK已安装并配置
272-
- [ ] 网络连接正常(可以访问Maven仓库)
273-
- [ ] 已运行 `flutter pub get`
274-
- [ ] 已运行 `flutter clean`(如果遇到奇怪错误)
275-
- [ ] Gradle版本兼容(8.11.1+)
276-
- [ ] Android Gradle Plugin版本正确(8.9.1)
277-
- [ ] Kotlin版本正确(2.1.0)
278-
- [ ] 所有依赖都已下载
279-
280226
## 获取帮助
281227

282228
如果遇到问题:

README.md

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -153,23 +153,14 @@ flutter build apk --release
153153
### PGP加密实现
154154

155155
- 使用BouncyCastle库进行PGP加密/解密
156-
- 支持AES-256加密算法
157-
- 支持ZIP压缩
158-
- 支持完整性检查(Integrity Packet)
159-
- Android P+兼容:使用AndroidOpenSSL提供者避免BC提供者限制
156+
- 支持AES-256加密算法和完整性检查
157+
- Android P+兼容性支持(自动选择最佳加密提供者)
160158

161-
### 密钥解析
159+
### 密钥管理
162160

163-
- 自动清理ASCII-armored格式的密钥
164-
- 支持包含元数据的密钥(自动过滤 `Version:`, `Comment:`, `Charset:` 等)
165-
- 自动移除Base64行中的空格和制表符
166-
- 支持多种密钥格式(PGP、RSA等)
167-
168-
### 数据存储
169-
170-
- 使用 `shared_preferences` 存储密钥数据
171-
- 密钥以JSON格式存储
172-
- 支持密钥的增删查改操作
161+
- 自动解析和清理ASCII-armored格式的密钥
162+
- 支持包含元数据的密钥格式
163+
- 使用本地存储保存密钥数据
173164

174165
## 已知问题和限制
175166

@@ -194,33 +185,18 @@ flutter build apk --release
194185

195186
## 故障排除
196187

197-
### 加密失败
188+
### 常见问题
198189

199-
- **错误:无法解析公钥**
190+
- **加密失败:无法解析公钥**
200191
- 检查公钥格式是否正确
201-
- 确保公钥包含完整的 `-----BEGIN PGP PUBLIC KEY BLOCK-----``-----END PGP PUBLIC KEY BLOCK-----`
202-
- 尝试重新导入公钥
203-
204-
- **错误:exception constructing public key**
205-
- 这是Android P+的已知问题,已通过使用AndroidOpenSSL提供者解决
206-
- 如果仍然出现,请检查日志获取详细信息
192+
- 确保公钥包含完整的开始和结束标记
207193

208-
### 解密失败
209-
210-
- **错误:私钥密码错误**
194+
- **解密失败:私钥密码错误**
211195
- 确认输入的密码正确
212-
- 检查私钥是否真的有密码保护
213-
- 尝试使用空密码(如果私钥未加密)
196+
- 如果私钥未加密,可以留空密码
214197

215-
- **错误:未找到匹配的私钥**
198+
- **未找到匹配的私钥**
216199
- 确保使用的私钥与加密时使用的公钥对应
217-
- 检查私钥格式是否正确
218-
219-
### 文件导入失败
220-
221-
- **无法选择文件**
222-
- Android 10+ 使用系统文件选择器,通常不需要存储权限
223-
- 如果无法选择,尝试在设置中授予存储权限
224200

225201
## 更新日志
226202

@@ -229,9 +205,7 @@ flutter build apk --release
229205
- ✅ 密钥管理(导入、存储、删除)
230206
- ✅ 私钥密码保护支持
231207
- ✅ 一键复制加密结果
232-
- ✅ Android P+兼容性修复
233-
- ✅ 改进的公钥解析逻辑
234-
- ✅ 友好的用户界面和使用说明
208+
- ✅ Android P+兼容性支持
235209

236210
## 许可证
237211

android/app/src/main/kotlin/com/wxcrypt/app/PGPEncryptionHelper.kt

Lines changed: 86 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -510,83 +510,80 @@ object PGPEncryptionHelper {
510510

511511
// 提取私钥(支持密码保护)
512512
android.util.Log.d("PGPEncryptionHelper", "Extracting private key, has password: ${password != null && password.isNotEmpty()}")
513+
if (password != null && password.isNotEmpty()) {
514+
android.util.Log.d("PGPEncryptionHelper", "Password length: ${password.length}, password hash: ${password.hashCode()}")
515+
}
513516
val passwordChars = password?.toCharArray() ?: "".toCharArray()
517+
518+
// 尝试多个提供者策略,让 BouncyCastle 自动选择最佳实现
514519
val privateKey = try {
515-
// 尝试使用BC提供者(虽然Android P+有限制,但某些操作可能仍可用)
520+
// 策略1: 不指定提供者,让 BouncyCastle 内部自动选择(推荐)
521+
// BouncyCastle 会根据可用性和算法支持自动选择合适的提供者
522+
android.util.Log.d("PGPEncryptionHelper", "Attempting to extract private key without explicit provider")
516523
secretKey.extractPrivateKey(
517524
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
518-
.setProvider("BC")
525+
// 不设置提供者,让 BouncyCastle 自动选择
519526
.build(passwordChars)
520527
).also {
521-
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using BC provider")
528+
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using auto-selected provider")
522529
}
523530
} catch (e: Exception) {
524-
android.util.Log.w("PGPEncryptionHelper", "Failed with BC: ${e.message}, trying AndroidOpenSSL")
531+
android.util.Log.w("PGPEncryptionHelper", "Failed with auto provider: ${e.message}, trying BC explicitly")
525532
try {
526-
// 尝试AndroidOpenSSL
533+
// 策略2: 尝试明确使用 BC 提供者
527534
secretKey.extractPrivateKey(
528535
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
529-
.setProvider("AndroidOpenSSL")
536+
.setProvider("BC")
530537
.build(passwordChars)
531538
).also {
532-
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using AndroidOpenSSL")
539+
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using BC provider")
533540
}
534541
} catch (e2: Exception) {
535-
android.util.Log.w("PGPEncryptionHelper", "Failed with AndroidOpenSSL: ${e2.message}, trying system default")
542+
android.util.Log.w("PGPEncryptionHelper", "Failed with BC: ${e2.message}, trying Conscrypt")
536543
try {
537-
// 尝试不指定提供者,使用系统默认
538-
secretKey.extractPrivateKey(
539-
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
540-
// 不设置提供者,让系统自动选择
541-
.build(passwordChars)
542-
).also {
543-
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using system default provider")
544+
// 策略3: 尝试 Conscrypt 提供者(如果可用)
545+
val conscryptProvider = Security.getProvider("Conscrypt")
546+
if (conscryptProvider != null) {
547+
android.util.Log.d("PGPEncryptionHelper", "Conscrypt provider found, attempting to use it")
548+
secretKey.extractPrivateKey(
549+
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
550+
.setProvider("Conscrypt")
551+
.build(passwordChars)
552+
).also {
553+
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using Conscrypt provider")
554+
}
555+
} else {
556+
throw Exception("Conscrypt provider not available")
544557
}
545558
} catch (e3: Exception) {
546-
android.util.Log.e("PGPEncryptionHelper", "Failed to extract private key with password: ${e3.message}", e3)
547-
// 检查是否是密码错误(checksum mismatch 通常表示密码错误)
548-
val isPasswordError = e3.message?.contains("checksum") == true ||
549-
e3.message?.contains("mismatch") == true ||
550-
e3.message?.contains("wrong") == true
551-
552-
// 如果密码错误,尝试空密码(向后兼容)
553-
if (password != null && password.isNotEmpty() && isPasswordError) {
554-
android.util.Log.d("PGPEncryptionHelper", "Checksum mismatch detected, trying with empty password (password may be incorrect)")
555-
try {
556-
secretKey.extractPrivateKey(
557-
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
558-
.setProvider("BC")
559-
.build("".toCharArray())
560-
).also {
561-
android.util.Log.d("PGPEncryptionHelper", "Extracted with empty password using BC")
562-
}
563-
} catch (e4: Exception) {
564-
android.util.Log.w("PGPEncryptionHelper", "Failed with empty password and BC: ${e4.message}, trying AndroidOpenSSL")
565-
try {
566-
secretKey.extractPrivateKey(
567-
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
568-
.setProvider("AndroidOpenSSL")
569-
.build("".toCharArray())
570-
).also {
571-
android.util.Log.d("PGPEncryptionHelper", "Extracted with empty password using AndroidOpenSSL")
572-
}
573-
} catch (e5: Exception) {
574-
android.util.Log.w("PGPEncryptionHelper", "Failed with empty password and AndroidOpenSSL: ${e5.message}, trying system default")
575-
secretKey.extractPrivateKey(
576-
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
577-
// 不设置提供者
578-
.build("".toCharArray())
579-
).also {
580-
android.util.Log.d("PGPEncryptionHelper", "Extracted with empty password using system default")
581-
}
582-
}
559+
android.util.Log.w("PGPEncryptionHelper", "Failed with Conscrypt: ${e3.message}, trying AndroidOpenSSL")
560+
try {
561+
// 策略4: 尝试 AndroidOpenSSL(虽然可能不支持 CFB 模式)
562+
secretKey.extractPrivateKey(
563+
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder()
564+
.setProvider("AndroidOpenSSL")
565+
.build(passwordChars)
566+
).also {
567+
android.util.Log.d("PGPEncryptionHelper", "Successfully extracted private key using AndroidOpenSSL")
583568
}
584-
} else {
585-
// 如果是密码错误,提供更明确的错误信息
569+
} catch (e4: Exception) {
570+
android.util.Log.e("PGPEncryptionHelper", "All provider attempts failed. Last error: ${e4.message}", e4)
571+
// 检查是否是密码错误(checksum mismatch 通常表示密码错误)
572+
val isPasswordError = e4.message?.contains("checksum", ignoreCase = true) == true ||
573+
e4.message?.contains("mismatch", ignoreCase = true) == true ||
574+
e4.message?.contains("wrong", ignoreCase = true) == true ||
575+
e2.message?.contains("checksum", ignoreCase = true) == true ||
576+
e2.message?.contains("mismatch", ignoreCase = true) == true
577+
578+
android.util.Log.e("PGPEncryptionHelper", "Password error detected: $isPasswordError")
579+
android.util.Log.e("PGPEncryptionHelper", "BC error: ${e2.message}")
580+
android.util.Log.e("PGPEncryptionHelper", "Final error: ${e4.message}")
581+
582+
// 如果是密码错误,提供明确的错误信息
586583
if (isPasswordError) {
587-
throw Exception("私钥密码错误,请检查输入的密码是否正确")
584+
throw Exception("私钥密码错误,请检查输入的密码是否正确。如果密码确实正确,可能是密钥格式不兼容。")
588585
} else {
589-
throw Exception("私钥密码错误或私钥未加密。错误信息: ${e3.message}")
586+
throw Exception("无法提取私钥。可能的原因:1) 密码错误 2) 密钥格式不兼容 3) 系统加密提供者限制。错误信息: ${e4.message}")
590587
}
591588
}
592589
}
@@ -596,26 +593,47 @@ object PGPEncryptionHelper {
596593
// 创建解密器
597594
android.util.Log.d("PGPEncryptionHelper", "Creating data decryptor factory")
598595
val dataDecryptorFactory = try {
599-
// 首先尝试AndroidOpenSSL
596+
// 策略1: 不指定提供者,让 BouncyCastle 自动选择(推荐)
597+
// 这样可以避免 AndroidOpenSSL 不支持 CFB 模式的问题
598+
android.util.Log.d("PGPEncryptionHelper", "Attempting to create decryptor factory without explicit provider")
600599
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder()
601-
.setProvider("AndroidOpenSSL")
600+
// 不设置提供者,让 BouncyCastle 自动选择支持 CFB 的提供者
602601
.build(privateKey)
603602
} catch (e: Exception) {
604-
android.util.Log.w("PGPEncryptionHelper", "Failed with AndroidOpenSSL, trying system default: ${e.message}")
603+
android.util.Log.w("PGPEncryptionHelper", "Failed with auto provider: ${e.message}, trying BC explicitly")
605604
try {
606-
// 尝试系统默认提供者
607-
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder()
608-
// 不设置提供者,让系统自动选择
609-
.build(privateKey)
610-
} catch (e2: Exception) {
611-
android.util.Log.w("PGPEncryptionHelper", "Failed with system default, trying BC: ${e2.message}")
612-
// 最后尝试BC(可能在某些设备上可用)
605+
// 策略2: 尝试明确使用 BC 提供者(通常支持 CFB 模式)
613606
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder()
614607
.setProvider("BC")
615608
.build(privateKey)
609+
} catch (e2: Exception) {
610+
android.util.Log.w("PGPEncryptionHelper", "Failed with BC: ${e2.message}, trying Conscrypt")
611+
try {
612+
// 策略3: 尝试 Conscrypt 提供者(如果可用)
613+
val conscryptProvider = Security.getProvider("Conscrypt")
614+
if (conscryptProvider != null) {
615+
android.util.Log.d("PGPEncryptionHelper", "Conscrypt provider found, attempting to use it")
616+
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder()
617+
.setProvider("Conscrypt")
618+
.build(privateKey)
619+
} else {
620+
throw Exception("Conscrypt provider not available")
621+
}
622+
} catch (e3: Exception) {
623+
android.util.Log.w("PGPEncryptionHelper", "Failed with Conscrypt: ${e3.message}, trying AndroidOpenSSL as last resort")
624+
// 策略4: 最后尝试 AndroidOpenSSL(虽然可能不支持 CFB,但作为最后备选)
625+
try {
626+
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder()
627+
.setProvider("AndroidOpenSSL")
628+
.build(privateKey)
629+
} catch (e4: Exception) {
630+
android.util.Log.e("PGPEncryptionHelper", "All decryptor factory attempts failed", e4)
631+
throw Exception("无法创建解密器。可能的原因:系统不支持所需的加密算法(AES/CFB模式)。错误信息: ${e4.message}")
632+
}
633+
}
616634
}
617635
}
618-
android.util.Log.d("PGPEncryptionHelper", "Created data decryptor factory")
636+
android.util.Log.d("PGPEncryptionHelper", "Created data decryptor factory successfully")
619637

620638
// 解密数据 - 使用PGPPublicKeyEncryptedData
621639
val publicKeyEncryptedDataForDecrypt = publicKeyEncryptedData
@@ -668,4 +686,5 @@ object PGPEncryptionHelper {
668686
throw Exception("解密失败: ${e.message}", e)
669687
}
670688
}
689+
671690
}

0 commit comments

Comments
 (0)