SDP中fingerprint的作用
sdp信息中会出现如下字段
a=fingerprint:sha-256 5D:60:1C:B7:B3:A7:C6:32:E8:6D:54:80:00:4B:26:0A:A1:62:CB:57:79:83:2D:69:A6:D9:B9:28:6A:77:71:C7
a=setup:actpass
那么fingerprint是在什么时候使用呢,翻阅mediasoup代码可以看到,在创建dtls连接的时候,会根据客户端建立的ssl获取到其证书,获取到证书之后,通过sdp中的加密算法,推算出对应的签名值,并与sdp中值进行比较,如果不对,那么证书被篡改,链接失效
代码如下:
fingerprint校验:
inline bool DtlsTransport::CheckRemoteFingerprint()
{
MS_TRACE();
MS_ASSERT(
this->remoteFingerprint.algorithm != FingerprintAlgorithm::NONE, "remote fingerprint not set");
X509* certificate;
uint8_t binaryFingerprint[EVP_MAX_MD_SIZE];
unsigned int size{ 0 };
char hexFingerprint[(EVP_MAX_MD_SIZE * 3) + 1];
const EVP_MD* hashFunction;
int ret;
certificate = SSL_get_peer_certificate(this->ssl);
if (!certificate)
{
MS_WARN_TAG(dtls, "no certificate was provided by the peer");
return false;
}
switch (this->remoteFingerprint.algorithm)
{
case FingerprintAlgorithm::SHA1:
hashFunction = EVP_sha1();
break;
case FingerprintAlgorithm::SHA224:
hashFunction = EVP_sha224();
break;
case FingerprintAlgorithm::SHA256:
hashFunction = EVP_sha256();
break;
case FingerprintAlgorithm::SHA384:
hashFunction = EVP_sha384();
break;
case FingerprintAlgorithm::SHA512:
hashFunction = EVP_sha512();
break;
default:
MS_ABORT("unknown algorithm");
}
// Compare the remote fingerprint with the value given via signaling.
ret = X509_digest(certificate, hashFunction, binaryFingerprint, &size);
if (ret == 0)
{
MS_ERROR("X509_digest() failed");
X509_free(certificate);
return false;
}
// Convert to hexadecimal format in uppercase with colons.
for (unsigned int i{ 0 }; i < size; ++i)
{
std::sprintf(hexFingerprint + (i * 3), "%.2X:", binaryFingerprint[i]);
}
hexFingerprint[(size * 3) - 1] = '\0';
if (this->remoteFingerprint.value != hexFingerprint)
{
MS_WARN_TAG(
dtls,
"fingerprint in the remote certificate (%s) does not match the announced one (%s)",
hexFingerprint,
this->remoteFingerprint.value.c_str());
X509_free(certificate);
return false;
}
MS_DEBUG_TAG(dtls, "valid remote fingerprint");
// Get the remote certificate in PEM format.
BIO* bio = BIO_new(BIO_s_mem());
// Ensure the underlying BUF_MEM structure is also freed.
// NOTE: Avoid stupid "warning: value computed is not used [-Wunused-value]" since
// BIO_set_close() always returns 1.
(void)BIO_set_close(bio, BIO_CLOSE);
ret = PEM_write_bio_X509(bio, certificate);
if (ret != 1)
{
LOG_OPENSSL_ERROR("PEM_write_bio_X509() failed");
X509_free(certificate);
BIO_free(bio);
return false;
}
BUF_MEM* mem;
BIO_get_mem_ptr(bio, &mem); // NOLINT[cppcoreguidelines-pro-type-cstyle-cast]
if (!mem || !mem->data || mem->length == 0u)
{
LOG_OPENSSL_ERROR("BIO_get_mem_ptr() failed");
X509_free(certificate);
BIO_free(bio);
return false;
}
this->remoteCert = std::string(mem->data, mem->length);
X509_free(certificate);
BIO_free(bio);
return true;
}
其中remoteFingerprint为sdp信息中的值,hexFingerprint为获取到的值。