security(installer): 9 BLOCKER 修复 — 三路审计验收
基于 code-reviewer + red-team-attacker + red-team-logic 三路并行审计: B1: 日志脱敏 — Run-CmdWithUI 的 Bw-Log 对 URL 做 ://***@ 替换 B2: DPAPI 加密注册表 — Save/Get-CachedSecrets 用 ProtectedData.Protect/Unprotect B3: credential.helper store → manager (Windows Credential Manager, DPAPI) B4: 单实例 Mutex — Global\BookwormPortableSetup, 重复启动弹提示退出 B5: URL-encode git 凭证 — EscapeDataString 处理 @/#/% 等特殊字符 B6: 移除 OpenSSL fallback — BWENC1 格式与 openssl enc 不兼容, Node.js 为硬性要求 B7: validAttempts++ 后移 — 文件不存在不消耗尝试次数, 避免用户误锁 B8: ErrorActionPreference try/finally — 防止 uv 安装异常后全局静默吞错 B9: Registry 加载白名单 — CacheAllowedKeys 防止 PATH/COMSPEC 注入 V-04: Get-Random → GetTempFileName (原子创建+加密随机, 防并发碰撞) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8a6611d96e
commit
385d3de57f
103
auto-setup.ps1
103
auto-setup.ps1
@ -15,6 +15,15 @@ param(
|
|||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# ─── B4: 单实例保护 (防止双击两次导致竞态) ─────────
|
||||||
|
$mutexCreated = $false
|
||||||
|
$global:BWMutex = [System.Threading.Mutex]::new($true, "Global\BookwormPortableSetup", [ref]$mutexCreated)
|
||||||
|
if (-not $mutexCreated) {
|
||||||
|
Add-Type -AssemblyName System.Windows.Forms
|
||||||
|
[System.Windows.Forms.MessageBox]::Show("Bookworm 安装器已在运行中。`n请勿重复启动。", "提示", "OK", "Information") | Out-Null
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
# ─── 路径定义 ────────────────────────────────────────
|
# ─── 路径定义 ────────────────────────────────────────
|
||||||
# PS2EXE 兼容: $MyInvocation.MyCommand.Path 在 EXE 启动时为空,需用 Process MainModule
|
# PS2EXE 兼容: $MyInvocation.MyCommand.Path 在 EXE 启动时为空,需用 Process MainModule
|
||||||
$ScriptDir = if ($PSScriptRoot) {
|
$ScriptDir = if ($PSScriptRoot) {
|
||||||
@ -225,11 +234,14 @@ function Run-CmdWithUI {
|
|||||||
[int]$timeoutMs = 180000, # 默认 3 分钟
|
[int]$timeoutMs = 180000, # 默认 3 分钟
|
||||||
[switch]$captureOutput # 返回 stdout 内容
|
[switch]$captureOutput # 返回 stdout 内容
|
||||||
)
|
)
|
||||||
Bw-Log "CMD" "$exe $($arguments -join ' ')"
|
# B1: 脱敏日志 (去除 URL 内嵌凭证 user:pass@)
|
||||||
|
$sanitizedArgs = ($arguments -join ' ') -replace '://[^@]+@', '://***@'
|
||||||
|
Bw-Log "CMD" "$exe $sanitizedArgs"
|
||||||
Update-Progress-SubStatus $label
|
Update-Progress-SubStatus $label
|
||||||
|
|
||||||
$outFile = Join-Path $env:TEMP "bw-cmd-out-$(Get-Random).tmp"
|
# V-04: 用 GetTempFileName (原子创建+加密随机) 替代 Get-Random
|
||||||
$errFile = Join-Path $env:TEMP "bw-cmd-err-$(Get-Random).tmp"
|
$outFile = [System.IO.Path]::GetTempFileName()
|
||||||
|
$errFile = [System.IO.Path]::GetTempFileName()
|
||||||
try {
|
try {
|
||||||
$proc = Start-Process -FilePath $exe -ArgumentList $arguments `
|
$proc = Start-Process -FilePath $exe -ArgumentList $arguments `
|
||||||
-NoNewWindow -PassThru `
|
-NoNewWindow -PassThru `
|
||||||
@ -430,7 +442,26 @@ function Find-OpenSSL {
|
|||||||
return $paths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
return $paths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# ─── 凭证缓存 (Windows Credential Manager) ─────────
|
# ─── 凭证缓存 (DPAPI 加密, 绑定当前 Windows 用户) ──
|
||||||
|
# B2: 不再明文存注册表, 使用 ProtectedData 加密
|
||||||
|
# B9: 读取时使用白名单, 不加载任意 KEY
|
||||||
|
Add-Type -AssemblyName System.Security
|
||||||
|
|
||||||
|
$CacheAllowedKeys = @("ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","GITHUB_PERSONAL_ACCESS_TOKEN",
|
||||||
|
"SLACK_BOT_TOKEN","ATLASSIAN_API_TOKEN","BROWSERBASE_API_KEY","FIRECRAWL_API_KEY","GEMINI_API_KEY")
|
||||||
|
|
||||||
|
function Protect-String([string]$plain) {
|
||||||
|
$bytes = [System.Text.Encoding]::UTF8.GetBytes($plain)
|
||||||
|
$enc = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, "CurrentUser")
|
||||||
|
return [Convert]::ToBase64String($enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Unprotect-String([string]$b64) {
|
||||||
|
$enc = [Convert]::FromBase64String($b64)
|
||||||
|
$bytes = [System.Security.Cryptography.ProtectedData]::Unprotect($enc, $null, "CurrentUser")
|
||||||
|
return [System.Text.Encoding]::UTF8.GetString($bytes)
|
||||||
|
}
|
||||||
|
|
||||||
function Get-CachedSecrets {
|
function Get-CachedSecrets {
|
||||||
try {
|
try {
|
||||||
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
|
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
|
||||||
@ -443,9 +474,15 @@ function Get-CachedSecrets {
|
|||||||
$props = Get-ItemProperty $regPath -ErrorAction SilentlyContinue
|
$props = Get-ItemProperty $regPath -ErrorAction SilentlyContinue
|
||||||
$loaded = 0
|
$loaded = 0
|
||||||
foreach ($p in $props.PSObject.Properties) {
|
foreach ($p in $props.PSObject.Properties) {
|
||||||
if ($p.Name -match '^[A-Z_]+$') {
|
# B9: 只加载白名单内的 Key (防止 PATH/COMSPEC 注入)
|
||||||
[System.Environment]::SetEnvironmentVariable($p.Name, $p.Value, "Process")
|
if ($CacheAllowedKeys -contains $p.Name) {
|
||||||
|
try {
|
||||||
|
$val = Unprotect-String $p.Value
|
||||||
|
[System.Environment]::SetEnvironmentVariable($p.Name, $val, "Process")
|
||||||
$loaded++
|
$loaded++
|
||||||
|
} catch {
|
||||||
|
Bw-Log "WARN" "缓存解密失败: $($p.Name)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ($loaded -gt 0 -and $env:ANTHROPIC_API_KEY)
|
return ($loaded -gt 0 -and $env:ANTHROPIC_API_KEY)
|
||||||
@ -456,13 +493,14 @@ function Save-SecretsToCache {
|
|||||||
try {
|
try {
|
||||||
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
|
$regPath = "HKCU:\Software\Bookworm\CachedEnv"
|
||||||
if (-not (Test-Path $regPath)) { New-Item $regPath -Force | Out-Null }
|
if (-not (Test-Path $regPath)) { New-Item $regPath -Force | Out-Null }
|
||||||
$keys = @("ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","GITHUB_PERSONAL_ACCESS_TOKEN",
|
foreach ($k in $CacheAllowedKeys) {
|
||||||
"SLACK_BOT_TOKEN","ATLASSIAN_API_TOKEN","BROWSERBASE_API_KEY","FIRECRAWL_API_KEY")
|
|
||||||
foreach ($k in $keys) {
|
|
||||||
$v = [System.Environment]::GetEnvironmentVariable($k, "Process")
|
$v = [System.Environment]::GetEnvironmentVariable($k, "Process")
|
||||||
if ($v) { Set-ItemProperty $regPath -Name $k -Value $v -Force }
|
if ($v) {
|
||||||
|
$encrypted = Protect-String $v
|
||||||
|
Set-ItemProperty $regPath -Name $k -Value $encrypted -Force
|
||||||
}
|
}
|
||||||
Set-ItemProperty $regPath -Name "_expiry" -Value (Get-Date).Date.AddDays(1).ToString("o") -Force
|
}
|
||||||
|
Set-ItemProperty $regPath -Name "_expiry" -Value (Get-Date).Date.AddDays(1).ToUniversalTime().ToString("o") -Force
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,8 +624,9 @@ if (Test-Cmd "uv") {
|
|||||||
} else {
|
} else {
|
||||||
Log-Info "安装 uv (Python 包管理器, 可选)..."
|
Log-Info "安装 uv (Python 包管理器, 可选)..."
|
||||||
|
|
||||||
# 静默执行子进程, 错误全部捕获到日志文件, 绝不冒泡到 PS2EXE
|
# B8: try/finally 确保 ErrorActionPreference 恢复 (防止后续 Phase 静默吞错)
|
||||||
$prevErrPref = $ErrorActionPreference
|
$prevErrPref = $ErrorActionPreference
|
||||||
|
try {
|
||||||
$ErrorActionPreference = "SilentlyContinue"
|
$ErrorActionPreference = "SilentlyContinue"
|
||||||
|
|
||||||
# 方案 A: winget (最可靠)
|
# 方案 A: winget (最可靠)
|
||||||
@ -597,25 +636,23 @@ if (Test-Cmd "uv") {
|
|||||||
Out-File -FilePath $uvLogFile -Encoding utf8 -Append
|
Out-File -FilePath $uvLogFile -Encoding utf8 -Append
|
||||||
} catch { "[winget] $_" | Out-File -FilePath $uvLogFile -Encoding utf8 -Append }
|
} catch { "[winget] $_" | Out-File -FilePath $uvLogFile -Encoding utf8 -Append }
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||||
# winget 装到 %LOCALAPPDATA%\Microsoft\WinGet\Packages\astral-sh.uv_*
|
|
||||||
$uvCargoBin = "$env:LOCALAPPDATA\Microsoft\WinGet\Links"
|
$uvCargoBin = "$env:LOCALAPPDATA\Microsoft\WinGet\Links"
|
||||||
if (Test-Path $uvCargoBin) { $env:Path += ";$uvCargoBin" }
|
if (Test-Path $uvCargoBin) { $env:Path += ";$uvCargoBin" }
|
||||||
if (Test-Cmd "uv") { $uvInstalled = $true }
|
if (Test-Cmd "uv") { $uvInstalled = $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
# 方案 B: Astral 官方一行脚本 (走 https://astral.sh/uv/install.ps1)
|
# 方案 B: Astral 官方一行脚本
|
||||||
if (-not $uvInstalled) {
|
if (-not $uvInstalled) {
|
||||||
try {
|
try {
|
||||||
$null = & powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://astral.sh/uv/install.ps1 | iex" 2>&1 |
|
$null = & powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://astral.sh/uv/install.ps1 | iex" 2>&1 |
|
||||||
Out-File -FilePath $uvLogFile -Encoding utf8 -Append
|
Out-File -FilePath $uvLogFile -Encoding utf8 -Append
|
||||||
} catch { "[astral] $_" | Out-File -FilePath $uvLogFile -Encoding utf8 -Append }
|
} catch { "[astral] $_" | Out-File -FilePath $uvLogFile -Encoding utf8 -Append }
|
||||||
# Astral 脚本默认装到 %USERPROFILE%\.local\bin
|
|
||||||
$localBin = Join-Path $env:USERPROFILE ".local\bin"
|
$localBin = Join-Path $env:USERPROFILE ".local\bin"
|
||||||
if (Test-Path $localBin) { $env:Path += ";$localBin" }
|
if (Test-Path $localBin) { $env:Path += ";$localBin" }
|
||||||
if (Test-Cmd "uv") { $uvInstalled = $true }
|
if (Test-Cmd "uv") { $uvInstalled = $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
# 方案 C: pip fallback (Python 已装且前两个都失败)
|
# 方案 C: pip fallback
|
||||||
if (-not $uvInstalled -and (Test-Cmd "python")) {
|
if (-not $uvInstalled -and (Test-Cmd "python")) {
|
||||||
try {
|
try {
|
||||||
$null = & python -m pip install --quiet uv 2>&1 |
|
$null = & python -m pip install --quiet uv 2>&1 |
|
||||||
@ -627,8 +664,9 @@ if (Test-Cmd "uv") {
|
|||||||
} catch {}
|
} catch {}
|
||||||
if (Test-Cmd "uv") { $uvInstalled = $true }
|
if (Test-Cmd "uv") { $uvInstalled = $true }
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
$ErrorActionPreference = $prevErrPref
|
$ErrorActionPreference = $prevErrPref
|
||||||
|
}
|
||||||
|
|
||||||
if ($uvInstalled) {
|
if ($uvInstalled) {
|
||||||
Log-OK "uv 安装成功"
|
Log-OK "uv 安装成功"
|
||||||
@ -800,8 +838,8 @@ foreach ($t in $netTests) {
|
|||||||
# ========================================================================
|
# ========================================================================
|
||||||
Log-Phase 3 "同步 Bookworm 配置"
|
Log-Phase 3 "同步 Bookworm 配置"
|
||||||
|
|
||||||
# 配置 git credential helper
|
# B3: 使用 Windows Credential Manager (DPAPI 加密) 替代明文 store
|
||||||
git config --global credential.helper store 2>$null
|
git config --global credential.helper manager 2>$null
|
||||||
|
|
||||||
# 克隆/更新 config 仓库 (.claude/) — 使用 Run-CmdWithUI 防止 UI 冻结
|
# 克隆/更新 config 仓库 (.claude/) — 使用 Run-CmdWithUI 防止 UI 冻结
|
||||||
if (Test-Path (Join-Path $ClaudeDir ".git")) {
|
if (Test-Path (Join-Path $ClaudeDir ".git")) {
|
||||||
@ -819,7 +857,7 @@ elseif (Test-Path $ClaudeDir) {
|
|||||||
Rename-Item $ClaudeDir $BackupDir
|
Rename-Item $ClaudeDir $BackupDir
|
||||||
|
|
||||||
$cred = Show-GiteaCredentialDialog
|
$cred = Show-GiteaCredentialDialog
|
||||||
$cloneUrl = if ($cred) { $GitUrl -replace '://', "://$($cred.User):$($cred.Pass)@" } else { $GitUrl }
|
$cloneUrl = if ($cred) { $GitUrl -replace '://', "://$([System.Uri]::EscapeDataString($cred.User)):$([System.Uri]::EscapeDataString($cred.Pass))@" } else { $GitUrl }
|
||||||
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $cloneUrl, $ClaudeDir) "克隆配置仓库" 180000
|
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $cloneUrl, $ClaudeDir) "克隆配置仓库" 180000
|
||||||
if (Test-Path (Join-Path $ClaudeDir "CLAUDE.md")) {
|
if (Test-Path (Join-Path $ClaudeDir "CLAUDE.md")) {
|
||||||
Log-OK "配置仓库克隆成功 (旧目录已备份)"
|
Log-OK "配置仓库克隆成功 (旧目录已备份)"
|
||||||
@ -833,7 +871,7 @@ elseif (Test-Path $ClaudeDir) {
|
|||||||
else {
|
else {
|
||||||
Log-Info "首次安装, 克隆配置仓库..."
|
Log-Info "首次安装, 克隆配置仓库..."
|
||||||
$cred = Show-GiteaCredentialDialog
|
$cred = Show-GiteaCredentialDialog
|
||||||
$cloneUrl = if ($cred) { $GitUrl -replace '://', "://$($cred.User):$($cred.Pass)@" } else { $GitUrl }
|
$cloneUrl = if ($cred) { $GitUrl -replace '://', "://$([System.Uri]::EscapeDataString($cred.User)):$([System.Uri]::EscapeDataString($cred.Pass))@" } else { $GitUrl }
|
||||||
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $cloneUrl, $ClaudeDir) "克隆配置仓库" 180000
|
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $cloneUrl, $ClaudeDir) "克隆配置仓库" 180000
|
||||||
if (Test-Path (Join-Path $ClaudeDir "CLAUDE.md")) {
|
if (Test-Path (Join-Path $ClaudeDir "CLAUDE.md")) {
|
||||||
Log-OK "配置仓库克隆成功"
|
Log-OK "配置仓库克隆成功"
|
||||||
@ -861,7 +899,7 @@ if (Test-Path (Join-Path $BootDir ".git")) {
|
|||||||
} else {
|
} else {
|
||||||
Log-Info "克隆 boot 仓库 (含解密工具与凭证)..."
|
Log-Info "克隆 boot 仓库 (含解密工具与凭证)..."
|
||||||
if (-not $cred) { $cred = Show-GiteaCredentialDialog }
|
if (-not $cred) { $cred = Show-GiteaCredentialDialog }
|
||||||
$bootCloneUrl = if ($cred) { $BootUrl -replace '://', "://$($cred.User):$($cred.Pass)@" } else { $BootUrl }
|
$bootCloneUrl = if ($cred) { $BootUrl -replace '://', "://$([System.Uri]::EscapeDataString($cred.User)):$([System.Uri]::EscapeDataString($cred.Pass))@" } else { $BootUrl }
|
||||||
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $bootCloneUrl, $BootDir) "克隆 boot 仓库" 180000
|
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $bootCloneUrl, $BootDir) "克隆 boot 仓库" 180000
|
||||||
if (-not (Test-Path (Join-Path $BootDir "crypto-helper.js"))) {
|
if (-not (Test-Path (Join-Path $BootDir "crypto-helper.js"))) {
|
||||||
Log-Fail "启动工具包下载失败"
|
Log-Fail "启动工具包下载失败"
|
||||||
@ -885,17 +923,18 @@ if (Get-CachedSecrets) {
|
|||||||
}
|
}
|
||||||
# 再解密 (缓存命中则跳过)
|
# 再解密 (缓存命中则跳过)
|
||||||
if (-not $secretsDecrypted) {
|
if (-not $secretsDecrypted) {
|
||||||
|
# B6: Node.js 是硬性要求 (OpenSSL fallback 与 BWENC1 格式不兼容, 已移除)
|
||||||
$cryptoHelper = Join-Path $BootDir "crypto-helper.js"
|
$cryptoHelper = Join-Path $BootDir "crypto-helper.js"
|
||||||
$useNode = (Test-Cmd "node") -and (Test-Path $cryptoHelper)
|
if (-not (Test-Cmd "node") -or -not (Test-Path $cryptoHelper)) {
|
||||||
if (-not $useNode -and -not $opensslCmd) {
|
Log-Fail "解密需要 Node.js (Phase 1 应已安装)"
|
||||||
Log-Fail "无解密工具 (需要 Node.js 或 OpenSSL)"
|
Show-MsgBox "解密凭证需要 Node.js,但未检测到。`n请确认 Phase 1 安装成功后重试。" "缺少 Node.js" "OK" "Error"
|
||||||
}
|
}
|
||||||
elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $BootDir -Filter "secrets-*.enc" -ErrorAction SilentlyContinue)) {
|
elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $BootDir -Filter "secrets-*.enc" -ErrorAction SilentlyContinue)) {
|
||||||
$validAttempts = 0
|
$validAttempts = 0
|
||||||
while ($validAttempts -lt 3) {
|
while ($validAttempts -lt 3) {
|
||||||
$rawCode = Show-AuthCodeDialog ($validAttempts + 1) 3
|
$rawCode = Show-AuthCodeDialog ($validAttempts + 1) 3
|
||||||
if (-not $rawCode) {
|
if (-not $rawCode) {
|
||||||
Log-Warn "用户跳过授权码输入"
|
Log-Warn "用户取消授权码输入"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,26 +947,22 @@ elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $BootDir -Filter "secrets-*.e
|
|||||||
Show-MsgBox "格式错误。`n正确格式: BW-YYYYMMDD-XXXXXXXXXXXXXXXXXXXXXXXX`n`n请检查后重新粘贴。" "格式错误" "OK" "Warning"
|
Show-MsgBox "格式错误。`n正确格式: BW-YYYYMMDD-XXXXXXXXXXXXXXXXXXXXXXXX`n`n请检查后重新粘贴。" "格式错误" "OK" "Warning"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$validAttempts++
|
|
||||||
|
|
||||||
# 按 token 前8位定位 .enc 文件 (多用户独立 Key),回退 secrets.enc
|
# B7: 先检查文件存在, 再递增 validAttempts (文件缺失不消耗尝试次数)
|
||||||
$fileId = $token.Substring(0, 8)
|
$fileId = $token.Substring(0, 8)
|
||||||
$encFile = Join-Path $BootDir "secrets-$fileId.enc"
|
$encFile = Join-Path $BootDir "secrets-$fileId.enc"
|
||||||
if (-not (Test-Path $encFile)) { $encFile = $SecretsEnc }
|
if (-not (Test-Path $encFile)) { $encFile = $SecretsEnc }
|
||||||
if (-not (Test-Path $encFile)) {
|
if (-not (Test-Path $encFile)) {
|
||||||
Show-MsgBox "未找到对应凭证文件。`n请确认管理员已推送 secrets-$fileId.enc 到 Gitea`n并重新运行安装器(会自动拉取)。" "文件未找到" "OK" "Warning"
|
Show-MsgBox "未找到对应凭证文件。`n请确认管理员已推送 secrets-$fileId.enc 到 Gitea`n并重新运行安装器(会自动拉取)。`n`n(此次不计为失败尝试)" "文件未找到" "OK" "Warning"
|
||||||
$token = $null
|
$token = $null
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$validAttempts++ # B7: 只有真正尝试解密才计数
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($useNode) {
|
|
||||||
$decrypted = & node $cryptoHelper decrypt $token $encFile 2>&1
|
$decrypted = & node $cryptoHelper decrypt $token $encFile 2>&1
|
||||||
$decExit = $LASTEXITCODE
|
$decExit = $LASTEXITCODE
|
||||||
} else {
|
|
||||||
$decrypted = & $opensslCmd enc -aes-256-cbc -d -pbkdf2 -iter 600000 -in $encFile -pass "pass:$token" 2>$null
|
|
||||||
$decExit = $LASTEXITCODE
|
|
||||||
}
|
|
||||||
$token = $null
|
$token = $null
|
||||||
|
|
||||||
if ($decExit -eq 0 -and $decrypted -and $decrypted -notmatch 'WRONG_PASSWORD|WRONG_FORMAT|bad decrypt|bad magic') {
|
if ($decExit -eq 0 -and $decrypted -and $decrypted -notmatch 'WRONG_PASSWORD|WRONG_FORMAT|bad decrypt|bad magic') {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user