PowerShell加密后用node-forge解密报错:Encrypted message length is invalid
PowerShell RSA-OAEP加密后用node-forge解密报“Encrypted message length is invalid”的解决办法
问题重现
用PowerShell执行非对称加密后,通过Node.js的node-forge库解密时触发错误:
Error: Encrypted message length is invalid.
PowerShell加密代码
function Encrypt-Asymmetric { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()] [System.String] $ClearText, [Parameter(Position=1, Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ -PathType Leaf })] [System.String] $PublicKeyFilePath, [Parameter(Position=2)] [System.String] $OutputFilePath ) $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider $rsa.ImportSubjectPublicKeyInfo((Get-Content $PublicKeyFilePath -Raw)) $encryptedBytes = $rsa.Encrypt([System.Text.Encoding]::UTF8.GetBytes($ClearText), $true) $encryptedBase64String = [System.Convert]::ToBase64String($encryptedBytes) if ($OutputFilePath) { $encryptedBase64String | Set-Content -Path $OutputFilePath } return $encryptedBase64String } $clearText = "thisisasecret" $publicKeyFilePath = "public1.pem" $outputFilePath = "encrypted.txt" $encryptedString = Encrypt-Asymmetric -ClearText $clearText -PublicKeyFilePath $publicKeyFilePath -OutputFilePath $outputFilePath Write-Output "Encrypted: $encryptedString"
Node.js解密代码
const forge = require('node-forge'); const fs = require('fs'); function decryptAsymmetric(encryptedString, privateKeyFilePath) { const privateKeyPem = fs.readFileSync(privateKeyFilePath, 'utf8'); const privateKey = forge.pki.privateKeyFromPem(privateKeyPem); const encryptedBytes = forge.util.decode64(encryptedString); const decryptedBytes = privateKey.decrypt(encryptedBytes, 'RSA-OAEP', { md: forge.md.sha256.create(), mgf1: { md: forge.md.sha256.create() } }); return decryptedBytes.toString(); } const encryptedString = "IdnKfQ3tPZH/5AdYbqhsMzvRbW6/VQgGjvmJYtuQz/VT5nxlfVIDVTXKayIMDhnCtLvprODAOFg5GBhPUwEUtzuO4H7T6wzPu84Pnev4UyNC/w0cmnPBixwRggyVQpOvso1rKeTfD5wNcSTtQ4KIaQScSUC/+U5oAldhbjI5S1Y=" //fs.readFileSync('encrypted.txt', 'utf8') const privateKeyFilePath = 'private1.key'; const decryptedText = decryptAsymmetric(encryptedString, privateKeyFilePath); console.log('Decrypted:', decryptedText);
问题原因
核心问题是加密和解密使用的OAEP哈希算法不匹配:
- PowerShell中使用
RSACryptoServiceProvider.Encrypt(..., $true)时,默认采用SHA-1作为OAEP的哈希算法和MGF1的哈希算法 - Node.js代码中明确指定了SHA-256作为哈希,两边算法不一致导致解密时无法正确解析密文,触发长度错误
另外,手动复制密文时若引入换行、空格或截断,也可能导致密文长度异常,但从提供的代码来看,主要问题还是算法不匹配。
解决方案
方案1:Node.js端改用SHA-1(快速验证,不推荐生产环境)
修改node-forge的解密代码,将哈希算法改为SHA-1,与PowerShell端默认值匹配:
const decryptedBytes = privateKey.decrypt(encryptedBytes, 'RSA-OAEP', { md: forge.md.sha1.create(), mgf1: { md: forge.md.sha1.create() } });
方案2:PowerShell端改用SHA-256(推荐,更安全)
由于RSACryptoServiceProvider不支持自定义OAEP哈希算法,需改用RSACng类实现SHA-256的OAEP加密:
function Encrypt-Asymmetric { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()] [System.String] $ClearText, [Parameter(Position=1, Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ -PathType Leaf })] [System.String] $PublicKeyFilePath, [Parameter(Position=2)] [System.String] $OutputFilePath ) # 使用RSACng替代RSACryptoServiceProvider,支持自定义OAEP哈希 $rsa = New-Object System.Security.Cryptography.RSACng $rsa.ImportSubjectPublicKeyInfo((Get-Content $PublicKeyFilePath -Raw)) # 指定OAEP填充,哈希算法用SHA-256 $encryptedBytes = $rsa.Encrypt([System.Text.Encoding]::UTF8.GetBytes($ClearText), [System.Security.Cryptography.RSAEncryptionPadding]::OaepSHA256) $encryptedBase64String = [System.Convert]::ToBase64String($encryptedBytes) if ($OutputFilePath) { $encryptedBase64String | Set-Content -Path $OutputFilePath } return $encryptedBase64String } $clearText = "thisisasecret" $publicKeyFilePath = "public1.pem" $outputFilePath = "encrypted.txt" $encryptedString = Encrypt-Asymmetric -ClearText $clearText -PublicKeyFilePath $publicKeyFilePath -OutputFilePath $outputFilePath Write-Output "Encrypted: $encryptedString"
修改后,Node.js端原有使用SHA-256的代码即可正常解密。
额外注意事项
- 确保公私钥对匹配:加密用公钥必须和解密用私钥属于同一密钥对
- 避免手动复制密文:建议直接读取文件内容,防止引入多余格式字符
- 生产环境优先使用SHA-256及以上哈希算法,规避SHA-1的安全风险
内容的提问来源于stack exchange,提问作者AVS Kasturi Karthik
相关产品推荐
相关产品推荐

