HTTP与HTTPS的区别及HTTPS的加密原理
HTTP 与 HTTPS 的区别
协议基础
HTTP 即超文本传输协议(HyperText Transfer Protocol),是用于从万维网(WWW: World Wide Web )服务器传输超文本到本地浏览器的传送协议 。它基于 TCP/IP 协议,工作在应用层,是一种无状态协议,这意味着服务器不会保留关于客户端的任何信息,每次请求都是独立的。例如,当用户在浏览器中输入一个网址并回车,浏览器就会发起一个 HTTP 请求到对应的服务器,服务器收到请求后返回相应的网页内容。其通信过程大致如下:
- 客户端(浏览器)与服务器建立 TCP 连接。
- 客户端向服务器发送 HTTP 请求报文,包括请求方法(如 GET、POST 等)、请求头(包含一些元信息,如 User - Agent 等)和请求体(如果是 POST 请求,可能包含提交的数据)。
- 服务器接收到请求后,解析请求报文,根据请求的内容处理业务逻辑,并生成 HTTP 响应报文,同样包括响应状态码(如 200 表示成功,404 表示未找到等)、响应头(如 Content - Type 等)和响应体(即返回给客户端的实际数据,如 HTML 页面内容)。
- 服务器将响应报文发送回客户端,客户端接收并解析响应,然后将网页内容展示给用户。最后关闭 TCP 连接。
HTTPS 则是超文本传输安全协议(Hyper - Text Transfer Protocol over Secure Socket Layer),可理解为 HTTP + SSL/TLS。它也是工作在应用层,不过在 HTTP 与 TCP 层之间增加了 SSL/TLS 层。SSL(Secure Sockets Layer)即安全套接层,后来被 IETF 标准化并改名为 TLS(Transport Layer Security),目前广泛使用的是 TLS 协议。HTTPS 使得数据在传输过程中更加安全,因为它对传输的数据进行了加密。
安全性差异
- 数据传输加密
- HTTP 在数据传输过程中是明文的,这意味着数据在网络中传输时,任何处于网络传输路径上的设备(如路由器、中间节点等)都可以轻松获取到传输的内容。例如,用户在一个 HTTP 页面上输入用户名和密码进行登录,这些信息在传输过程中没有任何加密措施,一旦被第三方截获,用户的账号信息就会泄露。
- HTTPS 通过 SSL/TLS 协议对传输的数据进行加密。在建立连接阶段,客户端和服务器会协商加密算法和密钥,之后传输的数据都会使用协商好的密钥进行加密。这样即使数据被截获,第三方没有解密密钥也无法获取真实的数据内容。
- 身份验证
- HTTP 协议本身不对服务器进行身份验证,这就导致用户可能访问到伪装的服务器。比如,黑客可以搭建一个与真实银行网站一模一样的假网站,诱导用户输入账号密码等敏感信息。由于 HTTP 无法确认服务器的真实身份,用户很难察觉自己访问的是一个假网站。
- HTTPS 服务器需要向权威的证书颁发机构(CA,Certificate Authority)申请数字证书,客户端在与服务器建立连接时,会验证服务器的数字证书。如果证书是由受信任的 CA 颁发且证书信息与服务器匹配,客户端才会信任该服务器,从而建立安全连接。这大大降低了用户访问到假冒服务器的风险。
性能影响
- 连接建立过程
- HTTP 建立连接相对简单,只需经过 TCP 的三次握手即可开始传输数据。例如,在一个简单的网页请求场景下,从客户端发起连接请求到开始接收数据,HTTP 可以在较短时间内完成。
- HTTPS 在建立连接时,除了 TCP 的三次握手,还需要进行 SSL/TLS 握手。在 SSL/TLS 握手过程中,客户端和服务器要协商加密算法、交换密钥等操作,这使得连接建立过程更加复杂和耗时。例如,在一个 HTTPS 网站的首次访问中,可能会感觉到比 HTTP 网站稍慢一些,就是因为额外的 SSL/TLS 握手过程。
- 资源消耗
- HTTP 由于没有加密和解密的过程,对服务器和客户端的计算资源消耗相对较少。服务器可以快速处理请求并返回响应,客户端也能快速解析和展示内容。
- HTTPS 因为需要进行加密和解密操作,无论是服务器还是客户端都需要消耗更多的 CPU 和内存资源。例如,服务器在处理 HTTPS 请求时,需要使用 CPU 资源来进行加密算法的运算,这可能会导致服务器在高并发情况下性能下降,需要更高配置的硬件来支持。
端口与 URL 差异
- 端口
- HTTP 默认使用 80 端口。当我们在浏览器中输入一个网址,如
http://www.example.com
,如果没有指定端口号,浏览器会默认使用 80 端口与服务器建立连接。 - HTTPS 默认使用 443 端口。同样,当输入
https://www.example.com
时,浏览器会自动使用 443 端口与服务器进行通信。
- HTTP 默认使用 80 端口。当我们在浏览器中输入一个网址,如
- URL
- HTTP 的 URL 以
http://
开头,清晰地表明这是一个普通的超文本传输协议连接。例如http://news.cn
,用户看到这样的 URL 就知道该网站可能没有加密传输。 - HTTPS 的 URL 以
https://
开头,直观地告诉用户这个连接是安全加密的。例如https://pay.taobao.com
,在涉及支付等敏感操作的网站,使用 HTTPS 可以让用户更放心。
- HTTP 的 URL 以
HTTPS 的加密原理
加密算法基础
- 对称加密
对称加密是指加密和解密使用相同密钥的加密算法。例如,常见的对称加密算法有 AES(高级加密标准,Advanced Encryption Standard)。假设客户端和服务器协商好使用 AES 算法和一个共享密钥
key
。客户端要发送数据data
给服务器,它会使用key
对data
进行加密,得到密文encryptedData
。然后将encryptedData
发送给服务器。服务器收到encryptedData
后,使用相同的key
进行解密,就可以得到原始数据data
。对称加密的优点是加密和解密速度快,适合大量数据的加密。但缺点是密钥的管理和分发比较困难,如果密钥在传输过程中被泄露,那么数据就会失去保密性。以下是一个简单的 Python 示例,使用pycryptodome
库实现 AES 对称加密:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os
# 生成一个 16 字节的随机密钥
key = os.urandom(16)
# 待加密的数据
data = b"Hello, this is a secret message"
# 创建 AES 加密器
cipher = AES.new(key, AES.MODE_CBC)
# 对数据进行填充并加密
encrypted_data = cipher.encrypt(pad(data, AES.block_size))
# 创建 AES 解密器
decipher = AES.new(key, AES.MODE_CBC, cipher.iv)
# 解密并去除填充
decrypted_data = unpad(decipher.decrypt(encrypted_data), AES.block_size)
print(decrypted_data.decode('utf - 8'))
- 非对称加密
非对称加密使用一对密钥,即公钥和私钥。公钥可以公开给任何人,私钥则由所有者妥善保管。例如,RSA 算法就是一种常见的非对称加密算法。假设服务器生成了一对 RSA 密钥,公钥
publicKey
和私钥privateKey
。客户端要向服务器发送数据data
,它会使用服务器的公钥publicKey
对data
进行加密,得到密文encryptedData
。然后将encryptedData
发送给服务器。服务器收到encryptedData
后,使用自己的私钥privateKey
进行解密,从而得到原始数据data
。非对称加密的优点是密钥管理相对简单,公钥可以公开分发,不需要担心像对称加密那样密钥传输过程中的泄露问题。但缺点是加密和解密速度较慢,不适合大量数据的加密。以下是一个简单的 Python 示例,使用cryptography
库实现 RSA 非对称加密:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
# 生成私钥
private_key = rsa.generate_private_key(
public_exponent = 65537,
key_size = 2048,
backend = default_backend()
)
# 生成公钥
public_key = private_key.public_key()
# 将私钥序列化为 PEM 格式
private_pem = private_key.private_bytes(
encoding = serialization.Encoding.PEM,
format = serialization.PrivateFormat.PKCS8,
encryption_algorithm = serialization.NoEncryption()
)
# 将公钥序列化为 PEM 格式
public_pem = public_key.public_bytes(
encoding = serialization.Encoding.PEM,
format = serialization.PublicFormat.SubjectPublicKeyInfo
)
# 待加密的数据
message = b"Hello, this is a secret message"
# 使用公钥加密
encrypted = public_key.encrypt(
message,
padding.OAEP(
mgf = padding.MGF1(algorithm = hashes.SHA256()),
algorithm = hashes.SHA256(),
label = None
)
)
# 使用私钥解密
decrypted = private_key.decrypt(
encrypted,
padding.OAEP(
mgf = padding.MGF1(algorithm = hashes.SHA256()),
algorithm = hashes.SHA256(),
label = None
)
)
print(decrypted.decode('utf - 8'))
SSL/TLS 握手过程
- 客户端发起请求
客户端向服务器发送一个
ClientHello
消息,其中包含客户端支持的 SSL/TLS 版本、加密算法列表、压缩方法列表以及一个随机数ClientRandom
。例如,客户端可能支持 TLS 1.2 和 TLS 1.3 版本,加密算法列表中包含 AES - 256 - GCM、ChaCha20 - Poly1305 等。这个随机数ClientRandom
用于后续生成会话密钥。 - 服务器响应
服务器收到
ClientHello
消息后,回复一个ServerHello
消息。在这个消息中,服务器选择一个客户端支持的 SSL/TLS 版本、加密算法、压缩方法,并生成一个随机数ServerRandom
。同时,服务器会将自己的数字证书发送给客户端。数字证书包含了服务器的公钥以及一些关于服务器身份的信息,如域名、证书颁发机构等。例如,服务器选择 TLS 1.3 版本,加密算法为 AES - 256 - GCM,然后将相关信息和证书发送给客户端。 - 客户端验证证书 客户端收到服务器的证书后,会验证证书的有效性。它首先检查证书是否由受信任的证书颁发机构(CA)颁发,然后验证证书中的域名是否与当前访问的域名一致,以及证书是否在有效期内等。如果证书验证通过,客户端会从证书中提取服务器的公钥。如果证书验证失败,客户端会显示一个警告信息,提示用户连接可能不安全。
- 密钥交换
客户端生成一个预主密钥
PreMasterSecret
,并使用从证书中提取的服务器公钥对其进行加密,然后将加密后的预主密钥发送给服务器。服务器收到加密的预主密钥后,使用自己的私钥进行解密,得到预主密钥PreMasterSecret
。此时,客户端和服务器都拥有了ClientRandom
、ServerRandom
和PreMasterSecret
,通过一定的算法,它们可以生成相同的会话密钥SessionKey
。例如,在 TLS 1.3 中,使用 HKDF(HMAC - based Key Derivation Function)算法,基于ClientRandom
、ServerRandom
和PreMasterSecret
生成会话密钥。 - 加密通信
客户端和服务器使用生成的会话密钥
SessionKey
进行对称加密通信。客户端发送一个ChangeCipherSpec
消息,告诉服务器后续的通信将使用新协商的加密算法和密钥。然后客户端发送一个Finished
消息,该消息是使用新的加密算法和密钥对之前所有握手消息的摘要进行加密得到的。服务器收到ChangeCipherSpec
和Finished
消息后,也发送自己的ChangeCipherSpec
和Finished
消息。双方收到对方的Finished
消息并验证通过后,就可以开始使用对称加密进行正常的数据传输了。
数字证书
- 证书的生成与颁发 服务器要获得数字证书,需要向证书颁发机构(CA)提交证书申请。在申请过程中,服务器需要提供一些信息,如域名、组织信息等,并生成一对密钥(通常是 RSA 密钥对),将公钥包含在申请中。CA 收到申请后,会对服务器提交的信息进行验证,确保服务器的身份真实可靠。验证通过后,CA 使用自己的私钥对服务器的公钥以及其他相关信息(如域名、有效期等)进行签名,生成数字证书。例如,Let's Encrypt 是一个免费的 CA,许多网站都通过 Let's Encrypt 获取数字证书。
- 证书的验证
当客户端收到服务器的数字证书时,它会使用 CA 的公钥来验证证书上的签名。因为 CA 的公钥是被广泛信任并预装在操作系统、浏览器等客户端软件中的。如果签名验证通过,说明证书是由受信任的 CA 颁发的。然后客户端会检查证书中的其他信息,如域名是否匹配、证书是否过期等。只有当所有验证都通过后,客户端才会信任服务器的身份,并继续进行后续的 SSL/TLS 握手过程。例如,如果证书中的域名是
example.com
,而客户端访问的是example.org
,那么域名匹配验证就会失败,客户端会提示用户连接存在风险。
总结差异与加密原理在实践中的重要性
在实际的后端开发和网络应用中,理解 HTTP 与 HTTPS 的区别以及 HTTPS 的加密原理至关重要。对于涉及用户敏感信息(如登录密码、支付信息等)的应用,必须使用 HTTPS 来确保数据的安全性和用户的隐私。从开发角度看,开发人员需要了解如何配置服务器以支持 HTTPS,包括获取和安装数字证书、配置 SSL/TLS 相关参数等。同时,在性能优化方面,要考虑 HTTPS 带来的额外开销,如通过优化 SSL/TLS 握手过程、合理配置加密算法等方式来减少性能影响。对于用户而言,能够识别 HTTP 和 HTTPS 的差异,看到浏览器地址栏中的锁形图标(表示 HTTPS 连接安全),会增加对网站的信任度。总之,深入理解这些知识对于构建安全、可靠且高效的网络应用具有重要意义。