加密解密基本概念
什么是非对称加密
- 什么是公钥
这个就是谁都能获得的钥匙 - 什么是私钥
只有一个人能获得
非对称加密就是公钥上的锁,私钥才能打开,私钥上的锁公钥才能打开。比如说就是地下党接头的时候,把一个信息放在盒子里,然后这个盒子只有我能打开,这个盒子谁都可以放信息,但是只有要接收信息的那个人能打开。
数字签名
这样也不是安全的,因为如果那个人被逮住了,别人可以冒充公钥来骗别人。这就是数字签名的作用。
数字签名是一种用于验证电子文档或数据的身份和完整性的技术。数字签名实际上是一种数学算法,它使用一个私有密钥来加密文件的数字摘要,并将其附加到文件中,形成数字签名。数字摘要是根据文件内容计算出来的唯一字符串,任何对文件的修改都会改变数字摘要。数字签名的接收方可以使用公共密钥来解密数字签名,并使用相同的算法计算文件的数字摘要,然后将两个数字摘要进行比较。如果数字摘要匹配,接收方就可以确定文件没有被篡改,并且数字签名的私有密钥的持有者确实是文件的签署者。数字签名常用于保护电子邮件、文档、软件等的安全性和完整性,以及验证数字证书的有效性。
数字证书
数字证书就是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式,数字证书不是数字身份证,而是身份认证机构盖在数字身份证上的一个章或印(或者说加在数字身份证上的一个签名)。它是由权威机构–CA机构,又称为证书授权(Certificate Authority)中心发行的,人们可以在网上用它来识别对方的身份。
私有证书
-x:证书的格式,509最有名
-days:有效多少天
-newdey rsa:1024:是否有密钥,没有就生成一个
-nodes:不加密
-keyout server.key:生成密钥文件
-out server.cert:证书名字
常用加密算法
OpenSSL
- 什么是OpenSSL
就是开源的SSL - SSL , Secure Sockets Layer
这个就是安全套接字层 - TLS,Transort Layer Security
标准化,传输层安全协议
TLS协议
TLS握手协议
TLS 记录协议
OpenSSL原理
OpenSSL 采用了多种密码学算法和协议来实现其安全功能。它支持各种对称密码算法,如 AES、DES 和 Blowfish,用于加密和解密数据。此外,它还支持非对称密码算法,如 RSA 和 DSA,用于生成公钥和私钥,并进行数字签名和验证。OpenSSL 还支持 SSL/TLS 协议,用于在网络通信中建立安全连接。
SSL_CTX
SSL:代表一SSL 连接
SSL_Write/SSL_Read
如何使用OpenSSL原理
链接
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>
int main() {
// 初始化 OpenSSL
SSL_library_init();
// 创建 SSL 上下文
SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) {
printf("Failed to create SSL context.\n");
return 1;
}
// 加载服务器证书
if (SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM) != 1) {
printf("Failed to load server certificate.\n");
SSL_CTX_free(ctx);
return 1;
}
// 加载服务器私钥
if (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) != 1) {
printf("Failed to load server private key.\n");
SSL_CTX_free(ctx);
return 1;
}
// 创建 SSL 对象
SSL *ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create SSL object.\n");
SSL_CTX_free(ctx);
return 1;
}
// 设置连接套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Failed to create socket.\n");
SSL_free(ssl);
SSL_CTX_free(ctx);
return 1;
}
// 连接服务器
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(443);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
printf("Failed to connect to server.\n");
SSL_free(ssl);
SSL_CTX_free(ctx);
return 1;
}
// 将 SSL 对象绑定到连接套接字
SSL_set_fd(ssl, sockfd);
// 建立 SSL 连接
if (SSL_connect(ssl) <= 0) {
printf("Failed to establish SSL connection.\n");
SSL_free(ssl);
SSL_CTX_free(ctx);
return 1;
}
// 发送数据
char message[] = "Hello, server!";
SSL_write(ssl, message, strlen(message));
// 接收数据
char buffer[1024];
SSL_read(ssl, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
// 关闭 SSL 连接
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
return 0;
}
DTLS协议
- TLS是基于TCP协议的
- DTLS基于UDP协议的
DTLS(Datagram Transport Layer Security) 是基于 UDP 场景下数据包可能丢失或重新排序的现实情况下,为 UDP 定制和改进的 TLS 协议。在 WebRTC 中使用 DTLS 的地方包括两部分: 协商和管理 SRTP 密钥和为 DataChannel 提供加密通道。
DTLS握手协议
这个是四次握手,具体可以看看这个链接
DTLS时序图
1.实际上在握手之前还需要做很多事情,其中之一就是交换SDP信息,也就是媒体协商(需要通过信令进行连接),其中也包含交换了ICE的password和username
2.经过1之后就找到对方的Candidate了,也就是相互知道了对方 的ip和端口使用的协议是什么。下面就是在数据传输之前首先发送STUN request 把password与username带给流媒体服务器,流媒体服务器将用户名密码取出来与第一阶段中的用户名密码比较是否是一致的,如果带过来的是一致的,那说明用户是合法的,就会返回一个连接成功的 响应。
3.客户端收到这个响应后就会进行DTLS的四次握手(传递证书,公钥,私钥, 加密算法)
4.握手后就开始传送数据
SDP中比较关键的信息
DTLS-SRTP(真正在webRTC使用的协议)
DTLS-SRTP是DTLS的一个扩展,将SRTP加解密与DTLS的key交换和会话管理相结合。从SRTP的角度看,是为其提供一种新的key协商管理的方法;从DTLS的角度看,是为应用数据提供一个新的数据格式(SRTP/SRTCP)。
1,应用层数据加解密是由SRTP完成的,要求必须是RTP/RTCP的格式。
2,DTLS的握手过程是为SRTP加解密过程协商使用哪种profile和密钥。
3,除了应用数据加密为SRTP格式,其他record-layer的报文仍为普通的DTLS格式(比如TLS control message)
4,当发送SRTP格式的应用层数据时,需要直接跳过DTLS加密层,将SRTP数据包透传到下层的数据传输层做发送。
由于密钥和加密参数是在DTLS握手过程中协商得到的,而此过程是保密的,因而相比常规的方式(比如在通过SDP消息交互来协商)更为安全。在发起DTLS握手之前,需要先设置use-srtp扩展。
接收端使用 DTLS-SRTP
自DTLS下层的传输层收到报文之后,需要根据包头特征手动区分做demultiplexing,一般可以如下进行
检查第一个报文的第一个字节
1,是[0, 1]时,表示可能是STUN报文
2,是[128, 191]时,表示可能时RTP(SRTP)报文
3,是[20, 63]时,表示可能是DTLS record layer报文
其他的类别请根据实际情况做区分处理
DTLS握手成功之后,需要导出key material,然后从中分离出server/client端用于SRTP对称加密的密钥。key material中对应SRTP的密钥,构成如下
client_master_key server_master_key client_salt server_salt
其中 master_key 和 salt 的长度是根据最终协商的 SRTP 的profile来确定的。
DTLS要解决的问题
- 交换密钥
- 确认加密算法
SRTP要解决的问题
对数据加密,保证数据安全
保证数据完整性
与普通的RTP头一样,头不加密,只有数据加密。
libsrtp
开源的库。