我有一个有效的实现,但想确保它是安全的。目标是使用SSLStream并仅接受来自服务器的由特定RSA密钥签名的SSL证书。
这是我的连接代码:
var client = new TcpClient("server_address", port_number);
var sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient("SpeechGrid");
这是我对ValidateServerCertificate的实现:
private static bool ValidateServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors) {
// Only accept our specific key pair
foreach (var cert in chain.ChainElements) {
if (cert.Certificate.GetPublicKeyString() == k_prodPublicKey) {
return true;
}
}
return false;
}
由于X509Chain对象的丰富性,我想确保我不需要检查X509ChainStatusFlags.NotSignatureValid等内容。
例如,攻击者是否有可能“声称”由我的公钥签名,发送无效签名,并且这种攻击会起作用,因为.NET假设我正在检查所有这些标志?
谢谢!
更新:好的,到目前为止,我已决定将以下检查置于原始foreach之上。请注意,这有点特定于应用程序;例如,如果我希望证书过期,我会检查NotTimeValid等等。
foreach (var status in chain.ChainStatus) {
switch (status.Status) {
case X509ChainStatusFlags.Cyclic:
case X509ChainStatusFlags.NotSignatureValid:
case X509ChainStatusFlags.PartialChain:
return false;
}
}
答案 0 :(得分:1)
我会颠倒你在问题更新中添加的支票的逻辑。而不是寻找可能出错的东西并接受其他一切:
foreach (thing that I can think of that might be wrong)
return false;
if (public key matches regardless of other policy errors)
return true;
......我会寻找可能接受的错误,并拒绝任何其他政策错误:
if (policy errors)
{
foreach (error that is acceptable: remote name mismatch, untrusted root, etc.)
policy errors -= that particular error
}
if (any policy errors left)
return false;
else if (public key matches)
return true;
else
return false;
第一部分是这样的(我没有测试或编译它):
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
{
sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
}
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
{
var otherFlagsFound =
from i in chain.ChainStatus
where (i.Status & ~X509ChainStatusFlags.UntrustedRoot) != X509ChainStatusFlags.NoError
select i;
if (otherFlagsFound.Count() == 0)
{
sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
}
}
答案 1 :(得分:0)
您可以检查sslPolicyErrors参数是否存在其他错误,例如已过期,或者证书是否不受信任。如果一切正常,它应该返回SslPolicyErrors.None。从公钥导出私钥在计算上是不可行的,因此您不必担心其他人创建相同的密钥对并对其进行签名。