mirror of
https://github.com/pandorafuture/wx-cli.git
synced 2026-08-29 04:00:55 +00:00
fix: accept WeChat 4.1.7 and newer
This commit is contained in:
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Accept WeChat 4.1.7 and newer for key extraction instead of maintaining a fixed version-prefix allowlist.
|
||||||
|
|
||||||
## [0.7.4] - 2026-07-22
|
## [0.7.4] - 2026-07-22
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
## [未发布]
|
## [未发布]
|
||||||
|
|
||||||
|
### 变更
|
||||||
|
|
||||||
|
- 密钥提取改为支持 WeChat 4.1.7 及以上版本,不再维护固定版本前缀白名单。
|
||||||
|
|
||||||
## [0.7.4] - 2026-07-22
|
## [0.7.4] - 2026-07-22
|
||||||
|
|
||||||
### 功能
|
### 功能
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ wx-cli 提供了最关键的两样东西:完整的历史上下文,以及持
|
|||||||
## 支持范围
|
## 支持范围
|
||||||
|
|
||||||
- **平台**:macOS(arm64 / Apple Silicon)
|
- **平台**:macOS(arm64 / Apple Silicon)
|
||||||
- **WeChat 版本**:4.1.7.x / 4.1.8.x
|
- **WeChat 版本**:4.1.7 及以上
|
||||||
|
|
||||||
## 前置条件
|
## 前置条件
|
||||||
|
|
||||||
@@ -265,4 +265,4 @@ wx-cli/
|
|||||||
|
|
||||||
- `wx-cli key list` 确认密钥正确
|
- `wx-cli key list` 确认密钥正确
|
||||||
- `wx-cli info <db>` 检查文件是否为加密状态
|
- `wx-cli info <db>` 检查文件是否为加密状态
|
||||||
- 确认 WeChat 版本在 4.1.7.x / 4.1.8.x 范围内
|
- 确认 WeChat 版本不低于 4.1.7
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ pub enum KeychainError {
|
|||||||
#[error("WeChat is not running")]
|
#[error("WeChat is not running")]
|
||||||
WeChatNotRunning,
|
WeChatNotRunning,
|
||||||
|
|
||||||
#[error("WeChat version {version} is not supported for key extraction (requires 4.1.7.x or 4.1.8.x)")]
|
#[error(
|
||||||
|
"WeChat version {version} is not supported for key extraction (requires 4.1.7 or newer)"
|
||||||
|
)]
|
||||||
UnsupportedVersion { version: String },
|
UnsupportedVersion { version: String },
|
||||||
|
|
||||||
#[error("could not detect WeChat account directory")]
|
#[error("could not detect WeChat account directory")]
|
||||||
|
|||||||
@@ -3,17 +3,30 @@ use std::process::Command;
|
|||||||
|
|
||||||
use crate::error::KeychainError;
|
use crate::error::KeychainError;
|
||||||
|
|
||||||
pub const SUPPORTED_VERSION: &str = "4.1.8.21";
|
pub const SUPPORTED_VERSION: &str = "4.1.7+";
|
||||||
|
|
||||||
/// Version prefixes accepted for LLDB key extraction.
|
/// Minimum version accepted for key extraction.
|
||||||
/// Encryption params (PBKDF2-HMAC-SHA512, 256K iterations) are identical across these versions.
|
/// Encryption params (PBKDF2-HMAC-SHA512, 256K iterations) are identical from this version onward.
|
||||||
const EXTRACTION_VERSION_PREFIXES: &[&str] = &["4.1.7", "4.1.8"];
|
const MIN_EXTRACTION_VERSION: (u64, u64, u64) = (4, 1, 7);
|
||||||
|
|
||||||
/// Check whether a version string is compatible with our LLDB key extraction.
|
/// Check whether a version string is compatible with our LLDB key extraction.
|
||||||
fn is_extraction_compatible(version: &str) -> bool {
|
fn is_extraction_compatible(version: &str) -> bool {
|
||||||
EXTRACTION_VERSION_PREFIXES
|
let mut components = version.split('.');
|
||||||
.iter()
|
let Some(major) = components.next().and_then(|value| value.parse().ok()) else {
|
||||||
.any(|prefix| version == *prefix || version.starts_with(&format!("{prefix}.")))
|
return false;
|
||||||
|
};
|
||||||
|
let Some(minor) = components.next().and_then(|value| value.parse().ok()) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(patch) = components.next().and_then(|value| value.parse().ok()) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if components.any(|value| value.is_empty() || value.parse::<u64>().is_err()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(major, minor, patch) >= MIN_EXTRACTION_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -354,6 +367,28 @@ fn tiebreak_by_wal_mtime<'a>(accounts: &[&'a AccountDirInfo]) -> Option<&'a Acco
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extraction_version_accepts_4_1_7_and_newer() {
|
||||||
|
for version in [
|
||||||
|
"4.1.7", "4.1.7.31", "4.1.8", "4.1.9", "4.1.13", "4.2.0", "5.0.0",
|
||||||
|
] {
|
||||||
|
assert!(
|
||||||
|
is_extraction_compatible(version),
|
||||||
|
"expected {version} to be supported"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extraction_version_rejects_older_and_invalid_versions() {
|
||||||
|
for version in ["4.1.6.99", "4.0.99", "3.9.9", "4.1", "4.1.beta", ""] {
|
||||||
|
assert!(
|
||||||
|
!is_extraction_compatible(version),
|
||||||
|
"expected {version:?} to be rejected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_base_wxid_with_suffix() {
|
fn test_extract_base_wxid_with_suffix() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user