Я хочу реализовать закрепление сертификата / открытого ключа в моем приложении C #. Я уже видел много решений, которые прикрепляют сертификат сервера напрямую, например, в этом вопросе. Однако для большей гибкости я хочу закрепить только корневой сертификат. Сертификат, который сервер получает в настройке, подписан промежуточным ЦС, который сам подписан корнем.
До сих пор я реализовал сервер, который загружает свой собственный сертификат, закрытый ключ, промежуточный сертификат и корневой сертификат из файла PKCS # 12 (.pfx). Я создал файл с помощью следующей команды:
openssl pkcs12 -export -inkey privkey.pem -in server_cert.pem -certfile chain.pem -out outfile.pfx
Файл chain.pem содержит корневой и промежуточный сертификаты.
Сервер загружает этот сертификат и хочет аутентифицироваться против клиента:
// certPath is the path to the .pfx file created before
var cert = new X509Certificate2(certPath, certPass)
var clientSocket = Socket.Accept();
var sslStream = new SslStream(
new NetworkStream(clientSocket),
false
);
try {
sslStream.AuthenticateAsServer(cert, false, SslProtocols.Tls12, false);
} catch(Exception) {
// Error during authentication
}
Теперь клиент хочет аутентифицировать сервер:
public void Connect() {
var con = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
con.Connect(new IPEndPoint(this.address, this.port));
var sslStream = new SslStream(
new NetworkStream(con),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("serverCN");
}
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
)
{
// ??
}
Проблема в том, что сервер отправляет клиенту только свой сертификат. Также параметр цепочка не содержит дополнительной информации. Это в какой-то степени правдоподобно, поскольку сертификат X509Certificate2 (в коде сервера) содержит только сертификат сервера и не содержит информации о промежуточном или корневом сертификате. Однако клиент не может проверить всю цепочку, поскольку (по крайней мере) промежуточный сертификат отсутствует.
До сих пор я не нашел возможности заставить .NET отправлять всю цепочку сертификатов, но я не хочу закреплять сертификат сервера iself или промежуточный, поскольку это разрушает гибкость закрепления корневого сертификата.
Следовательно, знает ли кто-нибудь возможность заставить SslStream отправлять всю цепочку для аутентификации или реализовать функциональность с использованием другого подхода? Или надо сертификаты по-другому упаковывать?
Спасибо!
Изменить: я сделал несколько других тестов, чтобы обнаружить проблему. Как было предложено в комментариях, я создал X509Store
, содержащий все сертификаты. После этого я построил X509Chain
, используя сертификат моего сервера и хранилище. На самом сервере новая цепочка правильно содержит все сертификаты, но не в функции ValidateServerCertificate
..
X509Chain
содержит цепочку центров сертификации, связанных с сертификатом сервера, вы можете увидеть это вRemoteCertificateValidationCallback
. Но вы используете свой собственный сертификат pfx, попробуйте сначала перечислить его и импортировать в хранилище сервера. Есть несколько статей с заголовком stackoverflow.com/questions/9141198/ и stackoverflow.com/questions/5036590/ - person Pavel Anikhouski   schedule 13.03.2019ChainElements
свойство объектаchain
в вашемValidateServerCertificate
методе должно иметь полную цепочку - person Pavel Anikhouski   schedule 13.03.2019ChainElements
содержит только один элемент на клиенте. Может быть, что-то не так с тем, как я создаю файл PKCS # 12? Вы знаете способ подтвердить это. - person PraMiD   schedule 13.03.2019openssl
- person Pavel Anikhouski   schedule 13.03.2019-in
, посколькуopenssl
будет смотреть только на последний из них. В опубликованной команде openssl, которую я использовал для создания файла pfx, я указал дополнительные сертификаты с помощью параметра-certfile
.X509Certificate2Collection
также может читать все три из них, но они не содержатся в цепочке на стороне клиента. Я добавил дополнительную информацию о проведенных мною тестах в исходный пост, возможно, это будет полезно. - person PraMiD   schedule 13.03.2019