gpt4 book ai didi

c# - 从远程主机自动下载 X509 证书链

转载 作者:太空狗 更新时间:2023-10-30 01:19:02 25 4
gpt4 key购买 nike

我正在构建一些 .net 代码,这些代码将在我们的一台服务器上按计划无人值守运行。它的部分执行要求它执行一个 Java 可执行文件,该可执行文件通过 SSL 与一些 Web 资源和服务对话。

如果 Java 通过 SSL 执行某些操作并且它没有远程证书链中的每个证书,那么它绝对会适合。所以在 .NET 中,我需要能够指定一个 https:// 资源,并需要它在本地下载整个远程链。

为什么我要自动执行此操作?因为我想让部署变得简单,而不必这样做 4 次,然后每次 Oracle 的一个证书过期时都重复一遍。

我这样做:

 X509Certificate2 lowestCert = SecurityHelper.DownloadSslCertificate(keyDownloadLocation);

X509Chain chain = new X509Chain();
chain.Build(lowestCert);

int counter = 0;
foreach (X509ChainElement el in chain.ChainElements) {
//Extract certificate
X509Certificate2 chainCert = el.Certificate;

//Come up with an alias and save location
string alias = certBaseName + counter;
string localLocation = Path.GetDirectoryName(
System.Reflection.Assembly.GetEntryAssembly().Location
) + @"\" +alias + ".cer";

//Save it locally
SecurityHelper.SaveCertificateToFile(chainCert, localLocation);

//Remove (if possible) and add to java's keystore
deleteKeyFromKeystore(
javaFolder,
alias,
certKeyStore,
SecurityHelper.GetEncryptedAppSetting("JavaKeystorePassword")
);

addKeytoKeyStore(
localLocation,
javaFolder,
alias,
certKeyStore,
SecurityHelper.GetEncryptedAppSetting("JavaKeystorePassword")
);

//Then delete
if (File.Exists(localLocation)) File.Delete(localLocation);

counter++;
}

SecurityHelper.DownloadSslCertificate 是一种从网站 url 创建 X509Certificate2 的自定义方法。

cert 是最低级别的证书,我可以取回它,但我不能做的是获取链中的所有内容。如果链的其余部分尚未安装在机器上,chain.ChainElements 仍然只有一层深。我的问题是这是一个全新的 URL,具有完全未知的(对机器而言)证书,我想进入堆栈并递归下载每个证书。

有没有办法点击机器未知的 URL 并以编程方式下载链中的每个证书?

编辑:这是我下载 SSL 证书的方式:

public static X509Certificate2 DownloadSslCertificate(string strDNSEntry)
{
X509Certificate2 cert = null;
using (TcpClient client = new TcpClient())
{
client.Connect(strDNSEntry, 443);

SslStream ssl = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(
(sender, certificate, chain, sslPolicyErrors) => {
return true;
}
), null);
try
{
ssl.AuthenticateAsClient(strDNSEntry);
}
catch (AuthenticationException e)
{
ssl.Close();
client.Close();
return cert;
}
catch (Exception e)
{
ssl.Close();
client.Close();
return cert;
}
cert = new X509Certificate2(ssl.RemoteCertificate);
ssl.Close();
client.Close();
return cert;
}
}

编辑 #2 获取对我有用的远程 SSL 证书的解决方案是捕获在 SslStream.AuthenticateAsClient(url); 期间发生的验证回调中的链

 private static X509ChainElementCollection callbackChainElements = null;
private static bool CertificateValidationCallback(
Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
callbackChainElements = chain.ChainElements;
return true;
}

然后为了用这个回调启动验证,我有类似的东西:

public static X509Certificate2 DownloadSslCertificate(string url)
{
X509Certificate2 cert = null;
using (TcpClient client = new TcpClient())
{
client.Connect(url, 443);

SslStream ssl = new SslStream(client.GetStream(), false, CertificateValidationCallback, null);
try
{
ssl.AuthenticateAsClient(url); //will call CertificateValidationCallback
}

...等等

然后在 AuthenticateAsClient 完成时,本地 callbackChainElements 变量设置为 X509ChainElement 的集合。

最佳答案

实际上,我使用 Powershell 做了一些与此非常相似的事情。

其中一项正在更改 ServicePointManager 以忽略 SSL 验证(因为您可能没有本地根证书,听起来)。您要将 ServerCertificateValidationCallback 设置为 true,这告诉它您正在使用自定义验证(或者在您的情况下,可能没有验证)。

从那里开始,您已经完成了链元件的大部分工作。您可以使用 Export 方法将证书导出到字节数组中:

foreach (X509ChainElement el in chain.ChainElements) {
var certToCreate = el.Certificate.Export(X509ContentType.Cert);
...
}

从那里开始,您只需对字节数组执行您想要的操作即可。您可以将它传递给另一个证书对象的构造函数,然后您可以将其导入 Java keystore 。

希望对您有所帮助,如果您还有其他问题,请告诉我。

编辑:实际上,我刚刚在 tips working with X.509 certificates in .NET 上注意到这篇帖子.作者建议不要直接从字节数组写入,因为它会将临时文件写入未清理的目录。所以他的建议是先把字节数组写入磁盘,写完了再手动清理。

关于c# - 从远程主机自动下载 X509 证书链,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24618798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com