使用公钥加密和编码密码字符串

问题描述 投票:0回答:1

我在做什么

我正在编写一个 PowerShell 脚本,自动登录到我拥有的设备(该设备是更深层次的网络连接),然后返回一些值。我之前曾为 BASH 开发过一个版本,它的功能符合预期。

问题是什么?

我正在努力用公钥正确加密密码,然后根据需要进行base64编码。

那么成分是什么?

网站有一个公钥,存储在一个名为

encryption-public.js
:

的JS文件中
const publicKey = `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs5nhtKPdlMXWh5FURGyD
GIoLxNPsAJoJtJ1TfiPaKYKNgZt2q4/HxbM3ArJqf7bDEB69SeYpQrvVNeS0c461
zhvl488HuHb8Ommms3/qyfuTvnyCQcjNXXEoBgGRYB+Rd2Q36cOi5qlHdomTCnZm
GBg80ZamQcANayc9I/cIMUtEZbIYTo9TZAs/7ZJAnuAgqUXOjUdbFxVtjCgVsuUF
BIoDfUIuYDvpGA84w+icjE0tD4jkzLo/pFaKvY8+kW4g/ikb0UZQ53FjZpihN1vc
C5s45t/lVWICB9C8y4LzeITbGWLvjfabuSqzP9TaHsdj4+f1MJ2lHPAxiEtkRe46
UtI4EU6kjU8TiZWPMfE8mPCrrswuEiO3ZRKVpG8Z8bzvqCwHSTnmWM+HHmWJxms+
z+0KOiK4oh/+5D2Zf5ETxZZuWlBKBhxPbIZ4ryu2jEafcGg0ChrKyp3rpiFpitK+
iNdI4xfh5XhtBzPKuDjL2RpRg7stlATgrit98c0g0pUqnOnrnizOPs5yZMCYwPz8
hPxenhTxzTAifAv3aCJlepBfuGnVBZO0CUQ76UVJsM81igH0V+5mZxMjwHdl3vZl
TYXhV7pG+y56vd0kOH8oqrYVtKG8XO94gVwz1lWb202ez4cKTD8zbzaj91kuMive
El82NUJJGOZ9oyBL4bwe1BcCAwEAAQ==
-----END PUBLIC KEY-----
`;

export default publicKey;

我已将此密钥保存到名为

pubkey.pem
的本地文件中:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs5nhtKPdlMXWh5FURGyD
GIoLxNPsAJoJtJ1TfiPaKYKNgZt2q4/HxbM3ArJqf7bDEB69SeYpQrvVNeS0c461
zhvl488HuHb8Ommms3/qyfuTvnyCQcjNXXEoBgGRYB+Rd2Q36cOi5qlHdomTCnZm
GBg80ZamQcANayc9I/cIMUtEZbIYTo9TZAs/7ZJAnuAgqUXOjUdbFxVtjCgVsuUF
BIoDfUIuYDvpGA84w+icjE0tD4jkzLo/pFaKvY8+kW4g/ikb0UZQ53FjZpihN1vc
C5s45t/lVWICB9C8y4LzeITbGWLvjfabuSqzP9TaHsdj4+f1MJ2lHPAxiEtkRe46
UtI4EU6kjU8TiZWPMfE8mPCrrswuEiO3ZRKVpG8Z8bzvqCwHSTnmWM+HHmWJxms+
z+0KOiK4oh/+5D2Zf5ETxZZuWlBKBhxPbIZ4ryu2jEafcGg0ChrKyp3rpiFpitK+
iNdI4xfh5XhtBzPKuDjL2RpRg7stlATgrit98c0g0pUqnOnrnizOPs5yZMCYwPz8
hPxenhTxzTAifAv3aCJlepBfuGnVBZO0CUQ76UVJsM81igH0V+5mZxMjwHdl3vZl
TYXhV7pG+y56vd0kOH8oqrYVtKG8XO94gVwz1lWb202ez4cKTD8zbzaj91kuMive
El82NUJJGOZ9oyBL4bwe1BcCAwEAAQ==
-----END PUBLIC KEY-----

处理加密和编码的文件称为

authUtils.js

该文件的内容:

import axios from 'axios';
import to from 'await-to-js';

import publicKey from '../keys/encryption-public.js';
const crypto = require('crypto');

export const setAuthToken = function (token) {
  if (token) {
    // apply authorization token to every request if logged in
    axios.defaults.headers.common['Authorization'] = token;
  } else {
    // delete auth header
    delete axios.defaults.headers.common['Authorization'];
  }
};

export const encryptWithPublicKey = function (string) {
  if (string) {
    const encrypted = crypto.publicEncrypt(publicKey, Buffer.from(string));
    return encrypted.toString('base64');
  }
};

export const validateToken = async () => {
  await to(axios.post('/api/admin/validateToken'));
};

export const JWT_TOKEN_KEY = 'deeperDeviceLoginToken';

现在,我什至不精通 NodeJS(我相信这就是它),所以得到了一位知识渊博的人的帮助,他为我编写了这个工作命令(在 BASH 中,使用 OpenSSL):

有效的命令是:

$(echo -n "password" | openssl rsautl -encrypt -pubin -inkey deeper.pem -oaep 2> /dev/null | base64 | tr -d '\n');

该命令获取密码,删除字符串末尾的任何换行符,并通过 OpenSSL 运行它,使用提供的密钥进行 RSA 步骤。错误消息被抑制,输出以 base64 编码,并从 base64 输出中删除任何新行(可能还有空格?)。这很丑陋,但它有效。

长话短说,该脚本的其余部分也是用 BASH 编写的,但是,它与这个问题无关。

我决定用 PowerShell(我可以像英语一样轻松地编写)重写它。 那已经成功了,除了这一步。 如果我从浏览器中的开发工具中获取结果字符串并将其硬编码到我的脚本中,我就可以运行我的 PowerShell 脚本。但我不想那样做,因为我想把我的代码分发给其他人。

这一步骤在 PowerShell 中我的代码是什么样的?

#Encrypt the password - I think this is the bit that needs fixing.
$PasswordENC = cmd /c '<NUL set /p =`"password`"| openssl rsautl -encrypt -pubin -inkey "deeper.pem" -oaep 2> $null'

#Encode the output - This seems to be the correct Base64 code, after testing. 
$PasswordB64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($PasswordENC))

所有这些之后,密码可以传递到更深层次的设备(使用硬编码密码字符串):

$Token = ((Invoke-WebRequest -UseBasicParsing -Uri "http://192.168.1.10/api/admin/login" `
-Method POST `
-ContentType "application/json" `
-Body "{`"username`":`"admin`",`"password`":`"$PasswordB64`"}"  |
Select-Object -ExpandProperty Content) | ConvertFrom-Json | Select-Object token).token

上面的输出为我提供了所需的 Bearer Token,然后我可以用它来做我需要做的事情。或者至少它是故意的。

相反,我得到

Invoke-WebRequest : {"decryptionError":"Failed to decrypt password"}

注意

cmd /c '<NUL set /p =`"password`"|

这是一种变通尝试,它试图修复在 PowerShell 管道期间添加的换行符,取自 this solution。我仍然有上面的错误信息。

我想要什么?

理想情况下,我想修复该错误。 话虽如此,我对实现相同目标的不同方法持开放态度。 如果我可以摆脱对 OpenSSL 的需求,那就太好了!我喜欢在没有外部应用程序的情况下全部用代码完成所有工作,但是,我知道在 PowerShell 中可能还有一种使用 NodeJS 的方法。另一个想法是使用“Selenium”来做一些浏览器操作,但是,我认为这不是最好的方法......我想使用 PowerShell,而不是 Python。

我曾尝试为 IE 创建一个 COM 对象以使用 oldskool 的方式获取字符串,但是,MS 杀死了 IE,即使在它仍然可以工作的机器上,IE 也无法正确加载 JS。

有人能帮帮我吗? :)

powershell encryption openssl base64 public-key
1个回答
0
投票

PowerShell 没有使用公钥加密密码的内置命令,但您可以使用 .NET 框架来完成此操作。这是一个演示如何执行此操作的示例脚本:

$publicKeyFile = "C:\keys\my_public_key.xml"
$securePassword = Read-Host -AsSecureString
$bytes = [System.Text.Encoding]::Unicode.GetBytes($securePassword)
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$rsa.FromXmlString(Get-Content $publicKeyFile)
$encryptedData = $rsa.Encrypt($bytes,$false)
$encryptedPassword = [System.Convert]::ToBase64String($encryptedData)
Write-Host $encryptedPassword

说明: 此脚本提示用户输入密码并将其作为安全字符串存储在变量 $securePassword 中。然后它将安全字符串转换为字节数组并创建一个新的 RSACryptoServiceProvider 对象。该脚本从文件中读取公钥并将其加载到 RSACryptoServiceProvider 对象中。然后它使用 RSACryptoServiceProvider 对象的 Encrypt 方法对密码进行加密,并将加密数据转换为 base64 编码的字符串。最后,它将加密后的密码写入控制台。

要使用此脚本,您需要将公钥文件的路径($publicKeyFile)替换为公钥文件的实际路径。您还可以修改脚本以提示用户输入公钥文件的路径。

注意加密后的密码只能使用对应的私钥解密。您应该确保私钥安全,并仅与授权用户或系统共享公钥。

这应该会给你一个关于你的问题的提示。 亨迪

© www.soinside.com 2019 - 2024. All rights reserved.