2024年11月

在Java中使用FFmpeg拉取RTSP流并推送到另一个目标地址是一个相对复杂的任务,因为Java本身并没有直接处理视频流的功能。但是,我们可以借助FFmpeg命令行工具来实现这个功能。FFmpeg是一个非常强大的多媒体处理工具,能够处理音频、视频以及其他多媒体文件和流。

为了在Java中调用FFmpeg,我们通常会使用
ProcessBuilder

Runtime.getRuntime().exec()
来执行FFmpeg命令。在这个示例中,我们将展示如何使用
ProcessBuilder
来拉取RTSP流并推送到另一个RTSP服务器。

一、前提条件

  1. 安装FFmpeg
    :确保你的系统上已经安装了FFmpeg,并且可以从命令行访问它。
  2. RTSP源和目标
    :确保你有一个有效的RTSP源URL和一个目标RTSP服务器URL。

二、代码示例一

以下是一个完整的Java示例代码,展示了如何使用
ProcessBuilder
来调用FFmpeg命令,从RTSP源拉取视频流并推送到另一个RTSP服务器。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class FFmpegRTSPStreamer {
 
    public static void main(String[] args) {
        // RTSP source and destination URLs
        String rtspSourceUrl = "rtsp://your_source_ip:port/stream";
        String rtspDestinationUrl = "rtsp://your_destination_ip:port/stream";
 
        // FFmpeg command to pull RTSP stream and push to another RTSP server
        String ffmpegCommand = String.format(
                "ffmpeg -i %s -c copy -f rtsp %s",
                rtspSourceUrl, rtspDestinationUrl
        );
 
        // Create a ProcessBuilder to execute the FFmpeg command
        ProcessBuilder processBuilder = new ProcessBuilder(
                "bash", "-c", ffmpegCommand
        );
 
        // Redirect FFmpeg's stderr to the Java process's standard output
        processBuilder.redirectErrorStream(true);
 
        try {
            // Start the FFmpeg process
            Process process = processBuilder.start();
 
            // Create BufferedReader to read the output from FFmpeg process
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
 
            // Wait for the process to complete
            int exitCode = process.waitFor();
            System.out.println("\nFFmpeg process exited with code: " + exitCode);
 
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

三、代码示例一说明及注意事项

(一)说明

  1. RTSP URLs:
    • rtspSourceUrl
      :你的RTSP源地址。
    • rtspDestinationUrl
      :你的目标RTSP服务器地址。
  2. FFmpeg命令:
    • ffmpeg -i <source> -c copy -f rtsp <destination>
      :这是FFmpeg的基本命令格式,用于从源拉取流并复制到目标。
      -c copy
      表示不重新编码,直接复制流。
  3. ProcessBuilder:
    • 我们使用
      ProcessBuilder
      来构建和执行FFmpeg命令。由于FFmpeg是一个命令行工具,我们在
      ProcessBuilder
      中指定了
      bash -c
      来执行FFmpeg命令。
    • redirectErrorStream(true)
      将FFmpeg的stderr重定向到stdout,这样我们可以在Java程序中看到FFmpeg的输出。
  4. BufferedReader:
    • 我们使用
      BufferedReader
      来读取FFmpeg进程的输出,并将其打印到Java程序的控制台。
  5. 等待进程完成:
    • 使用
      process.waitFor()
      等待FFmpeg进程完成,并获取其退出代码。

(二)注意事项

  • 路径问题
    :确保FFmpeg命令可以在你的系统路径中找到。如果FFmpeg不在系统路径中,你需要提供FFmpeg的完整路径。
  • 错误处理
    :示例代码中的错误处理比较简单,你可以根据需要添加更详细的错误处理逻辑。
  • 性能
    :直接在Java中调用FFmpeg命令可能会受到Java进程和FFmpeg进程之间通信效率的限制。对于高性能需求,可能需要考虑使用JNI或其他更底层的集成方法。

四、代码示例二

以下是一个更详细的Java代码示例,它包含了更多的错误处理、日志记录以及FFmpeg进程的异步监控。

(一)代码示例

首先,我们需要引入一些Java标准库中的类,比如
Process
,
BufferedReader
,
InputStreamReader
,
OutputStream
,
Thread
等。此外,为了简化日志记录,我们可以使用Java的
java.util.logging
包。

import java.io.*;
import java.util.logging.*;
import java.util.concurrent.*;
 
public class FFmpegRTSPStreamer {
 
    private static final Logger logger = Logger.getLogger(FFmpegRTSPStreamer.class.getName());
 
    public static void main(String[] args) {
        // RTSP source and destination URLs
        String rtspSourceUrl = "rtsp://your_source_ip:port/path";
        String rtspDestinationUrl = "rtsp://your_destination_ip:port/path";
 
        // FFmpeg command to pull RTSP stream and push to another RTSP server
        // Note: Make sure ffmpeg is in your system's PATH or provide the full path to ffmpeg
        String ffmpegCommand = String.format(
                "ffmpeg -re -i %s -c copy -f rtsp %s",
                rtspSourceUrl, rtspDestinationUrl
        );
 
        // Use a thread pool to manage the FFmpeg process
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<?> future = executorService.submit(() -> {
            try {
                ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", ffmpegCommand);
                processBuilder.redirectErrorStream(true);
 
                Process process = processBuilder.start();
 
                // Read FFmpeg's output asynchronously
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    logger.info(line);
                }
 
                // Wait for the process to complete
                int exitCode = process.waitFor();
                logger.info("FFmpeg process exited with code: " + exitCode);
 
            } catch (IOException | InterruptedException e) {
                logger.log(Level.SEVERE, "Error running FFmpeg process", e);
            }
        });
 
        // Optionally, add a timeout to the FFmpeg process
        // This will allow the program to terminate the FFmpeg process if it runs for too long
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.schedule(() -> {
            if (!future.isDone()) {
                logger.warning("FFmpeg process timed out and will be terminated");
                future.cancel(true); // This will interrupt the thread running FFmpeg
                // Note: This won't actually kill the FFmpeg process, just the Java thread monitoring it.
                // To kill the FFmpeg process, you would need to find its PID and use `Process.destroy()` or an OS-specific command.
            }
        }, 60, TimeUnit.MINUTES); // Set the timeout duration as needed
 
        // Note: The above timeout mechanism is not perfect because `future.cancel(true)` only interrupts the Java thread.
        // To properly handle timeouts and killing the FFmpeg process, you would need to use a different approach,
        // such as running FFmpeg in a separate process group and sending a signal to that group.
 
        // In a real application, you would want to handle the shutdown of these ExecutorServices gracefully,
        // for example, by adding shutdown hooks or providing a way to stop the streaming via user input.
 
        // For simplicity, this example does not include such handling.
    }
}

(二)注意事项

  1. 日志记录
    :我使用了
    java.util.logging.Logger
    来记录日志。这允许您更好地监控FFmpeg进程的输出和任何潜在的错误。
  2. 线程池
    :我使用了一个单线程的
    ExecutorService
    来运行FFmpeg进程。这允许您更轻松地管理进程的生命周期,并可以在需要时取消它(尽管上面的取消机制并不完美,因为它只是中断了监控FFmpeg的Java线程)。
  3. 异步输出读取
    :FFmpeg的输出是异步读取的,这意味着Java程序不会阻塞等待FFmpeg完成,而是会继续执行并在后台处理FFmpeg的输出。
  4. 超时处理
    :我添加了一个可选的超时机制,但请注意,这个机制并不完美。它只会中断监控FFmpeg的Java线程,而不会实际杀死FFmpeg进程。要正确实现超时和杀死FFmpeg进程,您需要使用特定于操作系统的命令或信号。
  5. 清理
    :在上面的示例中,我没有包含
    ExecutorService

    ScheduledExecutorService
    的清理代码。在实际的应用程序中,您应该确保在不再需要时正确关闭这些服务。
  6. 路径问题
    :确保FFmpeg命令可以在您的系统路径中找到,或者提供FFmpeg的完整路径。
  7. 错误处理
    :示例中的错误处理相对简单。在实际应用中,您可能需要添加更详细的错误处理逻辑,比如重试机制、更详细的日志记录等。
  8. 性能
    :直接在Java中调用FFmpeg命令可能会受到Java进程和FFmpeg进程之间通信效率的限制。对于高性能需求,可能需要考虑使用JNI或其他更底层的集成方法。但是,对于大多数用例来说,上面的方法应该足够高效。

前一篇:《人工智能模型学习到的知识是怎样的一种存在?》

序言:
在人工智能领域,卷积神经网络(CNN)备受瞩目,但神经网络的种类远不止于此。实际上,不同类型的神经网络各有其独特的应用场景。在接下来的几节中,我将带大家走近循环神经网络(RNN),深入了解其原理及其在处理人类自然语言中的改进与应用。

需要注意的是,目前自然语言处理领域主流的技术框架是基于 Transformer 架构的模型(如ChatGPT)。Transformer 克服了 RNN 在长序列上下文捕捉中的局限性,并以更高的训练效率和性能成为行业标准。我们在前面已经详细介绍过 Transformer 的相关内容。

本节对 RNN 的介绍,旨在帮助大家理解人工智能技术在序列建模领域的历史演进,以及它是如何一步步发展到今天的状态的。

在前面的几章节中,我们了解了如何对文本进行分词和序列化,将句子转换为数字张量,然后将其输入神经网络。接着,在上一章节中,我们进一步学习了嵌入方法,这是一种让具有相似意义的单词聚集在一起以便于计算情感的方式。这种方法效果非常好,正如你在构建讽刺分类器时所看到的那样。然而,这种方法也有一个局限性,那就是句子并不仅仅是单词的集合——通常,单词出现的顺序会决定句子的整体意义。形容词可以增强或改变它们所修饰名词的意义。例如,“蓝色”(blue)这个词从情感角度可能毫无意义,“天空”(sky)这个词亦然,但当你把它们组合成“蓝天”(blue sky)时,就传达出了一种通常是积极的情感。而有些名词也可能限定其他名词,比如“雨云”(rain cloud)、“书桌”(writing desk)、“咖啡杯”(coffee mug)。

为了考虑到像这样的序列信息,我们需要一种额外的方法,那就是将循环性融入到模型架构中。在接下来的几节中,我们将了解实现这一点的不同方法。我们将探讨如何学习序列信息,以及如何利用这些信息来构建一种更能理解文本的模型:循环神经网络(RNN)。

循环的基础

为了理解循环是如何工作的,首先让我们回顾一下本书迄今为止所使用模型的局限性。本质上,创建模型的过程有点像图 7-1 所示。你提供数据和标签,定义一个模型架构,模型学习将数据与标签匹配的规则。这些规则随后变成了一个 API,能够为未来的数据返回预测标签。


图 7-1. 模型创建的高层视图

不过,你可以看到,数据是被整体塞进去的。没有涉及到任何细节,也没有努力去理解数据出现的顺序。这意味着,像“blue”(蓝色)和“sky”(天空)这样的词,在“今天我很沮丧,因为天空是灰色的”(today I am blue, because the sky is gray)和“今天我很开心,有美丽的蓝天”(today I am happy, and there’s a beautiful blue sky)这样的句子中,它们的意义没有任何区别。对于我们来说,这些词的用法区别是显而易见的,但对于一个像这里所示架构的模型来说,真的没有区别。

那么我们该怎么解决这个问题呢?首先,让我们探讨一下循环的本质,从这里你就能了解基本的 RNN 是如何工作的。

考虑一下著名的斐波那契数列。如果你不熟悉它,我在图 7-2中列出了一些数字。


图 7-2. 斐波那契数列的前几个数字

这个数列的理念是,每个数字都是它前面两个数字的和。所以如果我们从 1 和 2 开始,下一个数字就是 1 + 2,等于 3。再下一个是 2 + 3,等于 5,然后是 3 + 5,等于 8,以此类推。

我们可以把这个过程放到一个计算图中,得到图 7-3。


图 7-3. 斐波那契数列的计算图表示

在这里你可以看到,我们将 1 和 2 输入到函数中,得到输出 3。我们把第二个参数(2)带到下一步,并与前一步的输出(3)一起输入函数。这次的输出是 5,然后它与前一步的第二个参数(3)一起输入函数,产生输出 8。这个过程无限继续,每一步的操作都依赖于之前的结果。左上角的 1 可以说是“存活”在整个过程中。它是被输入到第二次运算的 3 的一部分,也是被输入到第三次运算的 5 的一部分,等等。因此,1 的某种本质贯穿于整个序列,虽然它对整体数值的影响逐渐减小。

这类似于循环神经元的架构。你可以在图 7-4中看到循环神经元的典型表示。


图 7-4. 一个循环神经元

在一个时间步长中,一个值 x 被输入到函数 F,因此通常标记为 xt。这会在该时间步产生一个输出 y,通常标记为 yt。它还产生一个值,被前馈到下一步,这由从 F 指向它自己的箭头表示。

如果你看看循环神经元在不同时间步中如何彼此协作,这会更清晰一些,你可以在图 7-5中看到。


图 7-5. 时间步中的循环神经元

在这里,x₀ 被操作得到 y₀ 和一个传递到下一步的值。下一步获取那个值和 x₁,产生 y₁ 和一个传递到下一步的值。再下一步获取那个值和 x₂,产生 y₂ 和一个传递到下一步的值,就这样一直下去。这和我们在斐波那契数列中看到的类似,我总觉得这是记住 RNN 工作原理的一个好记忆方法。

将循环扩展到语言

在上一节中,你看到了一个在多个时间步上运行的循环神经网络如何帮助在序列中保持上下文。实际上,RNN 将在本书后面用于序列建模。但是,当涉及到语言时,使用像图 7-4 和图 7-5 中那样的简单 RNN,可能会错过一些细微之处。就像之前提到的斐波那契数列例子,被传递的上下文量会随着时间的推移而减小。第 1 步神经元的输出在第 2 步的影响很大,在第 3 步更小,在第 4 步更小,依此类推。

所以,如果我们有一句像“今天有一片美丽的蓝色<…>”这样的句子,“蓝色”这个词对下一个词有很大的影响;我们可以猜测它很可能是“天空”。但是,如果上下文来自句子更前面的地方呢?例如,考虑这句话:“我住在爱尔兰,所以在高中我不得不学习如何说和写<…>。”

那个 <…> 是盖尔语,但真正给我们上下文的词是“爱尔兰”,它在句子中更靠前的位置。因此,为了能够识别 <…> 应该是什么,我们需要一种方法来在更长的距离上保持上下文。RNN 的短期记忆需要变得更长,为此,发明了一种对架构的增强,称为长短期记忆(LSTM)。

虽然我不会详细介绍 LSTM 的底层架构是如何工作的,但如图 7-6 所示的高层图解传达了主要观点。要了解更多关于内部操作的内容,可以查看 Christopher Olah 关于该主题的优秀博文。

LSTM 架构通过添加一个“细胞状态”来增强基本的 RNN,这使得上下文不仅可以从一步到下一步保持,还可以在整个步骤序列中保持。记住这些是神经元,以神经元的方式学习,你可以看到这确保了重要的上下文会随着时间被学习。


图 7-6. LSTM 架构的高级视图

LSTM 的一个重要部分是它可以是双向的——时间步既向前又向后迭代,因此可以在两个方向上学习上下文。请参见图 7-7 获取其高级视图。


图 7-7. LSTM 双向架构的高级视图

这样,既进行了从 0 到 number_of_steps 的评估,也进行了从 number_of_steps 到 0 的评估。在每个步骤中,y 的结果是“前向”传递和“后向”传递的聚合。你可以在图 7-8 中看到这一点。


图 7-8. 双向 LSTM

将每个时间步的每个神经元视为 F₀、F₁、F₂ 等。时间步的方向已显示,所以在前向方向上对 F₁ 的计算是 F₁(→),在反向方向上是 (←)F₁。这些值被聚合以给出该时间步的 y 值。此外,细胞状态也是双向的。这对于管理句子中的上下文非常有用。再次考虑这句话:“我住在爱尔兰,所以在高中我不得不学习如何说和写<某物>”,你可以看到 <某物> 被“爱尔兰”这个上下文词限定了。但如果反过来呢:“我住在<这个国家>,所以在高中我不得不学习如何说和写盖尔语”?你可以看到,通过逆向遍历句子,我们可以了解 <这个国家> 应该是什么。因此,使用双向 LSTM 对于理解文本中的情感非常强大(正如你将在第 8 章中看到的,它们对于生成文本也非常强大!)。

当然,LSTM,特别是双向的,有很多复杂的过程,所以训练会很慢。这时候,值得投资一个 GPU,或者至少在可能的情况下使用 Google Colab 的托管 GPU。

总结:
本节我们介绍了循环神经网络(RNN),并探讨了如何通过改进使其更好地应用于人类语言处理。下一节中,我们将深入讨论 RNN 在自然语言处理中的具体应用及实现方法。

前一章我们介绍了基于模型自我合成数据迭代,来提升LLM生成更合理的自我推理思考链路。但在模型持续提升的道路上,只提升Generator能力是不够的,需要同步提升Supervisor、Verifier的能力,才能提供有效的监督优化信号。

人类提供的监督信号有几类,包括人工直接生成最优回答(Demonstration), 人工提供偏好对比(Preference),人工给出优化建议(Critique)等几种,论文中曾提及以上几类信号的难易程度

The Evaluation of AI output is typically faster and easier for humans than the demonstration of ideal output

所以RLHF阶段的引入,除了降低模型模仿,提升泛化,增加更高水平的对齐,其实也有一部分原因是人类生成golden answer的上限是比较低的,毕竟不能雇佣一堆各领域专家来给你生成最优回答,所以训练也就从人类标注转移到了人类评估。

而现在当大模型能力提升到一定水平后,不仅是Demonstration,连Prefernce和Critique也会遇到瓶颈。当前阻碍模型智能进一步提升的一个核心问题就是评估水平的上限,而这时就需要模型评估的辅助,尤其是生成式评估能力的加持,下面我们看两篇OpenAI在生成式评估上的论文。

22年:Self-critiquing models for assisting human evaluators

比较早的这篇论文我们主要看下结论,毕竟模型更大更强了,训练范式也在这两年发生了转变。论文的核心就是
机器辅助人类进行标注
。可能早在22年之前,OpenAI就已经到了大模型在复杂问题上输出结果接近人类标注员的水平,所以才早早开始研究这个方向。

这里标注的任务已经脱离了早期descriminative的NLP任务,例如多项选择,分类等判断模型,而是已经聚焦在了对生成式模型的输出进行广泛评估。并且
机器辅助
也并非简单的
对/错
的分类判别,而是
分类判别(critiqueable)、生成式评估(critique)、基于评估的条件优化(refinement)的结合体
,如下

image

论文评估用模型辅助人类标注,得到了以下结论

  • 生成式评估可以帮助标注员发现更多模型回答问题(人机协同,相比各自单打独斗能发现更多模型回答的问题)

image

  • 随着模型规模提升,模型的回答会更难被发现问题(critiqueability),但同时模型自我评估的能力也会随之提升(fraction helpful)

image

  • 足够大的模型可以通过自己评估自己的回答,来优化答案生成,通过拒绝采样得到更准确的critique,可以进一步提升效果

image

24年: LLM Critics Help Catch LLM Bugs

如果说22年初的论文还只是针对在部分人类难以评估的领域,例如生成式摘要上,使用人机协同评估带来的增益。24年的这篇论文就更广泛地讨论
Scalable Oversight
问题。这是Anthropic也在22年提出的概念,就是当模型能力在多数任务上超越人类时,人类该如何继续为模型提供有效的对齐信号,如下图

image

论文给出方案就是训练CriticGPT,使用模型生成式评估来辅助人类标注员。并同时给出了在推理时可以平衡问题发现的准召比例的推理方案Force Sampling Beam Search。论文评估在CriticGPT模型的帮助下,人工标注的效果会有显著的提升。下面我们分别讲下训练和推理部分。

image

数据和训练

论文选择了Coding,这个任务复杂度上限很高,相对容易验证且客观的任务场景。训练的核心在于代码标注RLHF数据集的构建,包括偏好标注标准和数据集组成。什么样的模型标注是好标注?什么样的模型代码样本能让偏好标注的一致性更高,同时数据集足够全面?

先说数据标注标准,论文综合召回和准确给出了4条衡量模型标注优劣的标准

  • 召回率:模型的标注评论是否发现了回答中的所有Bug
  • 核心召回率(CBI):模型的标注评论是否发现了回答中的核心Bug
  • 准确率:模型的标注评论是无中生有,或者鸡蛋里挑骨头
  • 综合召回+准确:模型标注评论整体的有用性

人工标注员除了需要对每条模型评论针对以上标准进行打分外,还需要对4条模型标注的整体效果进行对比,最终是使用对比结果来作为RLHF的训练标签,考虑在标注时绝对打分的一致性要远远低于相对打分的一致性。

再说数据构成,整个RLHF的数据集包含两个部分

  • 人工在模型回答中注入Bug,再让模型进行评论
  • 模型回答自带Bug
    image

人工数据部分就是论文的一个亮点,上图就是人工数据构建的过程,既人工在模型回答中加入Bug(Tampering),给出注入Bug的相关解释。之后模型需要在人工修改过的答案上进行标注评论,同时标注员也会依赖Bug说明,来衡量模型生成的多条标注的效果。

这类构造数据在RLHF数据集中占比更高,原因在于相比自带Bug的天然数据,这类加工数据,不仅Bug更加复杂,同时因为自带golden answer,所以在人工标注阶段能得到更一致,准确率更高的标注结果,在偏好数据的标注过程中,审核一致性是非常重要的。同时在收集数据过程中,论文还使用了多个版本,多个大小的模型,来丰富整个RLHF数据集的分布覆盖度。两类数据的占比分布如下

image

偏好数据收集完,后面就是比较常规的训练Reward模型,再基于reward模型,使用PPO训练CriticGPT。

推理和效果

推理时,论文采用了Reward模型和推理搜索结合的方式,目标是提高模型标注的长度,并降低回答幻觉。其实也很简单就是在单纯reward 打分的基础上,加了一个模型引用源代码段落数的得分。

模型标注的推理格式是引用一段源代码,再分析一下这段代码的问题,所以在打分中加入代码数可以鼓励模型推理对更多的源代码片段进行分析,从而发现更多的Bug,而reward打分则用于控制幻觉,这样既保质也保量。

效果上,有模型标注协同,人工标注可以显著发现更多的bug,并且相比单纯使用criticGPT进行机器标注,会有显著更低的幻觉比例。整体上criticGPT配合人工标注是更加balance的模型标注方案。

image

image

想看更全的大模型论文·微调预训练数据·开源框架·AIGC应用 >>
DecryPrompt

Redis为什么这么快?

  1. 完全基于内存,数据存在内存中,绝大部分请求是纯粹的内存操作,非常快速,跟传统的磁盘文件数据存储相比,避免了通过磁盘IO读取到内存这部分的开销。
  2. 数据结构简单,对数据操作也简单。【Redis中的数据结构】是专门进行设计的,每种数据结构都有一种或多种数据结构来支持。Redis正是依赖这些灵活的数据结构,来提升读取和写入的性能。
  3. 采用单线程,省去了很多上下文切换的时间以及CPU消耗,不存在竞争条件,不用去考虑各种锁的问题,不存在加锁释放锁操作,也不会出现死锁而导致的性能消耗。
  4. Redis直接自己构建了VM 机制 ,避免调用系统函数的时候,浪费时间去移动和请求
  5. Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,【IO 多路复用机制】是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。

Redis 基于 Reactor 模式开发了自己的网络事件处理器,这个处理器被称为文件事件处理器 file event handler。由于这个文件事件处理器是单线程的,所以Redis才叫做单线程的模型,但是它采用IO多路复用机制同时监听多个Socket,并根据Socket上的事件来选择对应的事件处理器进行处理。文件事件处理器的结构包含4个部分,线程模型如下图:

多个 Socket 可能会产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个Socket,将Socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个过程。其中执行命令阶段,
由于Redis是单线程来处理命令的,所有每一条到达服务端的命令不会立刻执行,所有的命令都会进入一个队列中,然后逐个被执行
。并且多个客户端发送的命令的执行顺序是不确定的。但是可以确定的是
不会有两条命令被同时执行,不会产生并发问题
,这就是Redis的单线程基本模型。

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,然后程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个客户端的网络IO连接请求(尽量减少网络 IO 的时间消耗)

为什么Redis是单线程?

这里我们强调的单线程,指的是网络请求模块使用一个线程来处理,即一个线程处理所有网络请求,其他模块仍用了多个线程。

那为什么使用单线程呢?官方答案是:因为CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

但是,我们使用单线程的方式是无法发挥多核CPU 性能,不过我们可以通过在单机开多个Redis 实例来解决这个问题

Redis6.0 的多线程

1、Redis6.0 之前为什么一直不使用多线程?

Redis使用单线程的可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。

2、Redis6.0 为什么要引入多线程呢?

因为Redis的瓶颈不在内存,而是在网络I/O模块带来CPU的耗时,所以Redis6.0的多线程是用来处理网络I/O这部分,充分利用CPU资源,减少网络I/O阻塞带来的性能损耗。

多线程模式下,是否存在线程并发安全问题?

如图,一次redis请求,要建立连接,然后获取操作的命令,然后执行命令,最后将响应的结果写到socket上。

在redis的多线程模式下,获取、解析命令,以及输出结果着两个过程,可以配置成多线程执行的,因为它毕竟是我们定位到的主要耗时点,但是命令的执行,也就是内存操作,依然是单线程运行的。所以,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行,也就
不存在并发安全
问题。

面试题专栏

Java面试题专栏
已上线,欢迎访问。

  • 如果你不知道简历怎么写,简历项目不知道怎么包装;
  • 如果简历中有些内容你不知道该不该写上去;
  • 如果有些综合性问题你不知道怎么答;

那么可以私信我,我会尽我所能帮助你。

liwen01 2024.11.17

前言

计算机网络在给人们带来便利的同时,也引入了安全风险,对于无线WiFi网络而言,风险更高。无线 WiFi 网络安全主要包括两大部分:
接入认证

数据加密

虽然现在网络安全事件远少于网络诈骗,网络认证与数据加密的方法及原理仍值得学习和借鉴。

(一) WiFi 安全威胁

我们看上面这个简单的网络结构图,一个路由器上连接着4台电脑、一台服务器,一台手机。

如果路由器的热点是开放未加密的,那连接到路由器上的所有设备的网络都会是不安全的。

(1) 数据安全

笔记本1、笔记本2、手机都是通过 WiFi 连接到路由器上,通过无线电波以空口包的形式进行数据交互。

如果非法攻击者位于路由器比较近的距离,它是可以直接使用空口包抓包工具将网络包抓取出来。然后对数据进行解密、分析,他就能找到他想要的数据信息。

数据的加密方式,决定了攻击者对数据解密的难易程度。WiFi中常用的加密方式有:
RC4、TKIP、AES、CCMP、GCMP

(2) 认证安全

最上面图中,路由器的有线与无线网络处于同一网段,如果非法攻击者连接上了路由器,它不但可以攻击无线设备,还能攻击处于同一个网络中的有线设备(台式电脑、服务器等)。

要解决链路安全问题,需要在连接无线网络时进行设备认证。

  • 适用于个人和家庭版本的是:
    WEP、WPA-PSK、WPA2-PSK、WPA3-PSK
  • 适用于企业的是:
    WPA-802.1X、WPA2-802.1X、WPA3-802.1X

(3) 非法AP问题

有些非法AP,它将 SSID 设置成与合法 AP 一致,假装成合法的无线网络,诱使用户连接。一旦连接,攻击者可以拦截流量、进行数据窃取或传播恶意软件。

要解决非法 AP 问题,可以在网络中布置 WIDS(Wireless Intrusion Detection System)无线入侵检测系统。

(4) 认证与加密

(二) WEP 认证与加密

WEP (Wired Equivalent Privacy)
有线等效加密是 1997 年批准的原始802.11标准的一部分,可用于802.11a和802.11b设备的加密协议,旨在为 WiFi 提供与有线网络类似的安全性。

尽管 WEP 现在已经过时且存在多个安全漏洞,但其认证过程仍然值得学习,因为它是无线网络安全历史上的重要一步。

WEP 认证过程中主要有两种模式:
开放系统认证

共享密钥认证

(1) 开放系统认证(Open System Authentication)

这是 WEP 最简单的一种认证方式,实际上它并不涉及加密认证。在开放系统认证中,任何客户端都可以请求连接接入点 (AP),无论客户端是否知道 WEP 密钥。

尽管它被称为
认证
,但实际上它几乎没有安全性。

开放系统认证的步骤:

  1. 请求认证
    :客户端向 AP 发送一个认证请求帧。这一帧只是表明客户端希望加入网络,不包含任何加密信息。
  2. 认证回应
    :AP 接收到请求后,通常会直接回应一个认证应答帧,表示认证成功。由于开放系统认证并不涉及身份验证,即使客户端不知道正确的 WEP 密钥,AP 也会允许它进入网络。
  3. 发送关联请求
    :认证完成后,客户端发送关联请求,表明它想加入网络。
  4. AP回应关联请求
    :AP 会回应一个关联应答,表示客户端已成功加入网络。

(2) 共享密钥认证(Shared Key Authentication)

共享密钥认证使用 WEP 密钥进行身份验证,确保只有知道正确 WEP 密钥的客户端可以通过认证。

共享密钥认证的步骤:

  1. 请求认证
    :客户端发送一个认证请求帧,表明它希望通过共享密钥认证加入网络。请求帧中包含客户端的 MAC 地址等信息,但不包含任何加密数据。
  2. 挑战帧(Challenge Frame):AP 接收到请求后,会生成一个随机数,称为挑战文本
    (Challenge Text)。AP 将挑战文本以
    明文
    的形式发送给客户端,同时要求客户端使用 WEP 密钥对该挑战文本加密后再返回。
  3. 加密挑战并响应
    :客户端使用其本地配置的 WEP 密钥对挑战文本进行 RC4 加密,然后将加密后的数据返回给 AP。
  4. AP验证
    :AP 接收到加密后的挑战响应后,使用相同的 WEP 密钥对挑战文本加密,并将结果与客户端的响应进行对比。如果两者匹配,则说明客户端知道正确的 WEP 密钥,认证成功。否则,认证失败。
  5. 关联过程
    :如果认证成功,客户端会发送关联请求帧,AP 则回复关联应答帧,表明客户端成功加入网络。

共享密钥认证的特点:

  • 加密认证
    :使用 WEP 密钥对挑战文本加密,表面上看起来比开放系统认证安全得多。
  • 漏洞
    :共享密钥认证本身存在严重的设计缺陷。由于挑战文本是明文发送的,而加密后的响应可被拦截,这意味着攻击者可以通过分析多个认证过程,逆向推算出 WEP 密钥。这种攻击被称为
    加密文本选择攻击

(3) WEP工作原理与加密过程

1.数据载荷和 CRC 生成(无线设备)

  • 数据载荷
    (Payload)是准备要传输的数据。
  • 计算数据载荷的 CRC(循环冗余校验)。CRC 用于确保数据的完整性,接收端可以通过 CRC 验证数据在传输过程中没有被篡改。
  • 数据载荷 + CRC
    被组合成一个数据包,它作为加密过程中的明文输入。

2. IV(初始化向量)和共享密钥

  • 通过 IV 生成算法生成一个 初始化向量(IV)。IV 是一个 24 位的值,用于确保即使重用相同的共享密钥,不同数据包的加密结果也会不同。
  • 这个 IV 和共享密钥的组合作为
    RC4 算法
    的输入。

3.RC4 加密

  • RC4 算法
    使用连接后的 IV 和共享密钥生成
    密钥流
  • 生成的密钥流与
    明文输入
    (数据载荷 + CRC)进行 异或运算(XOR),生成
    密文
  • IV 作为数据包的一部分与密文一起传输,因为接收端需要它来解密数据。

4.接收端(AP)

  • 接入点(AP)接收到包含
    IV

    密文
    的数据包。
  • AP 将接收到的 IV 与
    共享密钥
    (与设备预先共享)连接,并输入
    RC4 算法
    以生成与加密时相同的
    密钥流
  • AP 将
    密文
    与生成的密钥流进行异或运算,得到原始的
    明文输出
    (数据载荷 + CRC)。
  • 最后,AP 使用
    CRC
    验证数据的完整性,并提取
    数据载荷
    以供进一步处理。

关键点介绍:

  • RC4 流密码
    :该算法生成一个密钥流,与数据进行异或运算以生成密文。同样的密钥流用于解密数据。
  • IV
    :一个 24 位的值,用于防止在不同的数据包中重复使用相同的密钥流。
  • 共享密钥
    :设备与 AP 预先共享的密钥,是 RC4 加密的基础。
  • 数据载荷保护
    :CRC 用于确保数据完整性,而密钥流通过加密确保数据的机密性。

(4) WEP 加密的缺陷

  • IV 碰撞
    :IV 长度仅为 24 位,容易导致 IV 重复使用,使得 WEP 易受到分析攻击。
  • RC4 的弱点
    :RC4 自身存在已知的漏洞,因此与现代加密标准如 WPA 和 WPA2 相比,WEP 的安全性较低。

(三) WPA1/WPA2 的 PSK 认证

WEP 协议是最早的无线网络加密标准,但其设计存在严重缺陷,如容易被攻击者通过捕获足够多的数据包进行密钥还原。

因此,WiFi 联盟开发了 WPA(WPA1) 标准,作为 WEP 的过渡性替代方案,其中引入了 TKIP 来提高数据传输的安全性,同时也引入了PSK 认证方法。

Pre-Shared Key (PSK)
认证方法常用在
WPA-Personal

WPA2-Personal
模式下,它不需要企业级的认证服务器(如RADIUS),而是依赖于所有用户共享的同一个密码来进行认证。也就是我们现在连接家用路由器的方式。

(2) PSK 认证的整体流程

  1. 预共享密钥配置
    :网络管理员在无线接入点(AP)上配置一个密码(即预共享密钥,PSK)。连接到此网络的设备也需要输入相同的密码。
  2. 连接请求
    :当客户端设备(如手机或笔记本电脑)尝试连接到 WiFi 网络时,首先输入预共享密钥(即WiFi密码),然后发起连接请求。
  3. PSK 验证
    :无线接入点接收到客户端的连接请求后,会检查客户端提供的 PSK 是否与其自身配置的 PSK 相匹配。如果 PSK 匹配,认证通过;如果 PSK 不匹配,则连接被拒绝。
  4. 四次握手协议
    (Four-Way Handshake):为了防止 PSK 匹配时数据被窃听,双方需要通过握手协议生成独立的加密密钥(即
    会话密钥
    ),用于加密无线数据传输。

四次握手过程:

  1. 第一步
    :AP 生成一个随机数,称为
    AP Nonce
    (ANonce),并将其发送给客户端。这个随机数是用于生成最终加密密钥的关键材料之一。
  2. 第二步
    :客户端收到 ANonce 后,结合预共享密钥(PSK)和客户端自身生成的随机数
    SNonce
    来计算出
    PTK
    (Pairwise Transient Key,成对瞬时密钥),这个密钥用于加密客户端和 AP 之间的通信。客户端随后将它的
    SNonce
    发送给 AP。
  3. 第三步
    :AP 收到 SNonce 后,使用 AP 的 ANonce、客户端的 SNonce、双方的 MAC 地址,以及 PSK,生成与客户端相同的 PTK。同时,AP 还生成一个 GTK(Group Temporal Key,组临时密钥),用于加密网络中的广播和组播通信。AP 接着将加密后的 GTK 和消息完整性代码(
    MIC
    )发送给客户端,以确认握手数据的完整性。
  4. 第四步
    :客户端收到加密的 GTK 和 MIC 后,使用之前生成的 PTK 进行解密和验证。如果验证通过,客户端会向 AP 发送一个确认消息,表示握手成功。此时,客户端和 AP 都拥有相同的 PTK 和 GTK,从而可以开始加密的通信

通过这个握手过程,客户端和AP最终拥有了相同的
会话密钥
(Session Key),而 PSK 只是参与了会话密钥的生成,并不会直接用于加密传输数据。

PSK 认证的关键元素:

  1. 预共享密钥
    (PSK):由网络管理员设置的一个密码,必须在所有设备和AP上配置相同的 PSK。它参与了会话密钥的生成,但不会用于直接加密数据。
  2. 四次握手协议
    :在验证 PSK 之后,客户端和 AP 通过四次握手协商出一个新的
    临时密钥
    (TK),即会话密钥,用来加密和保护无线通信数据。
  3. 会话密钥
    (Session Key / PTK):握手协议生成的动态密钥,它是基于 PSK、AP 和客户端的 MAC 地址、以及生成的随机数计算而得的。这使得即便PSK相同,客户端和AP之间的通信也是独一无二的。
  4. Group Temporal Key
    (GTK):用于加密在网络中所有设备之间的广播和组播消息。GTK 由 AP 生成并发送给每个已认证的客户端。

(4) PSK 认证的优点

  • 简便易用
    :PSK模式不需要复杂的基础设施(如认证服务器),只需在接入点和客户端之间共享密码,因此特别适合家庭和小型网络。
  • 灵活性
    :任何拥有正确PSK的设备都可以连接到WiFi网络,适合需要简单设置的场景。
  • 加密数据传输
    :在 PSK 验证通过后,四次握手协议生成的会话密钥(Session Key)确保每个数据包的加密是独一无二的,这有效地防止了窃听和篡改。

(5) PSK 认证的隐患

尽管 PSK 是一种简单且有效的认证方式,但它也存在一定的安全隐患:

  1. 密码强度
    :如果 PSK 密码过于简单或常见,攻击者可以通过暴力破解或字典攻击来猜测密码。一旦PSK被破解,攻击者可以完全访问网络。
  2. 密钥共享风险
    :所有用户共享相同的 PSK,这意味着如果 PSK 被泄露,网络的所有安全性都将被破坏。
  3. 设备移除的复杂性
    :在 PSK 模式下,无法轻易从网络中移除单个设备。要取消某个设备的访问权限,必须更改网络密码,并在所有其他合法设备上重新输入新的密码。

(四) WAP 的 TKIP 加密

TKIP(Temporal Key Integrity Protocol) 是为了解决 WEP 中的静态密钥和容易被破解的问题而设计的,它主要的目标是
在不更改硬件的情况下,提高现有设备的安全性

(1) TKIP的主要功能与特性

TKIP 的工作原理与 WEP 类似,但它通过增强的密钥管理和数据包完整性检查来解决 WEP 的安全漏洞。其工作流程大致如下:

  1. 初始化
    :TKIP 在开始时使用共享密钥和初始化向量(IV)来生成初始密钥。
  2. 密钥混合
    :TKIP通过混合函数将共享密钥、IV以及数据包的序列号等信息组合在一起,生成一个唯一的加密密钥,用于该数据包的加密。
  3. 加密数据包
    :数据包在传输之前使用RC4流加密算法加密,加密的密钥是动态生成的每个数据包的唯一密钥。
  4. MIC校验
    :加密前,TKIP还会计算消息完整性校验(MIC)值并附加在数据包中,确保数据包未被篡改。
  5. 重放保护
    :接收方通过检查数据包的序列号来防止重放攻击。

(2) TKIP 的局限性

虽然 TKIP 在设计上比 WEP 更安全,但它并不是完美的,主要局限性包括:

  • 计算性能较低
    :TKIP为了兼容现有的硬件设备,其设计不得不做出一些妥协,这导致其在处理加密时效率较低。尤其是在较高带宽的网络环境下,性能问题尤为明显。
  • 安全性已过时
    :随着计算能力的提升,TKIP本身也逐渐被证明不再足够安全。例如,Michael算法中的某些弱点已经被发现并利用。因此,WiFi联盟已经建议在WPA2标准中弃用TKIP,改用更安全的AES(高级加密标准)。
  • 不支持现代的WiFi标准
    :随着WiFi标准的进步(如WPA2、WPA3),TKIP不再能满足现代无线通信的安全需求,这使得它在新标准中被逐步淘汰

TKIP 作为 WEP 到 WPA 过渡期间的一项重要技术,为提升无线网络安全性做出了贡献。随着时间的推移和计算能力的提升,TKIP 逐渐暴露出其安全性和性能上的局限性。在 802.11 标准的 2012 年修订版中已被弃用。

(五) WAP2 的 AES 加密

AES(Advanced Encryption Standard)
被引入是为了替代
WEP(Wired Equivalent Privacy)

WPA(Wi-Fi Protected Access)
初始版本中的 RC4 加密算法,它在WPA2中被广泛使用。

(1) AES 的优点

AES 是一种分组加密算法,它具备下面特点:

  • 安全性强
    :AES 是一种对称加密算法,通常支持 128 位、192 位和 256 位密钥,且已被全球安全专家评估为高效且难以破解的算法。
  • 效率高
    :AES 采用 Rijndael 算法,不仅安全性高,而且在硬件加速和计算效率上表现优异,适用于无线网络环境。
  • 受支持广泛
    :AES 是美国政府采纳的加密标准,广泛用于商业和政府机构,适用于几乎所有现代设备。

(2) AES 在的应用

AES 主要用于 Counter Mode with Cipher Block Chaining Message Authentication Code Protocol (CCMP) 模式,即
计数器模式+密码块链接消息验证码协议
。这种模式提供数据加密和完整性验证。

  • 计数器模式
    (Counter Mode):通过一个唯一的计数器(nonce)将每个数据包的内容进行加密,从而确保数据的唯一性和机密性。
  • 消息验证码协议
    (MAC):使用 Cipher Block Chaining Message Authentication Code (CBC-MAC) 来确保数据的完整性,防止数据篡改。

(3) AES-CCMP 的工作流程

  • 密钥生成
    :用户设置的预共享密钥(PSK)经过一系列运算生成 Pairwise Transient Key (PTK) 和 Group Transient Key (GTK),用于加密各自的数据包。
  • 计数器加密
    :每次发送的数据包会携带一个新的计数器值 (nonce),AES 使用该计数器加密分组数据块,通过分组加密生成伪随机流,最终与明文数据按位异或得到密文。
  • 完整性检查
    :AES-CCMP 在发送数据前会使用 CBC-MAC 生成一个消息认证代码(MIC),并将其附加到数据包尾部,接收端再进行 MIC 计算并对比,以确保数据的完整性。

(4) AES-CCMP 的缺点

  • 高计算资源需求
    :AES 计算复杂度较高,对低性能设备或电池供电设备有一定的能耗影响。
  • 兼容性
    :部分早期设备不支持 AES,可能需更换设备才能使用 WPA2。

(六) WAP3 的 SAE 认证

2018年推出的
Wi-Fi Protected Access 3
(WPA3) 引入了一种新的认证协议SAE (Simultaneous Authentication of Equals),用于替代 WPA2 中的 Pre-Shared Key (PSK) 机制。

SAE 被称为
同时认证的对等方
,在 WPA3 中提供更强的安全性,尤其是抵御离线字典攻击。

(1) SAE 认证的工作原理

SAE 是基于密码学的零知识证明协议,具体基于
离散对数难题

椭圆曲线密码学
(ECC),可以在不直接传输密码的情况下验证用户身份。

它是一个抗离线攻击的安全协议,使得攻击者即使截获了 Wi-Fi 握手数据,也无法通过离线尝试密码。

  • Diffie-Hellman 密钥交换
    :SAE 认证使用修改版的 Diffie-Hellman 密钥交换协议,通过每次握手生成一个唯一的会话密钥,即使知道之前的密钥也无法破解新的密钥。
  • 抗离线字典攻击
    :在 SAE 中,即使攻击者获取到 Wi-Fi 握手数据,也无法在离线环境中暴力破解密码,因为 SAE 每次握手生成的密钥是唯一的,且需要在线验证。

(2) SAE 的认证过程

  • Commit Message
    初始化并交换 Diffie-Hellman 公钥,双方开始计算共享密钥。
  • Confirm Message
    验证密钥的一致性并确认对方身份,确保握手安全。
  • Authentication Success
    双方信任彼此生成的共享密钥,认证完成。
  • Association Request/Response
    确认设备加入网络,准备加密通信。

SAE 的认证过程涉及两大主要步骤:密钥
生成

确认

第 1 步:初始化阶段

  • 每个客户端和接入点 (AP) 在认证之前会生成一个唯一的随机数,并将其称为私有密钥。
  • 双方使用 Diffie-Hellman 密钥交换来生成各自的公钥,并通过广播公钥与对方交换。

第 2 步:密钥交换和生成共享密钥

  • 双方各自用自己的私有密钥和接收到的对方公钥计算一个共享密钥。
  • 由于每次握手都会生成不同的随机数,因此即便同样的密码也会产生不同的共享密钥。

第 3 步:零知识证明

  • 零知识证明用于验证用户身份而不直接传输密码。用户需要向 AP 证明自己知道密码,而无需实际泄露密码信息。
  • 通过计算出的共享密钥,双方生成会话密钥,并进行相互认证。
  • 如果认证通过,双方确认共享密钥有效,即认证成功,允许接入网络。

(3) SAE 的安全特性

  • 前向安全性
    (Forward Secrecy):SAE 使用的每次独立密钥生成机制,即使历史会话密钥泄露,也不会影响未来会话的安全性。
  • 零知识证明
    :零知识证明在认证过程中不会传输实际密码或密钥,防止了密码泄露。
  • 抗离线字典攻击
    :攻击者无法通过离线分析握手数据来猜测密码,避免了离线暴力破解。

(4) SAE 与 WPA2-PSK 的差异

  • 安全性更强
    :SAE 相比 WPA2 的 PSK 模式,提供更高的安全性,特别是在抵御离线攻击和暴力破解方面。
  • 握手机制
    :WPA2-PSK 通过静态共享密钥认证,容易遭受重放攻击;SAE 采用动态密钥交换机制,每次认证生成不同密钥。
  • 兼容性
    :SAE 使用了椭圆曲线密码学,这要求设备支持较高的计算能力,部分旧设备可能不支持 WPA3-SAE。

(5) SAE 的局限性

  • 计算资源需求高
    :SAE 的零知识证明和密钥交换算法对设备计算能力有一定要求,可能会影响低功耗设备的使用体验。
  • 不支持 WPA2 设备
    :许多 WPA2 设备不兼容 WPA3 的 SAE 认证机制,因此需要 WPA3 支持设备的环境下才能发挥其全部优势。

(七) WAP3 的 AES-GCMP 加密

在 WPA3 中,为了增强数据传输的安全性,采用了
AES-GCMP
(AES-Galois/Counter Mode Protocol) 加密模式,这种加密模式在 WPA3 的 Enterprise 和 Personal 网络中广泛应用。

AES-GCMP 结合了加密和消息认证功能的算法,确保数据的机密性、完整性和认证。

(1) AES-GCMP 的基本概念

AES-GCMP 是一种基于 AES(Advanced Encryption Standard)的认证加密模式,结合了 Galois/Counter Mode (GCM) 的分组加密和认证功能,用于保护无线网络的数据通信。

AES-GCMP 比 WPA2 中的 AES-CCMP 更安全和高效,支持更高的数据速率和更强的安全性。

  • AES-GCM
    :AES-GCM 是一种分组加密模式,通过计数器模式 (Counter Mode) 实现加密,通过 Galois Message Authentication Code (GMAC) 实现数据的认证。
  • GMAC 认证
    :GMAC 是一种基于 Galois 字段运算的消息认证码,确保数据包在传输过程中没有被篡改。

(2) AES-GCMP 的工作流程

AES-GCMP 结合了加密和认证的流程,其数据处理过程分为以下几步:

  • 计数器模式加密
    :每个数据包会生成一个唯一的计数器 (nonce) 来确保随机性和不可重用性,然后使用 AES 加密每个分组数据块。
  • 数据认证
    :加密后,AES-GCMP 使用 GMAC 生成一个消息认证码 (MAC),用于验证数据的完整性。此 MAC 被附加到数据包的尾部。
  • 数据包发送与验证
    :接收方解密数据包时会验证 GMAC,确保数据包未被篡改。如果验证通过,则解密数据包并还原数据。

(3) AES-GCMP 与 AES-CCMP 的区别

AES-GCMP 与 WPA2 中的 AES-CCMP 有几个重要区别:

  • 性能
    :AES-GCMP 比 AES-CCMP 更快,因为它在认证过程中减少了计算负担,适合更高的吞吐量。
  • 认证方式
    :AES-GCMP 使用 GMAC(而不是 CBC-MAC)来完成认证,效率更高且加密流程更简化。
  • 加密强度
    :AES-GCMP 支持更长的密钥长度,如 256 位,相比 WPA2 中 AES-CCMP 常见的 128 位密钥更安全。

(4) AES-GCMP 的优点

  • 更强的安全性
    :AES-GCMP 支持 256 位密钥,进一步增强了 WPA3 网络的安全性。
  • 抗篡改保护
    :AES-GCMP 的 GMAC 认证模式可以检测数据包中的篡改行为,从而保护数据的完整性。
  • 高效性
    :AES-GCMP 在较高带宽下也能高效运行,因此特别适合于需要较高传输速率和低延迟的网络环境,如 Wi-Fi 6。

(5) AES-GCMP 的局限性

  • 硬件支持
    :AES-GCMP 的加密和认证过程对计算性能要求较高,需要设备硬件支持 AES 硬件加速,才能达到较好的性能。
  • 不向下兼容 WPA2
    :AES-GCMP 仅适用于 WPA3,不向下兼容 WPA2 网络,因此对某些老旧设备不支持。

结尾

上面内容主要介绍了WiFi个人版本中WIFI认证与加密相关的一些知识,日常生活中,比较多的无线设备还是使用WPA2协议,不少厂家也在逐渐更新为WPA3。

日常家庭使用WPA2/3已可以满足需求。对于公司企业,还是使用企业版本认证加密可能会更为稳妥。

------------------End------------------
如需获取更多内容
请关注 liwen01 公众号