You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Python调用PowerShell解密密码遇密钥无效问题求助

Python调用PowerShell解密密码报错的解决方法

问题描述

我正在编写Python脚本,通过调用PowerShell函数解密密码,代码如下:

import subprocess
keypwd = "BoFaTnpCv0XYrVxND8mi"
pwd= "76492d1116743f0423413b16050a5345MgB8AFUAMQA5AHEAWABvAFMAdwBHAEQASQAyAHcAVABJAHMAbwBKAHAASwBBAEEAPQA9AHwANAA4ADAANwA0ADAANQA5ADEAMgBlADkAZABjAGEAZQA5ADUAZQAyADcAZQBmADAAZAA1AGQAMAAxAGYAMAA0ADQAMQA5ADcAOAAxAGMAYgBlAGYAMwAwADcANwBhADMAMwA0AGMAOQAzAGYAOQA0AGQAMwAwAGMAYgA3ADMAMQA4AGQAYgBlAGUANAAyADQAOQAzADcAMABkADQAMABmADAAMABmADAAYwBkADQAMwBkADMAMABkAGUAOABjAGIA"

POWERSHELL = 'powershell -c "{0}"'
KEY_DECRYPT_CMD = '''Function KeySet {{
    [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'None')]
    param([string]$string)
    $length = $string.length
    $pad = 32-$length
    $encoding = New-Object System.Text.ASCIIEncoding
    $bytes = $encoding.GetBytes($string + "0" * $pad)
    return $bytes
}}

Function DecryptData ($data, $key) {{
    $data | ConvertTo-SecureString -key $key |
    ForEach-Object {{[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_))}}
}}


$setkey = KeySet '{key}';
DecryptData -data '{pwd}' -key $setkey
'''

cmd1 = POWERSHELL.format(KEY_DECRYPT_CMD.format(pwd=pwd, key = keypwd))
p = subprocess.Popen(cmd1, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout,stderr = p.communicate()

单独调用KeySet函数时,Python输出为:

b'66\r\n111\r\n70\r\n97\r\n84\r\n110\r\n112\r\n67\r\n118\r\n48\r\n88\r\n89\r\n114\r\n86\r\n120\r\n78\r\n68\r\n56\r\n109\r\n105\r\n48\r\n'

该输出与PowerShell中的结果一致(仅不含\r\n)。但调用DecryptData函数时出现错误,错误信息如下:

b'ConvertTo-SecureString : 
The specified key is not valid. Valid key length settings are either 128 bits, 192 bits, or \r\n256 bits.
\nAt line:12 char:13\r\n+   $data | ConvertTo-SecureString -key $key |\r\n+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    
+ CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], PSArgumentException\r\n    
+ FullyQualifiedErrorId : ImportSecureString_InvalidArgument,Microsoft.PowerShell.Commands.ConvertToSecureStringCo \r\n   mmand\r\n \r\n'

该脚本在PowerShell中可正常运行,问题出在DecryptData函数的密钥传递格式上,请问如何让这段代码正常工作?

解决方法

错误根源是通过字符串格式化传递字节数组时,PowerShell接收的是字符串形式的字节列表,而非实际的字节数组对象。当你在Python里把$setkey通过字符串替换传入时,$key变成了由换行分隔的数字字符串,而ConvertTo-SecureString需要的是[byte[]]类型的密钥。

方案1:在PowerShell脚本内直接生成密钥字节数组(推荐)

修改KEY_DECRYPT_CMD,让DecryptData直接接收密钥字符串,内部调用KeySet生成字节数组,避免跨进程传递类型对象的问题:

import subprocess
keypwd = "BoFaTnpCv0XYrVxND8mi"
pwd= "76492d1116743f0423413b16050a5345MgB8AFUAMQA5AHEAWABvAFMAdwBHAEQASQAyAHcAVABJAHMAbwBKAHAASwBBAEEAPQA9AHwANAA4ADAANwA0ADAANQA5ADEAMgBlADkAZABjAGEAZQA5ADUAZQAyADcAZQBmADAAZAA1AGQAMAAxAGYAMAA0ADQAMQA5ADcAOAAxAGMAYgBlAGYAMwAwADcANwBhADMAMwA0AGMAOQAzAGYAOQA0AGQAMwAwAGMAYgA3ADMAMQA4AGQAYgBlAGUANAAyADQAOQAzADcAMABkADQAMABmADAAMABmADAAYwBkADQAMwBkADMAMABkAGUAOABjAGIA"

POWERSHELL = 'powershell -c "{0}"'
# 修改后的脚本:DecryptData直接处理密钥字符串,内部生成字节数组
KEY_DECRYPT_CMD = '''Function KeySet {{
    [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'None')]
    param([string]$string)
    $length = $string.length
    $pad = 32-$length
    $encoding = New-Object System.Text.ASCIIEncoding
    $bytes = $encoding.GetBytes($string + "0" * $pad)
    return $bytes
}}

Function DecryptData ($data, $keyString) {{
    $key = KeySet $keyString
    $data | ConvertTo-SecureString -key $key |
    ForEach-Object {{[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_))}}
}}

DecryptData -data '{pwd}' -keyString '{key}'
'''

cmd1 = POWERSHELL.format(KEY_DECRYPT_CMD.format(pwd=pwd, key = keypwd))
p = subprocess.Popen(cmd1, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout,stderr = p.communicate()
# 处理输出:转码并去除多余换行符
print(stdout.decode('utf-8').strip())

方案2:通过Base64传递字节数组

如果一定要传递字节数组,可以在Python中将密钥字节转为Base64字符串,再在PowerShell中还原为字节数组:

import subprocess
import base64

keypwd = "BoFaTnpCv0XYrVxND8mi"
pwd= "76492d1116743f0423413b16050a5345MgB8AFUAMQA5AHEAWABvAFMAdwBHAEQASQAyAHcAVABJAHMAbwBKAHAASwBBAEEAPQA9AHwANAA4ADAANwA0ADAANQA5ADEAMgBlADkAZABjAGEAZQA5ADUAZQAyADcAZQBmADAAZAA1AGQAMAAxAGYAMAA0ADQAMQA5ADcAOAAxAGMAYgBlAGYAMwAwADcANwBhADMAMwA0AGMAOQAzAGYAOQA0AGQAMwAwAGMAYgA3ADMAMQA4AGQAYgBlAGUANAAyADQAOQAzADcAMABkADQAMABmADAAMABmADAAYwBkADQAMwBkADMAMABkAGUAOABjAGIA"

# 在Python内生成密钥字节数组并转为Base64
encoding = 'ascii'
pad_length = 32 - len(keypwd)
key_bytes = (keypwd + '0'*pad_length).encode(encoding)
key_b64 = base64.b64encode(key_bytes).decode(encoding)

POWERSHELL = 'powershell -c "{0}"'
KEY_DECRYPT_CMD = '''Function DecryptData ($data, $keyB64) {{
    $key = [Convert]::FromBase64String($keyB64)
    $data | ConvertTo-SecureString -key $key |
    ForEach-Object {{[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_))}}
}}

DecryptData -data '{pwd}' -keyB64 '{key_b64}'
'''

cmd1 = POWERSHELL.format(KEY_DECRYPT_CMD.format(pwd=pwd, key_b64=key_b64))
p = subprocess.Popen(cmd1, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout,stderr = p.communicate()
print(stdout.decode('utf-8').strip())

错误原因说明

原代码中,Python通过字符串格式化把$setkey的结果(字节数组的字符串表示)传入DecryptData,此时$key在PowerShell中是一个字符串数组(每个元素是单个字节的数字字符串),而非[byte[]]类型。ConvertTo-SecureString无法识别这种类型,因此抛出密钥长度无效的错误。而直接在PowerShell中运行时,$setkey是真正的[byte[]]对象,所以可以正常工作。

内容的提问来源于stack exchange,提问作者Luka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:13:20