1 回答

TA貢獻(xiàn)1821條經(jīng)驗(yàn) 獲得超6個(gè)贊
SslStream 永遠(yuǎn)不會(huì)發(fā)送整個(gè)鏈(自我頒發(fā)的證書除外)。約定是發(fā)送除根以外的所有內(nèi)容,因?yàn)榱硪环揭匆呀?jīng)擁有并信任根,要么沒有(因此/或不信任根),無論哪種方式都是浪費(fèi)帶寬。
但是 SslStream 只有在理解中間體時(shí)才能發(fā)送中間體。
var cert = new X509Certificate2(certPath, certPass);
這只會(huì)提取最終實(shí)體證書(帶有私鑰的證書),它會(huì)丟棄 PFX 中的任何其他證書。如果要加載需要使用的所有證書X509Certificate2Collection.Import
。但是......這也對(duì)你沒有幫助。SslStream 只接受最終實(shí)體證書,它希望系統(tǒng)能夠?yàn)樗鼧?gòu)建一個(gè)功能鏈。
為了構(gòu)建功能鏈,您的中間證書和根證書需要位于以下任一位置:
通過 X509Chain.ChainPolicy.ExtraStore 作為手動(dòng)輸入提供
由于有問題的鏈?zhǔn)怯?SslStream 構(gòu)建的,因此您不能在這里真正做到這一點(diǎn)。
當(dāng)前用戶\我的 X509Store
*LocalMachine\My X509Store
CurrentUser\CA X509Store
**LocalMachine\CA X509Store
CurrentUser\Root X509Store
**LocalMachine\Root X509Store
*LocalMachine\ThirdPartyRoot X509Store
http
在證書的授權(quán)訪問標(biāo)識(shí)符擴(kuò)展中標(biāo)識(shí)的(非 s)位置。
*
在 Linux 上的 .NET Core 上不存在標(biāo)記為的商店。標(biāo)記 的存儲(chǔ)**
在 Linux 上確實(shí)存在,但不能由 .NET 應(yīng)用程序修改。
這還不夠,因?yàn)椋ㄖ辽賹?duì)于 Linux 上的 SslStream 和 .NET Core 上的 macOS 而言)它仍然只在構(gòu)建它信任的鏈時(shí)才發(fā)送中間體。因此,服務(wù)器需要真正信任根證書才能發(fā)送中間證書。(或者客戶端需要信任客戶端證書的根)
另一方面,同樣的規(guī)則也適用。不同之處在于,在回調(diào)中您可以選擇重建鏈以添加額外的證書。
private static bool IsExpectedRootPin(X509Chain chain)
{
X509Certificate2 lastCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
return lastCert.RawBytes.SequenceEquals(s_pinnedRootBytes);
}
private static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
)
{
if ((sslPolicyErrors & ~SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
// No cert, or name mismatch (or any future errors)
return false;
}
if (IsExpectedRootPin(chain))
{
return true;
}
chain.ChainPolicy.ExtraStore.Add(s_intermediateCert);
chain.ChainPolicy.ExtraStore.Add(s_pinnedRoot);
chain.ChainPolicy.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority;
if (chain.Build(chain.ChainElements[0].Certificate))
{
return IsExpectedRootPin(chain);
}
return false;
}
當(dāng)然,這種方法的問題是你還需要了解并提供遠(yuǎn)程端的中間件。真正的解決方案是中間體應(yīng)該在 HTTP 分發(fā)端點(diǎn)上可用,并且頒發(fā)的證書應(yīng)該帶有授權(quán)信息訪問擴(kuò)展,以便能夠動(dòng)態(tài)定位它們。
- 1 回答
- 0 關(guān)注
- 188 瀏覽
添加回答
舉報(bào)