使用 powershell 上传 X509 证书 - 错误 'Cannot find the requested object'
upload X509 certificate using powershell - error 'Cannot find the requested object'
我目前正在开发一个原型 C# MVC 应用程序,它允许用户将证书和 CRL 上传到存储库。例如,该应用程序将采用上传的 .cer,并使用 X509Certificate2 的 Import() 方法对其进行解析。我这样做是为了验证用户上传的确实是证书:
public CertModel(byte[] bytes)
{
this._Certificate = new X509Certificate2();
try // Attempt to parse as a certificate to see if this is actually a cert
{
this._Certificate.Import(bytes);
this.Subject = _Certificate.Subject;
this.Sha1Fingerprint = _Certificate.Thumbprint;
this.RawData = Convert.ToBase64String(_Certificate.RawData);
}
catch (CryptographicException e)
{
this._Certificate = null;
}
}
有一个呈现上传表单的MVC网页,最终调用了上面的代码。这在直接使用 Web 表单时效果很好。
另一个团队正在编写 powershell 脚本,他们正在尝试使用 Invoke-WebRequest commandlet 进行上传。这是我们不能开始工作的。
$filePath = "%HOMEPATH%\Desktop\certs\myCert.cer"
$fileInfo = gi $filePath
# Get the raw data of the cert to upload #
$rawCertData = [System.IO.File]::ReadAllText($fileInfo)
$length = $rawCertData.Length;
Write-Host $rawCertData
## Type of file you are uploading ##
$fileType = "Certificate"
## Build the POST Body ##
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`n"
$bodyLines = (
"--$boundary",
'Content-Disposition: form-data; name="Type"',
'',
"$fileType",
"--$boundary",
'Content-Disposition: form-data; name="upload"; filename="myCert.cer"',
'Content-Type: application/octet-stream',
'',
"$rawCertData",
"--$boundary--"
) -join $lf
$contentType = "multipart/form-data; boundary=$boundary"
$uri = "http://localhost:58484/repo/upload_service"
$response = Invoke-WebRequest -Uri $uri -Method POST -ContentType $contentType -Body $bodyLines -WebSession $session
$tempStore.Clear()
对于同一个文件,我已验证请求有效负载看起来完全相同。此外,我可以验证传递给 Import() 的字节数组是否相同。但是,当使用 curl/Invoke-WebRequest 方法时。我在 CryptographicException 中收到 'Cannot find the requested object' 消息。
我以前从未接触过 powershell,所以我希望有一个我可以实施的 C# 解决方案来解决这个问题,但我会采纳我能得到的任何建议。
@Eris 感谢您在评论中提供的解决方案。
$rawCertData = [System.IO.File]::ReadAllBytes($fileInfo)
$rawCertData = [System.Convert]::ToBase64String($rawCertData);
唯一让我感到奇怪的是使用网络表单时字节数组不同,但似乎 X509Certificate2.Import() 知道如何在任何一种情况下正确解析它。
我目前正在开发一个原型 C# MVC 应用程序,它允许用户将证书和 CRL 上传到存储库。例如,该应用程序将采用上传的 .cer,并使用 X509Certificate2 的 Import() 方法对其进行解析。我这样做是为了验证用户上传的确实是证书:
public CertModel(byte[] bytes)
{
this._Certificate = new X509Certificate2();
try // Attempt to parse as a certificate to see if this is actually a cert
{
this._Certificate.Import(bytes);
this.Subject = _Certificate.Subject;
this.Sha1Fingerprint = _Certificate.Thumbprint;
this.RawData = Convert.ToBase64String(_Certificate.RawData);
}
catch (CryptographicException e)
{
this._Certificate = null;
}
}
有一个呈现上传表单的MVC网页,最终调用了上面的代码。这在直接使用 Web 表单时效果很好。
另一个团队正在编写 powershell 脚本,他们正在尝试使用 Invoke-WebRequest commandlet 进行上传。这是我们不能开始工作的。
$filePath = "%HOMEPATH%\Desktop\certs\myCert.cer"
$fileInfo = gi $filePath
# Get the raw data of the cert to upload #
$rawCertData = [System.IO.File]::ReadAllText($fileInfo)
$length = $rawCertData.Length;
Write-Host $rawCertData
## Type of file you are uploading ##
$fileType = "Certificate"
## Build the POST Body ##
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`n"
$bodyLines = (
"--$boundary",
'Content-Disposition: form-data; name="Type"',
'',
"$fileType",
"--$boundary",
'Content-Disposition: form-data; name="upload"; filename="myCert.cer"',
'Content-Type: application/octet-stream',
'',
"$rawCertData",
"--$boundary--"
) -join $lf
$contentType = "multipart/form-data; boundary=$boundary"
$uri = "http://localhost:58484/repo/upload_service"
$response = Invoke-WebRequest -Uri $uri -Method POST -ContentType $contentType -Body $bodyLines -WebSession $session
$tempStore.Clear()
对于同一个文件,我已验证请求有效负载看起来完全相同。此外,我可以验证传递给 Import() 的字节数组是否相同。但是,当使用 curl/Invoke-WebRequest 方法时。我在 CryptographicException 中收到 'Cannot find the requested object' 消息。
我以前从未接触过 powershell,所以我希望有一个我可以实施的 C# 解决方案来解决这个问题,但我会采纳我能得到的任何建议。
@Eris 感谢您在评论中提供的解决方案。
$rawCertData = [System.IO.File]::ReadAllBytes($fileInfo)
$rawCertData = [System.Convert]::ToBase64String($rawCertData);
唯一让我感到奇怪的是使用网络表单时字节数组不同,但似乎 X509Certificate2.Import() 知道如何在任何一种情况下正确解析它。