跳到主要内容

6 篇博文 含有标签「https」

查看所有标签

https 详解

· 阅读需 7 分钟
1adybug
子虚伊人

对称加密

对称加密是一种加密算法,其中加密和解密使用同一个密钥。它的工作原理是,发送方用密钥对数据进行加密,接收方使用相同的密钥来解密数据。由于加密和解密过程中使用的密钥是相同的,因此被称为“对称”。

对称加密的基本流程

  1. 密钥生成:系统生成一个共享的秘密密钥。
  2. 加密:发送方使用密钥和对称加密算法对原始数据进行加密,生成密文。
  3. 传输密文:将密文传输给接收方。
  4. 解密:接收方使用相同的密钥解密密文,恢复原始数据。

常见的对称加密算法

  • DES(数据加密标准):一种较早的对称加密算法,密钥长度为 56 位,安全性较低。
  • AES(高级加密标准):一种现代的对称加密算法,密钥长度可以是 128 位、192 位或 256 位,具有较高的安全性和效率。

对称加密的优点

  • 加密速度快:对称加密比非对称加密在处理大数据时速度更快。
  • 算法简单:实现相对简单,资源消耗较低。

对称加密的缺点

  • 密钥管理困难:双方必须安全地共享和管理密钥。如果密钥被泄露,数据就不再安全。客户端是不可信的,所以客户端的密钥泄露后果很严重。
  • 不适用于大量用户的环境:因为每对用户需要单独的一套密钥,管理多个密钥对会非常复杂。

非对称加密

非对称加密是一种加密算法,它使用一对密钥:公钥私钥。这对密钥中的一个用于加密,另一个则用于解密。公钥可以公开给任何人,而私钥必须由所有者保密。非对称加密解决了对称加密中“密钥分发”的难题,因为加密和解密使用不同的密钥。

非对称加密的基本流程

  1. 密钥对生成:系统生成一对密钥,包含一个公钥和一个私钥。
  2. 公钥加密:发送方使用接收方的公钥对消息进行加密。
  3. 私钥解密:接收方使用自己的私钥解密密文,恢复原始数据。

由于使用不同的密钥,加密和解密过程更加安全,尤其是在公钥公开的情况下,只有持有对应私钥的人才能解密密文。

公钥私钥是非对称加密算法中的两种密钥,它们共同构成一对密钥,用于加密和解密数据。这两个密钥具有特殊的数学关系:使用一个密钥加密的数据,必须用另一个密钥来解密。

公钥和私钥

公钥(Public Key)

  • 定义:公钥是非对称加密中的一个密钥,可以公开给任何人使用。
  • 用途:主要用于加密数据和验证数字签名。任何人都可以使用接收方的公钥对消息进行加密。
  • 特点:即使公钥是公开的,没有对应的私钥,外部的人也无法解密数据,因此公钥的公开不会带来风险。

私钥(Private Key)

  • 定义:私钥是与公钥成对的密钥,必须严格保密,仅由密钥所有者掌握。
  • 用途:用于解密通过公钥加密的数据,或者用来生成数字签名,证明消息的真实性。
  • 特点:只有持有私钥的人才能解密用公钥加密的消息,或者验证私钥签署的数字签名的真实性。

公钥和私钥的工作原理

  1. 加密和解密

    • 发送方使用接收方的公钥加密数据。
    • 接收方使用自己的私钥解密数据。

    由于公钥可以公开,任何人都能加密消息,但只有持有私钥的人能解密。

  2. 数字签名

    • 发送方使用自己的私钥对消息进行签名,证明消息是由自己发出的。
    • 接收方使用发送方的公钥验证签名,确保消息的真实性。

    这种机制确保了消息的完整性和发送者的身份,防止了数据篡改和伪造。

公钥和私钥的应用场景

  • 加密通信:使用接收方的公钥加密数据,确保只有接收方能使用私钥解密。
  • 数字签名和认证:使用私钥进行签名,确保接收方能够验证消息的来源和真实性。
  • 密钥交换:通过非对称加密安全地交换对称加密所用的密钥。

关键点总结

  • 公钥可以公开,主要用于加密和验证签名。
  • 私钥必须保密,主要用于解密和生成签名。
  • 公钥和私钥是互补的,一个加密的数据只能通过另一个来解密。

常见的非对称加密算法

  • RSA(Rivest-Shamir-Adleman):一种广泛使用的非对称加密算法,常用于数字签名和密钥交换。
  • ECC(椭圆曲线加密):一种效率更高的非对称加密算法,提供相同安全性所需的密钥长度更短,计算更快。

非对称加密的优点

  • 安全性更高:由于公钥可以公开,私钥可以保持私密,非对称加密解决了对称加密中的密钥分发问题。
  • 支持数字签名:可以验证消息发送者的身份,确保消息的完整性和真实性。

非对称加密的缺点

  • 加密速度较慢:相比对称加密,非对称加密在处理大量数据时速度较慢,计算复杂度高。
  • 密钥长度较长:为了提供相同的安全性,非对称加密所需的密钥通常比对称加密的密钥长得多。

HTTPS

HTTPS(超文本传输安全协议)使用了对称加密、非对称加密和数字证书来保证通信的安全性。这个过程大致可以分为以下几个步骤:

  1. 建立安全连接:

    当浏览器连接到 HTTPS 网站时,服务器会发送其 SSL 证书给浏览器。这个证书包含了服务器的公钥,以及由可信任的证书颁发机构(CA)签名的证书信息。

  2. 验证证书:

    浏览器会验证证书的有效性,包括检查证书是否过期、是否由可信的 CA 签发等。这一步骤可以确保浏览器连接到的确实是预期的服务器,而不是某个冒充的恶意服务器。

  3. 生成会话密钥:

    验证通过后,浏览器会生成一个随机的对称密钥(会话密钥)。然后使用服务器的公钥对这个会话密钥进行加密。

  4. 密钥交换:

    浏览器将加密后的会话密钥发送给服务器。服务器使用自己的私钥解密,获得会话密钥。

  5. 安全通信:

    此后,浏览器和服务器就可以使用这个共享的会话密钥,通过对称加密算法来加密它们之间的所有通信内容。

为什么要使用这些技术:

  1. 非对称加密(公钥加密):

    • 用于安全地交换对称密钥
    • 解决了密钥分发的问题
    • 但是计算速度较慢
  2. 对称加密:

    • 用于加密实际的通信内容
    • 计算速度快,适合大量数据的加密
  3. CA 证书:

    • 用于验证服务器的身份
    • 防止中间人攻击

通过结合使用这些技术,HTTPS 能够:

  • 确保通信的机密性(防止被窃听)
  • 保证数据的完整性(防止被篡改)
  • 验证通信双方的身份(防止身份伪造)

这种方式既保证了安全性,又兼顾了效率,是目前互联网上广泛使用的安全通信方式。

在 nginx 中使用 https

· 阅读需 1 分钟
1adybug
子虚伊人
http {
server {
# 网站端口
listen 443 ssl;
# 网站域名
server_name urdomain.com;

# 证书地址
ssl_certificate /etc/letsencrypt/live/urdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/urdomain.com/privkey.pem;

location / {

#本地服务地址
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

在开发环境中使用 https

· 阅读需 1 分钟
1adybug
子虚伊人

现在很多环境下的网络请求要求必须是 https 请求,但是在开发或者内网环境下,无法使用 CA 机构颁发的证书,这时候可以使用 OpenSSL 提供的自签证书功能:

安装

在 windows 系统下,可以使用 winget 来安装第三方分发版本:

winget search openssl
# 选择一个版本较新的分发版本
winget install FireDaemon.OpenSSL

重启终端

生成证书

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout your-key.pem -out your-cert.pem

使用

import { readFileSync } from "fs"
import { createServer } from "https"

import express from "express"

const app = express()

const server = createServer(
{
key: readFileSync("your-key.pem"),
cert: readFileSync("your-cert.pem"),
},
app,
)

server.listen(3000)

在 Node.js 中使用 fetch 请求接口可能会报错:

TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11730:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: Error: self-signed certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
at TLSSocket.emit (node:events:514:28)
at TLSSocket._finishInit (node:_tls_wrap:1085:8)
at ssl.onhandshakedone (node:_tls_wrap:871:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
}
}

指定环境变量 NODE_TLS_REJECT_UNAUTHORIZED='0' 即可

npx cross-env NODE_TLS_REJECT_UNAUTHORIZED='0' node index.js

在 next.js 中使用 https

· 阅读需 1 分钟
1adybug
子虚伊人
import { readFileSync } from "fs"
import { createServer } from "https"
import { join } from "path"

import next from "next"

const app = next({})
const handle = app.getRequestHandler()

// https 证书相关
const key = readFileSync(join("/etc/letsencrypt/live", "yourdomain.com", "privkey.pem"), "utf8")

const cert = readFileSync(join("/etc/letsencrypt/live", "yourdomain.com", "cert.pem"), "utf8")
const ca = readFileSync(join("/etc/letsencrypt/live", "yourdomain.com", "chain.pem"), "utf8")

app.prepare().then(() => {
createServer({ key, cert, ca }, (req, res) => {
handle(req, res)
}).listen(3000)
})

在 Express 中使用 https 证书

· 阅读需 1 分钟
1adybug
子虚伊人
import { readFileSync } from "fs"
import https from "https"

import express from "express"

const app = express()

app.get("/", async (req, res) => {
res.send("Hello, World!")
})

https
.createServer(
{
key: readFileSync("../root/.acme.sh/a.deep-sea.dynv6.net_ecc/a.deep-sea.dynv6.net.key"),
cert: readFileSync("../root/.acme.sh/a.deep-sea.dynv6.net_ecc/fullchain.cer"),
},
app,
)
.listen(8080)