Tor*_*Tor 5 c# certificate x509certificate2 x509certificate
我正在构建一些 .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++;
}
Run Code Online (Sandbox Code Playgroud)
SecurityHelper.DownloadSslCertificate是一种从网站 url 创建 X509Certificate2 的自定义方法。
cert是最低级别的证书,我可以拿回来,但我不能做的是获取链中的所有内容。chain.ChainElements如果机器上尚未安装链的其余部分,则仍然只有 1 层深。我的问题是,这是一个全新的 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;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑#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;
}
Run Code Online (Sandbox Code Playgroud)
然后为了用这个回调开始验证,我有类似的东西:
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
}
Run Code Online (Sandbox Code Playgroud)
... ETC
然后到时间AuthenticateAsClient结束时,局部callbackChainElements变量被设置为 的集合X509ChainElement。
小智 4
事实上,我使用 Powershell 做了一些与此非常相似的事情。
其中之一是更改 ServicePointManager 以忽略 SSL 验证(听起来,因为您本地可能没有根证书)。您想要将 ServerCertificateValidationCallback 设置为 true,这告诉它您正在使用自定义验证(或者在您的情况下,可能没有验证)。
从那里开始,你就可以带着链元素完成大部分任务了。您可以使用 Export 方法将证书导出到字节数组中:
foreach (X509ChainElement el in chain.ChainElements) {
var certToCreate = el.Certificate.Export(X509ContentType.Cert);
...
}
Run Code Online (Sandbox Code Playgroud)
从那里开始,只需对字节数组执行您想要的操作即可。您可以将其传递给另一个证书对象的构造函数,然后可以将其导入到 Java 密钥库中。
希望对您有所帮助,如果您还有其他问题,请告诉我。
编辑:实际上,我刚刚注意到这篇关于 在 .NET 中使用 X.509 证书的提示的文章。作者建议不要直接从字节数组写入,因为它将临时文件写入不会被清理的目录。所以他的建议是将字节数组写入磁盘,然后在完成后手动清理它。
| 归档时间: |
|
| 查看次数: |
3963 次 |
| 最近记录: |