加密算法、摘要指纹、签名、CA证书全面梳理笔记

一、加密算法

1. 非对称加密

RSA:将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。 为了提升安全性,需要不断加长密钥长度,而这又会使加解密负担加重,因此需要一个新的算法来替代。

ECC :根据有限域上的椭圆曲线上的点群中的离散对数问题 ECDLP,ECDLP 是比因子分解问题更难的问题,它是指数级的难度。相比RSA有优势: 抗攻击性强 CPU 占用少 内容使用少 网络消耗低 加密速度快

ECC = 一种数学曲线(椭圆曲线密码学),是"原料"

DH = 一种密钥交换协议(Diffie-Hellman),是"用法"

ECDH = 在椭圆曲线上做 DH 密钥交换,是"具体产品"

非对称加密两大用途:

js 复制代码
┌─────────────────────────────────────────┐
│           非对称密码的两大用途            │
│                                         │
│  1. 密钥协商         2. 数字签名          │
│     ├─ DH                 ├─ DSA        │
│     ├─ ECDH ✓             ├─ ECDSA ✓    │
│     └─ X25519             └─ Ed25519    │
│         (现代首选)            (现代首选)  │
│                                         │
│  底层数学基础:ECC(椭圆曲线)             │
│  曲线名:P-256, P-384, Curve25519...    │
└─────────────────────────────────────────┘

2. 对称加密

对称加密的特点:加解密使用同一个密钥,速度相比非对称加密要快。 常见的对称加密算法:DES、3DES、AES

  • DES:已破解,不再安全,基本没有企业在用了,是对称加密算法的基石,具有学习价值

  • DESede(三重DES):替代DES出现的,计算密钥时间太长、加密效率不高,所以也基本上不用

  • AES:最常用的对称加密算法。密钥建立时间短、灵敏性好、内存需求低(不管怎样,反正就是好)

3. 哈希算法

散列解密算法的特点:不可逆/唯一/定长。 MD5速度更快,无法抵御碰撞攻击,但不适合用来做安全性校验; SHA1已被攻破,目前SHA256是目前更好的选择,安全性更高,但消耗时间也更多。

4. DSA数字签名算法(Digital Signature Algorithm)

js 复制代码
非对称密码学两大用途:

┌────────────────────────────────────────────────┐
│                                                │
│  非对称密钥对 (公钥 + 私钥)                      │
│       │                                        │
│       ├── 用途1: 加密/解密                      │
│       │    └─ RSA 可以,ECC 不方便              │
│       │                                        │
│       └── 用途2: 数字签名 ← DSA 就是这个         │
│            ├─ DSA (基于离散对数,已过时)         │
│            ├─ ECDSA (基于椭圆曲线) ← 你在用这个  │
│            └─ Ed25519 (更现代的椭圆曲线签名)     │
│                                                │
└────────────────────────────────────────────────┘

简单介绍ECDSA

js 复制代码
ECDSA = EC + DSA
        │     │
        │     └─ DSA: 签名算法(怎么做签名和验证)
        │           · 生成签名: 私钥 + 消息 → (r, s)
        │           · 验证签名: 公钥 + 消息 + (r, s) → 真/假
        │
        └─ EC: 底层数学基础(椭圆曲线)
              · 换成其他数学基础也行:
                - RSA 签名 (用的是大数分解难题)
                - DSA 原版 (用的是模幂运算离散对数)
                - ECDSA    (用的是椭圆曲线离散对数)

5. 相关的编码算法

Base64编码

加解密时经常会遇到有一个Base64编码的转换,所以这里也做一个简单介绍。

  • 输入:任意二进制数据
  • 输出:只用 64 个"安全字符"表示的文本
js 复制代码
┌─────────────────────────────────────────┐
│         Base64 字符表(64个)             │
│                                         │
│  A-Z (26)  a-z (26)  0-9 (10)  + / (2) │
│                                         │
│  全是可打印 ASCII 字符,且避开:           │
│  · 控制字符(\n, \r, \0...)             │
│  · 特殊 URL 字符(?, #, &...通过Base64URL)│
│  · JSON 转义字符(", \)                 │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│          Base64 字符串的识别特征              │
│                                             │
│  1. 只包含这些字符:                           │
│     A-Z a-z 0-9 + / =                       │
│                                             │
│  2. 经常以 = 或 == 结尾(填充符)              │
│                                             │
│  3. 长度永远是 4 的倍数                       │
│                                             │
│  4. 看起来像乱码,但没有奇怪的控制字符          │
└─────────────────────────────────────────────┘

相关编码对比:

js 复制代码
┌──────────┬──────────────┬─────────────────┬──────────────┐
│          │   标准 Base64 │    Base64URL     │    十六进制  │
├──────────┼──────────────┼─────────────────┼──────────────┤
│ 字符集   │ A-Za-z0-9+/  │ A-Za-z0-9-_     │ 0-9a-f       │
│ 填充     │ 用 = 补齐     │ 可以去掉 =       │ 不需要       │
│ URL安全  │ ❌ +/= 需转义 │ ✅ 直接放URL     │ ✅ 天然安全   │
│ 空间效率 │ 增加约 33%    │ 增加约 33%       │ 增加 100%    │
│ 典型用途 │ 邮件附件、证书│ JWT、JSON、URL  │ 调试、指纹   │
└──────────┴──────────────┴─────────────────┴──────────────┘

实例(同一二进制数据):
原始: [0xB9, 0x4D, 0x27, ...](32字节)

标准: "uU0nuZNOPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="    ← +和=在URL中麻烦
URL安全: "uU0nuZNOPgilLlLX2n2r-sSE7-N6U4DukIj3rOLvzek"  ← JSON中首选
十六进制: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9" ← 64字符

DER 编码

DER(Distinguished Encoding Rules)就是把结构化数据编码成"唯一确定的二进制格式",确保同一份数据在任何机器上编码结果完全一致。

为什么签名/证书需要它
js 复制代码
签名值本身是 (r, s) 两个大整数:
r = 0x8A2B...(32字节)
s = 0x3C7D...(32字节)

传输时怎么打包?

❌ 直接拼一起:接收方怎么知道从哪分开?
❌ JSON: {"r":"0x8A2B...","s":"0x3C7D..."}  → 太长,浪费空间
✅ DER: 用 TLV 格式编码,确定、唯一、紧凑
TLV 结构
js 复制代码
DER 的核心:TLV = Tag + Length + Value

┌──────┬──────────┬──────────────┐
│ Tag  │  Length  │    Value     │
│ 类型  │  长度    │     内容     │
├──────┼──────────┼──────────────┤
│ 1字节 │ 1~N字节  │  Length字节  │
└──────┴──────────┴──────────────┘

实际例子(ECDSA 签名):
签名 = 序列(r, s)

┌─ SEQUENCE ────────────────────────────────────────┐
│ Tag: 30 (SEQUENCE)                                │
│ Length: 44 (后面总共44字节)                         │
│                                                   │
│   ┌─ r 值 ──────────────┐  ┌─ s 值 ──────────────┐ │
│   │ Tag: 02 (INTEGER)   │  │ Tag: 02 (INTEGER)   │ │
│   │ Length: 20          │  │ Length: 20          │ │
│   │ Value: 8A2B...      │  │ Value: 3C7D...      │ │
│   └─────────────────────┘  └─────────────────────┘ │
└────────────────────────────────────────────────────┘

最终二进制(十六进制):
30 2C 02 14 8A2B... 02 14 3C7D...
│  │  │  │          │  │
│  │  │  │          │  └─ s 的 Value
│  │  │  │          └─ s 的 Length
│  │  │  └─ r 的 Value
│  │  └─ r 的 Length
│  └─ 总 Length
└─ 总 Tag
和 PEM 的关系
js 复制代码
DER  = 纯二进制,人是读不懂的
PEM  = DER 的 Base64 包装,加上 -----BEGIN xxx----- 头尾

同一个数据:
DER:  30 44 02 20 8A 2B...(二进制,文件后缀 .der)
PEM:  -----BEGIN PUBLIC KEY-----
      MFkwEwYHKoZI...
      -----END PUBLIC KEY-----
      (文本,文件后缀 .pem)

二、数字证书中学习摘要、签名、验签

先来看一个假设的签名和验签的过程,然后再逐个说明。

Plain 复制代码
┌──────────── 签名过程(客户端) ─────────────┐
│                                              │
│  请求JSON                                    │
│  {"user":"alice","amount":100}               │
│         │                                    │
│         ▼                                    │
│  SHA256 哈希                                 │
│  a1b2c3d4e5f6...(32字节摘要)               │
│         │                                    │
│         ▼                                    │
│  Secure Enclave 内                           │
│  用私钥 + ECDSA 算法计算签名                 │
│         │                                    │
│         ▼                                    │
│  签名值(r, s)DER编码 ≈ 70-72字节           │
│  30440220...base64url                        │
└──────────────────────────────────────────────┘

┌──────────── 验签过程(服务器) ─────────────┐
│                                              │
│  收到请求:                                   │
│  { "payload": "加密的JSON密文",              │
│    "signature": "30440220..." }              │
│         │                                    │
│         ▼                                    │
│  解密 payload → 得到原文                      │
│  {"user":"alice","amount":100}               │
│         │                                    │
│         ▼                                    │
│  对原文 SHA256 哈希                          │
│  a1b2c3d4e5f6...                            │
│         │                                    │
│         ▼                                    │
│  用客户端公钥 + 签名值 + 哈希值                │
│  → ECDSA 验证函数                            │
│         │                                    │
│         ▼                                    │
│  ✅ true / ❌ false                          │
└──────────────────────────────────────────────┘

摘要

任意长度输入 ──哈希函数──► 固定长度输出(摘要/指纹)

签名

js 复制代码
┌──────────────────────────────────────────────┐
│              数字签名的三大作用                 │
│                                              │
│  1. 完整性   证明消息没被篡改                    │
│  2. 认证     证明消息确实来自声称的发送者         │
│  3. 不可否认 发送者事后不能抵赖"这不是我发的"     │
└──────────────────────────────────────────────┘

签名及验签的的过程

arduino 复制代码
  明文 ──哈希──► 摘要 ──私钥签名──► 签名值
  验签时: 签名值 + 公钥 → 能验证"这个摘要确实是用对应私钥对这份明文产生的"

CA证书

如下是从浏览器查看的一个CA证书:

证书的主要内容:

js 复制代码
┌─────────────────────────────────────────────┐
│              X.509 数字证书                   │
│                                              │
│  ┌────────────────────────────────────┐      │
│  │  版本号: v3                         │      │
│  │  序列号: 0x1A2B3C...               │      │
│  │  签名算法: sha256WithRSAEncryption  │      │
│  │  颁发者: CN=My CA, O=My Company    │      │
│  │  有效期: 2025-01-01 ~ 2026-01-01   │      │
│  │  持有者: CN=app.example.com        │      │
│  ├────────────────────────────────────┤      │
│  │                                    │      │
│  │         ┌──────────────┐           │      │
│  │         │   公钥部分    │ ◄── 公钥指纹│      │
│  │         │  256 字节     │   计算这个  │      │
│  │         └──────────────┘           │      │
│  │                                    │      │
│  ├────────────────────────────────────┤      │
│  │  扩展: SAN, Key Usage...           │      │
│  ├────────────────────────────────────┤      │
│  │  CA 签名值: 30440220...            │      │
│  └────────────────────────────────────┘      │
│                                              │
│  证书指纹 = SHA256(整个文件)                   │
│  公钥指纹 = SHA256(只有公钥部分)               │
└─────────────────────────────────────────────┘

从权威CA证书颁发机构申请的证书链验证原理如下:

js 复制代码
┌─────────────────────────────────────────────────────────┐
│                    信任链(Chain of Trust)              │
│                                                         │
│  根CA(系统预置,绝对信任)                               │
│  ┌──────────────────────────────┐                       │
│  │ Root CA 自签名证书            │                       │
│  │ 公钥: root_pub              │                       │
│  │ 签名: root_priv(root_pub)   │ ← 自己签自己           │
│  └──────────────┬───────────────┘                       │
│                 │ 用 root_priv 签名                      │
│                 ▼                                       │
│  中间CA                                                  │
│  ┌──────────────────────────────┐                       │
│  │ Intermediate CA 证书         │                       │
│  │ 持有者: inter_pub           │                       │
│  │ 签发者: root_pub            │                       │
│  │ 签名: root_priv(inter_pub)  │                       │
│  └──────────────┬───────────────┘                       │
│                 │ 用 inter_priv 签名                     │
│                 ▼                                       │
│  终端证书(你的App)                                      │
│  ┌──────────────────────────────┐                       │
│  │ App 证书                     │                       │
│  │ 持有者: app_pub             │                       │
│  │ 签发者: inter_pub           │                       │
│  │ 签名: inter_priv(app_pub)   │                       │
│  └──────────────────────────────┘                       │
│                                                         │
│  验证路径:                                              │
│  app_pub ← 用 inter_pub 验签名 ← 用 root_pub 验签名 ✓   │
└─────────────────────────────────────────────────────────┘

自签证书与CA证书对比:

对比维度 自签 CA 商业 CA
签发者 你自己(服务器管理员) 受信的第三方机构(DigiCert、Let's Encrypt 等)
费用 免费 免费(Let's Encrypt)到数万元/年不等
浏览器/系统信任 默认不信任(红色警告) 默认信任(绿色锁)
适用场景 内部系统、App 间通信 公网网站、用户浏览器访问
信任建立方式 手动预埋证书或指纹 操作系统/浏览器预置根证书
管理复杂度 自己维护 CA 基础设施 到期续费,平台自动验证域名

为什么现在很多CA证书(包括上面图中的)写的是TLS RSA CA

这是历史惯性,不是因为它更安全。它们往往是十几年前就建好的基础设施:

最开始建根证书时: → 只有 RSA(1980s就有了) → ECC 还没成熟 / 支持度不够

于是根证书用了 RSA 4096 位密钥

到现在,它一直在给你签 TLS 证书(可能用 RSA,也可能用 ECDSA) 但它的"根"永远是那个老的 RSA 只要根证书还在有效期内,就一直这么标 (即使叶子证书用了更先进的 ECDSA 或 Ed25519,只要根证书是 RSA 的,证书链上依旧会看到 TLS RSA CA 标志。)

三、设计一个安全通信的规则

以下是一个不一定是HTTPS请求的一个安全通信设计:

js 复制代码
┌────────────────── 首次安装/注册 ──────────────────┐
│  客户端生成 ECDH 密钥对                            │
│  生成 Client_Identity_KeyPair (长期身份密钥)       │
│  Public_Identity_Key ──────► 服务器存储并签发证书  │
│  Private_Identity_Key 安全存储在 Keychain/Enclave  │
└────────────────────────────────────────────────────┘

┌────────────────── 建立安全会话 ─────────────────────────────┐
│                                                              │
│  客户端                                 服务器               │
│    │                                     │                   │
│    │ 1. 生成 ECDH 临时密钥对              │                   │
│    │    ephemeral_public_key ──────────►  │                   │
│    │                                     │ 2. 生成临时密钥对  │
│    │         ◄─────────── server_ephemeral_pub + 证书       │
│    │                                     │                   │
│    │ 3. ECDH 计算共享密钥                 │ ECDH 计算共享密钥 │
│    │    shared_secret = X25519(          │ shared_secret =   │
│    │      client_eph_priv,               │ X25519(server_   │
│    │      server_eph_pub)                │   eph_priv,      │
│    │                                     │   client_eph_pub)│
│    │ 4. HKDF 派生 session_key            │ HKDF 派生        │
│    │                                     │   session_key    │
│    │                                     │                   │
│    │ 5. session_key 对称加密通信内容      │                   │
│    │    + HMAC 完整性校验                 │                   │
│    │         ────────► verify & decrypt   │                   │
│    │                                     │                   │
│    │ 6. 身份签名(用长期身份密钥)         │                   │
│    │    签名关键操作,防止中间人            │ 验证身份签名      │
│                                                              │
└──────────────────────────────────────────────────────────────┘

10年前老项目的HTTP通信方式:(现在看来是不够完善的)

js 复制代码
┌─────────── 首次安装 ───────────┐
│  客户端生成 RSA 公私钥对        │
│  Client_Public_Key ──────► 服务器存储
│  Client_Private_Key 保留本地
└────────────────────────────────┘

┌─────────── 登录时 ────────────┐
│  客户端生成密钥Secret( UUID + 随机)   │
│  UUID 作为对称加密密钥          │
└────────────────────────────────┘

┌─────────── 关键请求 ──────────────────────────────────┐
│                                                        │
│  ① 用 Server_Public_Key 加密 (Secret+偏移字节) → key 字段   │
│  ② 用 UUID 对称加密 请求JSON → msg 字段                │
│  ③ 用 Client_Private_Key 签名 请求JSON → check 字段    │
│                                                        │
│  POST /api/secure                                     │
│  { key, msg, check } ─────────────────────► 服务器     │
└────────────────────────────────────────────────────────┘

┌─────────── 服务器处理 ────────────────────────────────-─┐
│                                                       │
│  ① Server_Private_Key 解密 key → Secret               │
│  ② Secret 解密 msg → json --》并计算Hash1               │
│  ③ Client_Public_Key 验签 check → JSON的哈希值HASH2     │
│  ④ 比对 Hash1 === Hash2                               │
│                                                        │
└────────────────────────────────────────────────────────┘

四、HTTPS的HMAC

Hash-based Message Authentication Code(基于哈希的消息认证码) 一句话:带密码的哈希。普通哈希谁都能算,HMAC 只有知道密钥的人才能算出来并验证。

js 复制代码
普通哈希 SHA256:
  任何人拿到 "hello" → 都能算出 b94d27b9...
  用于:验证数据有没有损坏(完整性)
  不能防:恶意篡改(攻击者改了数据,重新算个哈希就行)

HMAC-SHA256:
  只有知道密钥的人才能算出正确的 HMAC 值
  用于:验证数据有没有被篡改 + 证明它来自持有密钥的人(认证)
  能防:篡改、伪造

工作原理

js 复制代码
┌────────────── HMAC 计算过程 ──────────────┐
│                                            │
│  输入:                                      │
│  · 密钥 K (你的 secret)                     │
│  · 消息 M (要保护的数据)                     │
│                                             │
│  步骤:                                      │
│                                             │
│  1. 如果 K 比 block-size 长 → 先哈希缩短     │
│     如果 K 比 block-size 短 → 用 0 填充      │
│                                             │
│  2. 用 0x36 填充到 block-size → ipad        │
│     用 0x5c 填充到 block-size → opad        │
│                                             │
│  3. inner = SHA256((K ⊕ ipad) || M)         │
│                                             │
│  4. outer = SHA256((K ⊕ opad) || inner)     │
│                                             │
│  5. 输出: outer (32字节,和SHA256一样长)      │
│                                             │
└─────────────────────────────────────────────┘

图解流程:

密钥K    消息M
  │        │
  │        ▼
  │   ┌─────────┐
  │   │ (K⊕ipad)│ 异或内层填充
  │   └────┬────┘
  │        │
  │   K⊕ipad || M  ← 拼接
  │        │
  │        ▼
  │   ┌─────────┐
  │   │ SHA256  │ 第一次哈希
  │   └────┬────┘
  │        │  inner
  │        ▼
  │   (K⊕opad) || inner  ← 拼接外层
  │        │
  │        ▼
  │   ┌─────────┐
  │   │ SHA256  │ 第二次哈希
  │   └────┬────┘
  │        │
  │        ▼
  │   HMAC 值(32字节)
  │
  └── 输出

五、CRC数据校验

CRC = Cyclic Redundancy Check(循环冗余校验): 用多项式除法算出固定长度的校验码,贴在数据末尾,用来检测数据传输/存储中是否发生了意外损坏。

js 复制代码
┌──────────┬──────────────┬──────────────┬────────────────┐
│          │     CRC      │    SHA256    │     HMAC       │
├──────────┼──────────────┼──────────────┼────────────────┤
│ 目的     │ 检测意外损坏  │ 数据指纹     │ 防篡改+认证    │
│ 防意外   │ ✅ 极好       │ ✅ 极好      │ ✅ 极好        │
│ 防恶意   │ ❌ 一秒钟破解 │ ❌ 能重算    │ ✅ 没有密钥不行 │
│ 速度     │ 极快(硬件级)│ 较快         │ 较快           │
│ 输出长度 │ 8/16/32位    │ 256位        │ 256位          │
│ 典型场景 │ 网络包/硬盘   │ 文件指纹     │ API签名        │
└──────────┴──────────────┴──────────────┴────────────────┘

工作原理------多项式除法

js 复制代码
CRC 本质是把数据看成一个巨大的二进制数,除以一个固定的"生成多项式",
得到的余数就是 CRC 值。

┌────────── CRC-8 简化示例 ──────────┐
│                                    │
│  数据: 11010011101100              │
│  多项式: x³ + x + 1 → 除数: 1011   │
│                                    │
│  1. 数据末尾补 3 个零(多项式次数) │
│     11010011101100 000             │
│                                    │
│  2. 长除法(异或操作)              │
│     11010011101100000              │
│   ÷ 1011                           │
│   ─────────────                    │
│   ...(反复异或)                   │
│   ─────────────                    │
│     100 ← 余数 = CRC 值            │
│                                    │
│  3. 发送: 原始数据 + CRC           │
│     11010011101100 100             │
│                                    │
└────────────────────────────────────┘

接收端验证
┌────────── 验证流程 ──────────┐
│                              │
│  收到: 数据 + CRC            │
│  11010011101100 100          │
│                              │
│  对整个数据 + CRC 做除法:     │
│  11010011101100100           │
│  ÷ 1011                     │
│                              │
│  如果余数 = 0 → ✅ 数据完好   │
│  如果余数 ≠ 0 → ❌ 数据损坏   │
│                              │
│  为什么余数为零就对?         │
│  因为发送方特意选了 CRC 值    │
│  让 "数据+CRC" 能被多项式整除 │
└──────────────────────────────┘

实际应用场景

js 复制代码
┌──────────────────────────────────────────┐
│  CRC 在你平时看不见的地方大量存在          │
│                                          │
│  1. 网络传输                              │
│  ┌─────────────────────────────────┐     │
│  │ 以太网帧:                         │     │
│  │ [头部][数据][CRC-32] ← 每帧都校验  │     │
│  │ CRC 不对 → 直接丢弃,请对方重传    │     │
│  └─────────────────────────────────┘     │
│                                          │
│  2. 文件压缩                              │
│  ┌─────────────────────────────────┐     │
│  │ ZIP 文件:                         │     │
│  │ 每个压缩块末尾都有 CRC-32          │     │
│  │ 解压时比对 → 确认没损坏            │     │
│  └─────────────────────────────────┘     │
│                                          │
│  3. 存储系统                              │
│  ┌─────────────────────────────────┐     │
│  │ 硬盘/SSD 每个扇区:                │     │
│  │ [512/4096字节数据][CRC]           │     │
│  │ 读出时校验 → 发现坏块              │     │
│  └─────────────────────────────────┘     │
│                                          │
│  4. 嵌入式/IoT                            │
│  ┌─────────────────────────────────┐     │
│  │ 传感器数据包:                      │     │
│  │ 环境噪声大,容易比特翻转            │     │
│  │ CRC 检测 → 丢弃错误数据            │     │
│  └─────────────────────────────────┘     │
└──────────────────────────────────────────┘
相关推荐
他是龙5513 小时前
71:Python安全 & 反序列化 & PYC反编译 & 格式化字符串安全
开发语言·python·安全
幸福巡礼5 小时前
【LangChain 1.2 实战(八)】Agent Middleware 实战 —— 动态路由、监控、安全与容错
java·安全·langchain
xixixi777775 小时前
深度解读:网信办“清朗·整治AI应用乱象”专项行动,AI产业告别野蛮生长,全面迈入合规治理深水区
人工智能·安全·ai·大模型·合规·深度伪造·网信办
weixin_lizhao6 小时前
50天独立打造企业级API网关(二):安全防护体系与弹性设计
java·spring boot·安全·spring cloud·gateway
記億揺晃着的那天7 小时前
Claude Code 系统提示词里的安全底线:OWASP Top 10
安全·ai·ai编程·vibe coding·claude code
重明链迹实验室7 小时前
重明链迹丨每周区块链安全要闻(0427-0503)
安全·web3·区块链
百度安全8 小时前
HugeGraph 晋升 Apache 顶级项目 百度安全持续筑牢 AI 时代图数据基础设施
数据库·人工智能·安全·知识图谱
Bruce_Liuxiaowei9 小时前
AI投毒产业链曝光:安全工程师怎么看、怎么防
人工智能·安全·ai·投毒
Amy1870211182310 小时前
虚拟电厂为什么必须“牵手”微电网?答案全在这里
分布式·安全·能源