fix(browser): DPAPI 解密前先剥掉解码后 5 字节 DPAPI 前缀
This commit is contained in:
@@ -171,9 +171,13 @@ function readSourceKey(userDataDir: string): SourceKeyInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/** DPAPI 解出源浏览器的 AES 密钥(PowerShell 调 CryptUnprotectData;用户级,无需管理员) */
|
||||
/** DPAPI 解出源浏览器的 AES 密钥(PowerShell 调 CryptUnprotectData;用户级,无需管理员)。
|
||||
* Chromium 的 encrypted_key = base64("DPAPI" + 密文 blob):CryptUnprotectData 只接受
|
||||
* 剥掉 5 字节前缀后的 blob,前缀判断必须在解码后的字节上做——base64 文本本身
|
||||
* 永远不以 "DPAPI" 开头(实测带前缀调用必然 CryptographicException: 数据无效)。 */
|
||||
function dpapiUnprotectKey(encodedKey: string): Promise<Buffer | null> {
|
||||
const blob = encodedKey.startsWith('DPAPI') ? encodedKey.slice(5) : encodedKey
|
||||
const bytes = Buffer.from(encodedKey, 'base64')
|
||||
const blob = bytes.subarray(0, 5).toString('utf8') === 'DPAPI' ? bytes.subarray(5).toString('base64') : encodedKey
|
||||
const script =
|
||||
`$d=[Convert]::FromBase64String('${blob}');` +
|
||||
'Add-Type -AssemblyName System.Security;' +
|
||||
@@ -183,9 +187,12 @@ function dpapiUnprotectKey(encodedKey: string): Promise<Buffer | null> {
|
||||
'powershell.exe',
|
||||
['-NoProfile', '-NonInteractive', '-Command', script],
|
||||
{ timeout: 20_000 },
|
||||
(err, stdout) => {
|
||||
(err, stdout, stderr) => {
|
||||
if (err || !stdout.trim()) {
|
||||
log.warn('dpapi unprotect failed', { err: err instanceof Error ? err.message : String(err ?? 'empty output') })
|
||||
log.warn('dpapi unprotect failed', {
|
||||
err: err instanceof Error ? err.message : String(err ?? 'empty output'),
|
||||
stderr: stderr ? String(stderr).slice(0, 200) : undefined
|
||||
})
|
||||
resolve(null)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user