密钥派生算法介绍 及 PBKDF2(过时)<Bcrypt(开始淘汰)<Scrypt< Argon2(含Argon2d、Argon2i、Argon2id)简介

密钥派生算法介绍

https://blog.csdn.net/xcxhzjl/article/details/127297263

一、定义

密钥派生函数(Key Derivation Function)就是从一个密码产生出一个或多个密钥,具体就是从一个master key,password或者passphrase派生出一个或多个密钥,派生的过程使用PRF(Pseudo Random Function)。是一种实现key stretching(密钥延长算法,即一种更慢的哈希算法,用于将初始密钥转换成增强密钥,在计算过程中刻意延长时间或者消耗空间,这样有利于保护弱密码)的方法。

●最简单的KDF可以直接使用某种密码学散列算法,如:SHA256。将一个密码转换为一个散列值作为密钥。但易受字典攻击。

二、分类

根据派生源的不同,我们可以将密钥派生算法简单分为两种:

●HKDF(HMAC-based key derivation),基于HMAC的密钥派生算法

使用另一个随机数(salt)作为输入密钥,利用如HMAC-SHA256的HMAC算法对既有密钥派生新的密钥,并将salt与派生密钥一起存储,用于以后再次从这个既有密钥中派生出相同的派生密钥。salt通常不是私密的,并且可以重用。加盐(salt)可以防止彩虹表导致的密码泄露。

●从一个密码派生出一个或多个密钥:PBKDF2、Bcrypt、Scrypt、Argon2 

三、两种密钥派生算法

1、PBKDF2(CPU-Hard algorithm)

是一种基于密钥派生出密钥的算法,需要消耗很多算力,可防止暴力破解加密。

  1. passphrase -> [dklen, salt, c] > 1000] -> hash

  2. DK = PBKDF2(PRF, Password, Salt, c, dkLen)

其中,

passphrase:用于用户认证或者加密程序的操作步骤

dklen:派生所产生的密钥的长度

salt:盐值是一串随机生成的比特

c:迭代的次数

DK:期望的密钥derived key

PRF(Pseudorandom function):伪随机数产生的密钥,如:hmac-sha256

2、Scrypt(Memory-Hard algorithm)

是一种password-base KDF算法,比起PBKDF2需要消耗更多的资源。Scrypt内部用的是PBKDF2算法,不过内部会长时间的维护一组比特数据,这些数据会在生成复杂的salt的过程中反复加密。

3、区别

总结:PBKDF2是算力消耗性的,Scrypt是资源消耗性的。

PBKDF2和Scrypt都是密钥派生函数(KDFs),它们通过故意减慢计算速度来实现密钥延长,特别是通过用一个可调参数来控制速度。不同之处在于,Scryp需要大量且可调整的内存量才能进行高效计算。这样能防止专有硬件ASIC/FPGA的暴力破解。

参考博客(比较深入):

密码学学习笔记_01_密码学综述 - 知乎 (zhihu.com)

创建数字钱包(零)KDF 密钥派生算法 - 腾讯云开发者社区-腾讯云 (tencent.com)

密码学学习笔记_03_随机数与密钥派生 - 知乎 (zhihu.com)

-----------------------------(分割线)--------------------------------

密钥派生函数 Scrypt、Bcrypt 与 Argon2 - 写给开发者的实用密码学

https://zhuanlan.zhihu.com/p/612120129

https://zhuanlan.zhihu.com/p/557583762

以下介绍了三种密钥派生函数( KDF )的特点与使用建议,并给出了 Python 演示代码

相关的原文链接:

Bcrypt - Practical Cryptography for Developers (nakov.com)
Scrypt - Practical Cryptography for Developers (nakov.com)
Argon2 - Practical Cryptography for Developers (nakov.com)

PBKDF2(已经过时)  https://zhuanlan.zhihu.com/p/557583762

PBKDF2是一个简单的从密码派生密钥的KDF,它可以抵抗字典攻击和彩虹表攻击。

PBKDF2的思路是对密码和某些填充做多次迭代的HMAC来派生密钥。PBKDF2算法在RFC 2898 (PKCS #5).标准中有描述。

PBKDF2的算法公式描述如下:

key = pbkdf2(password, salt, iterations-count, hash-function, derived-key-len)
  • password : 密码/口令等
  • salt : 密码学安全伪随机数组
  • iterations-count : 迭代次数,如1024
  • hash-function : 用于HMAC的散列函数,如SHA256
  • derived-key-len : 派生密钥长度(字节数),如32

目前PBKDF2已经是一种过时的不安全的KDF算法,建议使用ScryptArgon2来代替它。

因为PBKDF2不抗GPU攻击( GPU-resistant),也不抗ASIC攻击( ASIC-resistant),因此在某些专业的服务器上被攻破的可能性较大,包括配置了专业显卡GPU的服务器或使用专门设计的硬件电路(ASIC)的服务器。
现代的KDF比如 ScryptArgon2都能抵抗字典攻击、GPU攻击与ASIC攻击,因为它们的算法在设计上就要消耗大量CPU与RAM内存资源,且不能通过GPU或ASIC来实现快速的并行计算。
GPU攻击与ASIC攻击在本质上是一种野蛮的试图攻破散列函数的攻击,因此现代KDF的设计目标之一就是使这种野蛮破解的成本上升到实际不可能实现的程度。

Bcrypt (开始淘汰)

Bcrypt 也是一个 KDF ,问世时间早于 Scrypt ,对于 ASIC 、GPU 攻击的抗性相对弱一些。其虽然也可以配置迭代数,但由于对内存的压力较小,因此比较容易构建相应的硬件加速密码破解器。

来自 https://zhuanlan.zhihu.com/p/557583762 的说法: 

Bcrypt是一个开始被淘汰的密码学KDF。它提供可配置的迭代次数,但使用恒定的内存,因此相对来说,比较容易被硬件加速密码破解器所破解,在抗GPU攻击和抗ASIC攻击上已经不再安全。 

算法参数、盐、Hash 的共同存储

在很多的应用、框架和工具中(比如 WordPress 站点的数据库),Bcrypt 加密后的密码都是和算法设置以及盐保存在一起的,体现为一个单一的字符串(字符串有着特定的格式)。这个字符串包含数个部分,以 $ 符号分割。例如,密码 p@ss~123 以 Bcrypt 标准格式存储的形式就是下面这样的(给出三个例子是为了方便读者看清特征):

$2a$07$wHirdrK4OLB0vk9r3fiseeYjQaCZ0bIeKY9qLsNep/I2nZAXbOb7m
$2a$12$UqBxs0PN/u106Fio1.FnDOhSRJztLz364AwpGemp1jt8OnJYNsr.e
$2a$12$8Ov4lfmZZbv8O5YKrXXCu.mdH9Dq9r72C5GnhVZbGNsIzTr8dSUfm

什么时候用 Bcrypt ?

在配置合适的前提下,Bcrypt 被认为是安全的 KDF 函数,在实践中应用广泛。但由于 Scrypt 比 Bcrypt 更加安全,因此很多应用更倾向于使用 Scrypt(或 Argon2 )。但我个人更推荐使用 Argon2 。

Scrypt

Scrypt 是一个强大的密钥派生函数,其通过内存密集的计算方式来抵抗 GPU、ASIC、FPGA 这类密码破解硬件的攻击。

Scrypt 接收多个输入参数,进行计算后输出密钥:

key = Scrypt(password, salt, N, r, p, derived-key-len)

其中的参数被称为" Scrypt 配置参数",说明如下:

  • N - 迭代次数,将影响 CPU 和内存用量,例:16384 、2048 ;
  • r - 块大小,将影响 CPU 和内存用量,例:8 ;
  • p - 并行因数 (并行运行的线程数,将影响 CPU 和内存用量),通常为 1 ;
  • password - 输入的密码(推荐至少为 8 - 10 个字符);
  • salt - 安全产生的随机字节序列(最小为 64 位,推荐 128 位);
  • derived-key-len - 输出的密钥要有多少字节长,例如 32 (256 位)

Scrypt 计算过程中的每一步都会 按照强相关的顺序 访问内存,这就让内存读写性能成为了算法速度的瓶颈。Scrypt 运行时所需的内存量可以通过下面的公式来计算:

所需内存 = 128 * N * r * p 字节

例如:128 * N * r * p = 128 * 16384 * 8 * 1 = 16MB(或 128 * 2048 * 8 * 1 = 2MB)

具体怎么选择参数,要取决于我们能够等待的时间和所需的安全等级(即抗破解的能力):

  • 用于交互式登录的示例参数:N=16384, r=8, p=1(RAM = 16MB)。交互式的登录一般耗时都要小于 0.5s ,所以必须快速完成计算。同样的,对于服务端而言,如果同时有很多用户登录,那么 Scrypt 的缓慢会拖慢整个系统;
  • 用于文件加密的示例参数:N=1048576, r=8, p=1(RAM = 1GB)。当要加密硬盘时,通常不会频繁解密数据(一天可能只解密 2 ~ 3次),所以你可能会愿意多等 2 ~ 3 秒作为提升安全性的代价。

你可以在开发自己的 app 或系统的过程中,自己多选几组参数进行测试。应该总是选择所用语言和平台所支持的、速度最快的 Scrypt 实现,因为尝试破解密码的人一定会选用最快的这个库。某些实现(如 python 实现)可能会比最快的实现慢上 100 倍。

在 MyEtherWallet 加密钱包应用中,默认的参数是 N=8192, r=8, p=1 。对于此类应用而言,该强度不够高,但可以通过要求用户输入又长又复杂的密码来对抗密码破解攻击。

示例 - Python 中的 Scrypt

接下来,我们在 Python 中使用 Scrypt 来体验从密码派生密钥的过程。首先,使用 pip 安装 scrypt 包:

pip install scrypt

注意,scrypt 包依赖 OpenSSL ,所以要先在默认目录中安装 OpenSSL (Windows 下可能为: C:\OpenSSL-Win64),然后再安装 scrypt python 包。

装好 scrypt 包后,通过如下 Python 代码来计算 Scrypt hash 值:

(本例中使用了较小的迭代数,这么做只是希望减少所需的时间。实际应用中推荐使用 16384 )

import pyscrypt
​
salt = b'aa1f2d3f4d23ac44e9c5a6c3d8f9ee8c'
passwd = b'p@$Sw0rD~7'
key = pyscrypt.hash(passwd, salt, 2048, 8, 1, 32)
print("Derived key:", key.hex())

Scrypt 接收的参数:password(字节序列)、salt(字节序列)、迭代数、每次迭代的块大小、并行因数、输出密钥长度(派生密钥的字节数)。上面代码的输出如下:

Derived key: b'e813a6f6ccc4e9110193bf9efb7c0a489d76655f9e36629dccbeaf2a73bc0c6f'

可以试着修改迭代数或块大小参数,来这些参数的变化对于执行时间的影响。不过别忘了,上面的 Python Scrypt 是一个比较慢的实现,如果要实际应用,可以试着找些更快的库

译注:所需要的密钥长度为 32 字节,而上面输出的实际长度为 64 字节,这是正确的结果。 我们在参数中写的"密钥长度"指的是【密钥二进制长度为32字节,即256位】,而由于真正包含8位信息的一个字节中的大部分是不可打印的,这就意味着它们无法被显示。因此,通行表示字节的方式是使用 16 进制字符(即字符 0 ~ f )。这样的一个字符只能表示 4 位的信息量,所以我们需要两个这样的字符才能涵盖完整的 8 位(即 1 字节)信息。这也就造成了最终我们得到的密钥字符长度是实际二进制密钥长度的 2 倍

算法参数、盐、Hash 的共同存储

在很多的应用、框架和工具中,Scrypt 加密后的密码都是和算法设置以及盐保存在一起的,体现为一个单一的字符串(以特定的格式)。这个字符串包含数个部分,以 $ 符号分隔。例如,密码 p@ss~123 以 Scrypt 标准格式存储的形式就是下面这样的(给出三个例子是为了方便读者看清特征):

16384$8$1$kytG1MHY1KU=$afc338d494dc89be40e317788e3cd9166d066709db0e6481f0801bd918710f46
16384$8$1$5gFGlElztY0=$560f6229356c281a525fad4e2fc4c209bb55c21dec789381335a32bb84888a5a
32768$8$4$VGhlIHF1aWo=$54d657cec8b3aaca675b407e790bccf1dddb0a23665cd5f994820a736d4b58ba

什么时候用 Scrypt ?

在配置合适的前提下,Scrypt 被认为是高度安全的 KDF 函数,所以可以用在任何需要 KDF 的地方——加密钱包、文件、App 密码等场景都可以

Argon2

Argon2 是一个现代的 抗ASIC、抗GPU 的安全密钥派生函数。在配置得当、且消耗资源相当的情况下,其相较于 PBKDF2、Bcrypt 和 Scrypt ,有着更强的密码破解抗性。

Argon2 变种

Argon2 有多个变种:

  • Argon2d - 提供强大的 GPU 攻击抗性,但在非常特殊的情况下,会有被旁路攻击的风险;
  • Argon2i - 提供弱一些的 GPU 攻击抗性,但没有被旁路攻击的风险;
  • Argon2id - 是上面两种变体的混合版,推荐使用这个版本

Argon2 的配置参数

Argon2 有如下几个配置参数,和 Scrypt 很像:

  • 密码 P : 要被 hash 的密码(或消息 message );
  • 盐 S : 随机生成的盐(用于密码 hash 时,推荐使用 16 字节长度的盐);
  • 迭代数 t : 要进行的迭代次数;
  • memorySizeKB m : 要使用的内存大小(单位为 kbytes) ;
  • parallelism p : 并行程度(即线程数);
  • outputKeyLength T : 想要算法返回的字节长度

示例 - Python 中的 Argon2

接下来我们写一些代码,来在 Python 中使用 Argon2 进行密钥派生。

首先,用下面的命令安装 python 包 argon2_cffi :

pip install argon2_cffi

用下面的代码来计算 Argon2 :

import argon2, binascii
​
hash = argon2.hash_password_raw(
    time_cost=16, memory_cost=2**15, parallelism=2, hash_len=32,
    password=b'password', salt=b'some salt', type=argon2.low_level.Type.ID)
print("Argon2 raw hash:", binascii.hexlify(hash))
​
argon2Hasher = argon2.PasswordHasher(
    time_cost=16, memory_cost=2**15, parallelism=2, hash_len=32, salt_len=16)
hash = argon2Hasher.hash("password")
print("Argon2 hash (random salt):", hash)
​
verifyValid = argon2Hasher.verify(hash, "password")
print("Argon2 verify (correct password):", verifyValid)
​
try:
    argon2Hasher.verify(hash, "wrong123")
except:
    print("Argon2 verify (incorrect password):", False)

上面的代码首先生成一个 "raw hash" (256 位密钥),这一步是基于 argon2 的密钥派生,和 Scrypt 类似。下一步会派生一个 argon2 hash ,其中包含了算法参数、盐和派生密钥,可以用于后续的密码存储和验证。这段代码的最后将对密码进行验证。

Argon2 接收如下几个输入配置参数:time_cost(时间消耗,即迭代次数)、memory_cost(要使用的 KB 数)、parallelism(并行度,使用多少个线程)、hash_len(派生密钥的长度)、salt_len(随机生成盐的长度,通常是 128 位 / 16 字节)。

上面代码的示例输出如下:

Argon2 raw hash: b'157f21dd3fdf7bafb76d2923ccaffa0b7be7cbae394709474d2bc66ee7b09d3e'
Argon2 hash (random salt): $argon2id$v=19$m=32768,t=16,p=2$Rfy6J41W9idBU+n/8sZc6Q$i3QYYPtoogIAw78I2qqlUQ8vjzUXGG1V6QsBOq2NIp4
Argon2 verify (correct password): True
Argon2 verify (incorrect password): False

上面输出中的 argon2 hash 是标准格式的:【配置参数 + 派生密钥 + 随机盐】。按照设计,每次代码执行时所用的盐和派生密钥都应该是不同的。

试着多执行几次上面的代码,会发现派生密钥总是相同的(因为盐相同),而派生的 argon2 hash 则每次都不同(这部分所用的随机盐是每次执行时在算法内部重新生成的)。

可以试着修改 time_cost 和 memory_cost 设置,来感受一下它们将如何影响密钥派生时间。

算法参数、盐、Hash 的共同存储

在很多的应用、框架和工具中,Argon2 加密后的密码都是和算法设置以及盐保存在一起的,体现为一个单一的字符串(字符串有着特定的格式,就如上面展示的那样)。这个字符串包含数个部分,以 $ 符号分割。例如,密码 p@ss~123 以 Argon2 标准格式存储的形式就是下面这样的(给出三个例子是为了方便读者看清特征):

$argon2d$v=19$m=1024,t=16,p=4$c2FsdDEyM3NhbHQxMjM$2dVtFVPCezhvjtyu2PaeXOeBR+RUZ6SqhtD/+QF4F1o
$argon2d$v=19$m=1024,t=16,p=4$YW5vdGhlcnNhbHRhbm90aGVyc2FsdA$KB7Nj7kK21YdGeEBQy7R3vKkYCz1cdR/I3QcArMhl/Q
$argon2i$v=19$m=8192,t=32,p=1$c21hbGxzYWx0$lmO1aPPy3x0CcvrKpFLi1TL/uSVJ/eO5hPHiWZFaWvY

上面的几个 hash 值都保存了相同的密码,但都有着不同的算法参数和不同的盐。

Argon2有三个变体:

  • Argon2d : 速度比较快,对GPU攻击具有很高的抵抗力,适用于不受侧信道攻击威胁的应用程序,比如加密货币。
  • Argon2i : 速度较慢,对GPU攻击抗力相对较弱,但不会受到侧信道攻击。
  • Argon2id : Argon2i和Argon2d的混合体,即对GPU攻击具有很高的抵抗力,也不会受到侧信道攻击。推荐首选的Argon2算法。 

什么时候用 Argon2 ?

在配置合适的前提下,Argon2 被认为是高度安全的 KDF 函数,是目前产业界能用到的最佳选择之一,所以可以用在任何需要 KDF 的地方——加密钱包、文件、App 密码等场景都可以。一般来说,Argon2 是最为推荐的 KDF ,优于 Scrypt, Bcrypt 和 PBKDF2 。

总体而言,安全高度上: Argon2 > Scrypt > Bcrypt(开始淘汰) > PBKDF2(过时)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/558332.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

汇编语言学习笔记

1、NOP指令:号称最安全的指令,全名为no Operation,一条nop指令占用一个字节,什么也不做。有时编译器会使用该指令将代码对齐到偶数地址边界(类似于内存对齐)。IA-32处理器从偶数双字地址处加载代码和数据时…

【简单介绍下Beego框架】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

等保合规:保护企业网络安全的必要性与优势

前言 无论是多部网络安全法律法规的出台,还是最近的“滴滴被安全审查”事件,我们听得最多的一个词,就是“等保。” 只要你接触安全类工作,听得最多的一个词,一定是“等保。” 那么,到底什么是“等保”呢…

c++初阶——类和对象(上)

大家好我是小锋今天我们来学习类和对象 面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对…

NASM中的-f选项

2024年4月19日,周五下午 -f选项 在 NASM 中,-f 选项用于指定输出格式或目标文件格式。这个选项允许你告诉 NASM 将汇编代码编译成特定格式的目标文件,以便与特定的操作系统或环境兼容。下面是 -f 选项的一些常见用法和参数: -f …

✌粤嵌—2024/4/11—合并区间✌

代码实现: /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/// 交换 void swap(i…

“开关是灯的日出日落,日出日落是灯的开关”

C语言刷题 day01 本篇是C语言刷题大杂烩,收集了笔者遇到的认为有价值的题目,本篇会持续更新~~ day01 至少是其他数字两倍的最大数 题目原文: 题意解析: 请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 …

【汇智知了堂来袭】西华师范大学鸿蒙专题讲座,共探HarmonyOS新机遇!

在这个信息化的时代,我们身处一个日新月异、科技飞速发展的世界。随着信创国产化的步伐加快,万物互联的大时代已经悄然开启。作为科技前沿的探索者,汇智知了堂始终站在行业的前沿,紧跟时代的发展脉搏。我们在4月9日走进西华师范大…

5. Django 探究CBV视图

5. 探究CBV视图 Web开发是一项无聊而且单调的工作, 特别是在视图功能编写方面更为显著. 为了减少这种痛苦, Django植入了视图类这一功能, 该功能封装了视图开发常用的代码, 无须编写大量代码即可快速完成数据视图的开发, 这种以类的形式实现响应与请求处理称为CBV(Class Base…

第一届AI Agent智能体现场开发大赛报名开启!8月上旬火热开赛~

由联想拯救者、AIGC开放社区、英特尔携手主办的“AI生成未来第二届拯救者杯OPENAIGC开发者大赛”已经正式启动,“2024 AI Agent极限挑战赛”作为特设专项赛道,也将同步于8月上旬开赛,参赛者将在更加紧张刺激的现场比赛中展现其技术与创造力。…

TypeScript 基础:接口、泛型和自定义类型在 Vue 3 中的应用

接口(Interfaces) 首先,我们定义一个接口 PersonInter 来描述一个人的信息,包括 id、name 和 age。 interface PersonInter {id: string;name: string;age: number; }自定义类型(Custom Types) 然后&…

如何在Windows 10中启用和使用上帝模式,这里有详细步骤

序言 上帝模式(God Mode)是一个特殊的文件夹,只在一个窗口中显示所有可用的操作设置。它可以节省搜索命令的时间,而无需知道通过“开始”菜单或“控制面板”查找命令的步骤。上帝模式默认情况下是隐藏的,所以我们需要…

世界500强:破解“智慧核能”数智化成功转型密码

近日,实在智能携手中国核能行业协会信息化专业委员会在中国人工智能小镇成功举办“基于大模型的RPA数字员工在核能行业实战应用案例专项培训”,中国核工业集团、中国广核集团、国家电力投资集团等企事业单位共同参加。中核集团作为我国核科技工业的主体&…

C++修炼之路之继承<二>

目录 一:子类的六大默认成员函数 二:继承与友元 三:继承与静态成员 四:复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

javaagent使用

Java Agent是什么? Java Agent是Java平台提供的一个强大工具,它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的,它能够在不影响正常编译的情况下修改字节码,相当于是在main方法执行之前的拦截器,也叫…

启明云端ESP32-S3+车载桥接器案例,能实现对车载产品集控

最近房车旅行很盛行,谁不想五一自驾游开车去外面玩?为了能提升用户体验,车企房车智能化升级越来越普遍,接下来小启给大家讲一个案例,启明云端ESP32-S3车载桥接器,感兴趣的可以看看。 一、ESP32-S3车载桥接器…

实验:使用FTP+yum实现自制yum仓库

实验准备 FTP服务器端:centos-1(IP:10.9.25.33) 客户端:centos-2 两台机器保证网络畅通,原yum仓库可用,已关闭防火墙和selinux FTP服务器端 ①安装vsftpd并运行,设定开机自启动 安装vsftpd…

免费ssl通配符证书申请教程

在互联网安全日益受到重视的今天,启用HTTPS已经成为网站运营的基本要求。它不仅保障用户数据传输的安全,提升搜索引擎排名,还能增强用户对网站的信任。通配符证书是一种SSL/TLS证书,用于同时保护一个域名及其所有下一级子域名的安…

​面试经典150题——对称二叉树

1. 题目描述 2. 题目分析与解析 2.1 思路一——递归 为了解决问题“检查一个二叉树是否是对称的”,我们需要判断树的左子树和右子树是否是彼此的镜像。这意味着树的左子树的左侧应该与右子树的右侧相同,左子树的右侧应该与右子树的左侧相同。 定义问题…

数字工厂管理系统的应用场景主要有哪些

随着信息技术的飞速发展,数字工厂管理系统逐渐成为了工业制造领域的一大亮点。这一系统集成了物联网、大数据、云计算、人工智能等先进技术,实现了对工厂生产流程的智能化、高效化管理。那么,数字工厂管理系统究竟在哪些应用场景中发挥着重要…