SHA3算法笔记

news2024/9/28 19:15:23

文章目录

  • 1 INTRODUCTION
  • 2 GLOSSARY
  • 3 KECCAK-p Permutations
    • 3.1 State
      • 3.1.2 Converting Strings to State Arrays
      • 3.1.3 Converting State Arrays to Strings
      • 3.1.4 Labeling Convention for the State Array
    • 3.2 Step Mappings
      • theta
      • rho
      • pi
      • chi
      • iota
    • 3.3 KECCAK-p[b, n~r~]
    • 3.4 KECCAK-f
  • 4 SPONGE CONSTRUCTION
    • 5.1 Specification of pad10*1
    • 5.2 Specification of KECCAK[c]
  • 6 SHA-3 FUNCTION SPECIFICATIONS
    • 6.1 SHA-3 Hash Functions
    • 6.2 SHA-3 Extendable-Output Functions
      • 6.3 Alternate Definitions of SHA-3 Extendable-Output Functions
  • A Security
    • A.1 Summary
  • B Examples
    • B.1 Conversion Functions
    • B.2 Hexadecimal Form of Padding Bits
  • 实现
  • 参考资料

原文档: SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions,《SHA-3标准:基于置换的哈希与可扩展输出函数》

1 INTRODUCTION

2012年10月,NIST选用Keccak作为SHA-3的标准算法,经过对原算法的修改,于2015年8月发布标准文档FIPS 202,作为对FIPS 180-4 SHA-2的补充。

准确地说,Keccak团队当初提交的是Keccak-f[1600]。

SHA-3 family:

  • 4 cryptographic hash functions:
    • SHA3-224
    • SHA3-256
    • SHA3-384
    • SHA3-512
  • 2 eXtendable-Output Functions (XOFs):
    • SHAKE128 (Secure Hash Algorithm KECCAK)
    • SHAKE256

其中,XOF输出的哈希值可以任意指定长度。

消息后面会追加2 bits,用来区分hash函数和XOFs,或者以后的sha3变体。

2 GLOSSARY

3 KECCAK-p Permutations

2 parameters:

  • b, in {25, 50, 100, 200, 400, 800, 1600}: the fixed length of the strings that are permuted, called the width of the permutation.
  • nr, any positive integer: the number of iterations of an internal transformation, called a round.

表示:KECCAK-p[b, nr]

b取值25和50仅仅用于研究原理,不可实际应用。

3.1 State

对于KECCAK-p[b, nr] permutation, state表示b bits.

另外两个参数:

  • w = b/25
  • l = log2(b/25) = log2w
b25501002004008001600
w1248163264
l0123456

比特流state(S)也可以表示为 5x5xW的三维bit数组A[x][y][z](0≤x<5, 0≤y<5, and 0≤z<w),这里还涉及以下概念:

  • 二维:sheets, planes, and slices
  • 一维:rows, columns, and lanes.

请添加图片描述

3.1.2 Converting Strings to State Arrays

A[x,y,z] = S[w(5y+x)+z]

其实就是点线面体,顺序为:

  1. lane ,z线
  2. plane ,xz面
  3. state,垒高

eg. b=1600, w=64

A[4,2,63]=S[959]

3.1.3 Converting State Arrays to Strings

其实就是反过来的过程,以lane为单位,从左到右,从下往上。

还是以b=1600, w=64为例:

S = A[0, 0, 0] || A[0, 0, 1] || ... || A[0, 0, 63]
 || A[1, 0, 0] || ... || A[1, 0, 63]
 || A[4, 4, 0] || ... || A[4, 4, 63]

3.1.4 Labeling Convention for the State Array

Z坐标为0的第一个slice面的中心为state原点。

X和Y轴坐标为3,4,0,1,2,也就是说S[0]对应(3,3,0)。

请添加图片描述

虽然中间的lane坐标为(0,0),但结合3.1.2和3.1.3,从代码的角度看,可以通过对5取余来处理,也就是说把数组第一个元素当成中间的lane即可。

3.2 Step Mappings

step mapping == Rnd == A round of a KECCAK-p permutation == round function,由5个函数组成。

构成Rnd(A round of a KECCAK-p permutation)的5个函数:

 θ, ρ, π, χ, ι
 or
 theta, rho, pi, chi, iota
  • 输入参数:state array A
  • 返回:state array A’

iota额外需要一个round index参数 ir

这一部分会比较绕,而且是以bit为单位进行讲解,但在代码中则是以ullLane(8字节unsigned long long)为单位进行运算。

theta

C[x,z]=A[x,0,z] 
	^ A[x,1,z] 
	^ A[x,2,z] 
	^ A[x,3,z] 
	^ A[x,4,z]
D[x,z]=C[(x-1) mod 5, z] 
	^ C[(x+1) mod 5, (z-1) mod w]
A′[x,y,z] = A[x, y, z] ^ D[x,z]

C:将5个plane面进行异或,在代码层面会得到5个ullLane(1个plane);

D:将column两两异或,在代码层面,相当于将8字节整型向高地址移位(小端整型,所以左移),得到的仍是5个ullLane;

将每个plane与plane D中异或后返回state array。

rho

这个函数的作用是将(0,0,z)以外的lane进行循环位移,offset表如下:

x = 3x = 4x = 0x = 1x = 2
y = 2153231310171
y = 155276363006
y = 0289101190
y = 41207821066253
y = 3211361054515

因为(0,0,z)这个中间的lane不需要变化,所以一共移动24个lane:

x,y = (1,0)
d = {}
for t in range(24):	# 23 times
    d[t] = (x,y)
    x,y = (y, (2*x + 3*y)%5)    # 这个公式恰好遍历24个lane
print(len(d))   # 24

for t,v in d.items():
    print(v)
    # z = (z - (t+1)*(t+2) /2) % w
    # 以下省略w
    print("t=%d offset = %d\n" % (t,(-(t+1)*(t+2)/2)))
# 24
# (1, 0)
# t=0 offset = -1
# (0, 2)
# t=1 offset = -3
# (2, 1)
# t=2 offset = -6
# (1, 2)
# t=3 offset = -10
# (2, 3)
# t=4 offset = -15
# (3, 3)
# t=5 offset = -21
# (3, 0)
# t=6 offset = -28
# (0, 1)
# t=7 offset = -36
# (1, 3)
# t=8 offset = -45
# (3, 1)
# t=9 offset = -55
# (1, 4)
# t=10 offset = -66
# (4, 4)
# t=11 offset = -78
# (4, 0)
# t=12 offset = -91
# (0, 3)
# t=13 offset = -105
# (3, 4)
# t=14 offset = -120
# (4, 3)
# t=15 offset = -136
# (3, 2)
# t=16 offset = -153
# (2, 2)
# t=17 offset = -171
# (2, 0)
# t=18 offset = -190
# (0, 4)
# t=19 offset = -210
# (4, 2)
# t=20 offset = -231
# (2, 4)
# t=21 offset = -253
# (4, 1)
# t=22 offset = -276
# (1, 1)
# t=23 offset = -300

计算出来的偏移为负值,对于unsigned long long小端存储类型来说是左移,与表格中的正值都是向z轴的正方向移动。

pi

该函数的作用是将中心以外的各个lane进行重新排列(乾坤大挪移 嘿哈)。

# A'[x,y] = A[(x + 3*y) % 5, x]
x,y = (1,0)
s = set()
for t in range(24):
    s.add((x,y))
    print(x,y)
    x,y = (x + 3*y) % 5, x	# 这个公式也恰好遍历24个lane
print(len(s))	# 24

chi

该函数是对每个row进行置换:

A′[x,y,z] = A[x,y,z] 
	^ ( (~A[(x+1) % 5, y, z])
		& A[(x+2) % 5, y, z])

当然在代码层面,还是以lane为单位进行操作的。

而且对于pi和chi两个置换函数,不要直接对原state进行操作,需要拷贝副本。

iota

这一函数的目的是使(0,0)这个lane与 round constant进行异或,因为这个lane受round index影响,而另外24个lane不会经过iota函数处理。

如前所说,iota函数需要一个round index参数,即3.3部分的Keccak_p函数的循环索引。

伪代码如下:

keccak_state iota(keccak_state A, uint32_t ir)
{
	// ir = Algorithm7(b, nr)  round index
	keccak_state retA = A;
	// uint32_t w = b / 25;	// 64
	// uint32_t l = log2(w);	// 6
	// uint64_t RC[w] = {0};	//  round constant
	// uint32_t j = 0;
	for (j = 0; j <= l; ++j)
	{
		RC[2 * *j - 1] = rc(j + 7 * ir);
        // the last one is RC[w-1]
	}
    // for all 0 <= z <= w
	retA[0, 0, z] = retA[0, 0, z] ^ RC[z];
	return retA;
}

可以看出,RC数组其实是固定的,并不需要在运行时计算,硬编码即可:

#define NUMBER_OF_ROUNDS 24
static const uint64_t roundconstants[NUMBER_OF_ROUNDS] = {
    0x0000000000000001ULL,    0x0000000000008082ULL, 
    0x800000000000808aULL,    0x8000000080008000ULL, 
    0x000000000000808bULL,    0x0000000080000001ULL, 
    0x8000000080008081ULL,    0x8000000000008009ULL, 
    0x000000000000008aULL,    0x0000000000000088ULL, 
    0x0000000080008009ULL,    0x000000008000000aULL, 
    0x000000008000808bULL,    0x800000000000008bULL, 
    0x8000000000008089ULL,    0x8000000000008003ULL, 
    0x8000000000008002ULL,    0x8000000000000080ULL, 
    0x000000000000800aULL,    0x800000008000000aULL, 
    0x8000000080008081ULL,    0x8000000000008080ULL, 
    0x0000000080000001ULL,    0x8000000080008008ULL
};

对于SHA3中每个lane,长度为8字节(64 bits),其中可置为1的下标为代码中的2 * *j - 1,如下:

0x80000000 8000808B

至于生成它的函数rc(t),根据keccak原文档 1.2节,它其实是一个线性反馈移位寄存器(LFSR):

// rc[t] = (x^t mod x^8 + x^6 + x^5 + x^4 + 1) mod x in GF(2)[x].

int LFSR86540(uint8_t* LFSR)
{
	int result = ((*LFSR) & 0x01) != 0;
	if (((*LFSR) & 0x80) != 0)
		// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
		(*LFSR) = ((*LFSR) << 1) ^ 0x71;	// 0111 0001
	else
		(*LFSR) <<= 1;
	return result;
}

void KeccakInitializeRoundConstants()
{
	uint8_t LFSRstate = 0x01;
	unsigned int ir, j, bitPosition;
	uint8_t nr = 24;
	uint64_t KeccakRoundConstants[64] = {0};
	for (ir = 0; ir < nr; ir++) {
		KeccakRoundConstants[ir] = 0;
		for (j = 0; j < 7; j++) {
			bitPosition = (1 << j) - 1; //2^j-1
			if (LFSR86540(&LFSRstate))
				KeccakRoundConstants[ir] ^= (uint64_t)1 << bitPosition;
		}
	}
	for (ir = 0; ir < 24; ++ir)
	{
		printf("%016llx\n", KeccakRoundConstants[ir]);
	}
}

3.3 KECCAK-p[b, nr]

Rnd函数:

Rnd(A, ir) = iota(chi(pi(rho( theta(A) ))), ir)

Keccak-p[b, nr]有nr轮Rnd迭代,如下:

string Keccak_p(string s/*length b*/,int nr)	// Algorithm 7
{
	string s;
    keccak_state A = convertS2A(s);
    uint32_t w = b / 25;	// 64
	uint32_t l = log2(w);	// 6
    for(int ir = 12+2*l-nr; ir <= 12+2*l-1; ++ir)
    {
        A = Rnd(A, ir);
    }
    s = convertA2S(A);
    return s;
}

在代码中,s是单字节数组,state array则是ull类型数组,所以convertS2A也是按照小端存储来转换。

沿着z轴方向,相当于从低地址到高地址。

3.4 KECCAK-f

原版本keccak中定义了KECCAK-f ,它其实是nr==12+2l时的keccak-p,也是SHA3最终选用的操作:

KECCAK-f[b] = KECCAK-p[b, 12+2*l]

SHA3选用了比特流长度b==1600,即KECCAK-p[1600, 24],相当于是KECCAK-f[1600]

4 SPONGE CONSTRUCTION

Keccak采用的算法结构叫做海绵结构。

string Z = SPONGE[f, pad, r](string N, uint d)

3 components:

  • f :
    • An underlying function on fixed-length strings;
    • b is called the width of f;
    • In SHA-3, f is invertible, although the sponge construction does not require f to be invertible.
  • r:
    • A parameter called the rate
    • capacity,c == b - r,specified in Sec. 5.2
  • pad: A padding rule
    • m = len(N), (m + len(pad(r, m)) ) mod r == 0

2 inputs:

  • N: a bit string
  • d: bit length of the output string

Output:

  • string Z of length d

海绵结构的流程(对应代码中的final函数)可看作以下几步:

  1. pad
  2. absorbing 吸入,string–>State Array,
  3. 轮函数执行f(),即keccak-f(),且每“吸入” 1个分组(rate 字节)就执行一次
  4. squeezing 挤出,State Array–>string of length d,而且每“挤出”1个分组,就要再执行一次f()。

在代码中第2、3步相当于hash udpate。

请添加图片描述

海绵结构和rate,这俩词非常形象,笔者一开始把rate理解为valid buffer,因为这些数据其实是存储在block中的,只不过不像sha2那样把block缓冲区填满。函数f相当于挤压海绵,吸收数据和输出摘要,都需要“挤压”一下。

根据第7章,SHA-3 hash分组大小rate如下表:

HashSHA3-224SHA3-256SHA3-384SHA3-512
BlockSize(bytes)14413610472

5.1 Specification of pad10*1

The padding rule for KECCAK is called multi-rate padding.

inputs:

  • r : rate
  • m : len(N)

output:

  • string P, (m + len(pad(r, m)) ) mod r == 0,即填充完后,数据长度是r的倍数,所以r就是分组大小。
uint pad10x1(uint r, uint m)
{
    uint P;
    uint j = (-m-2) % r;
            
	// (m + len(P)) % r == 0
    // len(P) == (-m) % r
    P = (1<<j) + 1;	// 1 || 0*j || 1
    return P;
}

实际的补充方法,请参见附录B。

5.2 Specification of KECCAK[c]

根据第4节海绵结构,总结一下keccak的组成:

  • 海绵函数Keccak-p[b, 12+2l]
  • 填充规则pad10*1
  • rate(<b),其实就是分组大小

如3.1所述,比特流长度b有7个可选值。当选用最大值b==1600时,就只有rate不确定了。而rate就由c(capacity)决定了:

KECCAK[c](N, d) = SPONGE[
	f = KECCAK-p[1600, 24]
	,pad = pad10*1
	,r = 1600–c](N, d)

6 SHA-3 FUNCTION SPECIFICATIONS

6.1 SHA-3 Hash Functions

SHA3有4个基于KECCAK[c] 定义的hash函数:

SHA3-224(M) = KECCAK[448] (M || 01, 224)
SHA3-256(M) = KECCAK[512](M || 01, 256)
SHA3-384(M) = KECCAK[768] (M || 01, 384)
SHA3-512(M) = KECCAK[1024](M || 01, 512)

如第1部分所述,消息后面会追加2 bits,用来区分hash函数和XOFs。

所以SHA3的这4个hash算法,相当于给消息追加01后的Keccak-f[1600]。

另外可以观察到,c==2d,也就是说,capacity是输出摘要长度的两倍。

6.2 SHA-3 Extendable-Output Functions

SHA3的两个XOF,SHAKE128 和 SHAKE256,也是基于KECCAK[c] 定义的:

SHAKE128(M, d) = KECCAK[256] (M || 1111, d)
SHAKE256(M, d) = KECCAK[512] (M || 1111, d)

6.3 Alternate Definitions of SHA-3 Extendable-Output Functions

还有两个原版sponge functions, RawSHAKE128 和 RawSHAKE256:

RawSHAKE128(J, d) = KECCAK[256] (J || 11, d)
RawSHAKE256(J, d) = KECCAK[512] (J || 11, d)

这个11后缀用以区分RawSHAKE和SHA3 SHAKE

J = M || 11时,就等价于SHAKE128和SHAKE256。这个11后缀,则是用来兼容RawSHAKE和Sakura coding scheme。

A Security

A.1 Summary

FunctionOutput SizeCollisionPreimage2nd Preimage
SHA3-224224112224224
SHA3-256256128256256
SHA3-384384192384384
SHA3-512512256512512
SHAKE128dmin(d/2, 128)≥ min(d, 128)min(d, 128)
SHAKE256dmin(d/2, 256)≥ min(d, 256)min(d, 256)

其中,Collision,Preimage,2nd Preimage为抵抗攻击的安全级别。

B Examples

B.1 Conversion Functions

这里给出了二进制和十六进制的转换法。简单地说,在每个字节中bit是小端存储。

以0xA32E为例:

# support trunc
def h2b(h:int, n:int):
    ret = ""
    b = bin(h)[2:]
    print(b)	# 10100011 00101110
    nBy = len(b) // 8
    for i in range(nBy):
        ret += b[8*i:8*i+8][-1::-1]
        ret += " "
    return ret[:n];
# 0xA32E为大端存储 "\xA3\x2E"
print(h2b(0xA32E, 14))
# 11000101 01110

B.2 Hexadecimal Form of Padding Bits

以上运算是以bit为单位的,但在实际应用中,数据N以及rate肯定是以字节为单位,也就是说r和m均为8的倍数。

在原文档附录B中,给出了以下公式,q为需要填补的字节数:

// m单位: byte
q = (r/8) - (m % (r/8))

这个很好理解,就是补充字节满足整体长度为rate的倍数,等价于下面这个公式:

# 单位: byte
8q == r - 8m % r

5.1 填充方法部分是以bit为单位讲解的,而在代码中,则是以字节为单位,更准确地说是十六进制。

结合5.1和6.1,要添加的bit流如下:

01 1 0j 1

也就是说,要填充的0的个数j,可能是4+8*n。填充结束后,还要将每个字节的bit顺序反转,如下:

def pad(j:int):
    strRet = "0x"
    padding = "01"
    padding += "1" + "0" * j + "1"
    nBy = len(padding) // 8
    for i in range(nBy):
        tmp = padding[8*i: 8*i+8][::-1]
        strRet += "%02x" % (int(tmp, 2))
    return strRet
print(pad(4))
# 0x86	q == 1
print(pad(12))
# 0x0680 q == 2
print(pad(20))
# 0x060080 q == 3
print(pad(28))
# 0x06000080 q == 4

而对于XOF,则是这样填充:

# 1111 1 0j 1
def pad_xof(j:int):
    strRet = "0x"
    padding =  "1111"
    padding += "1" + "0" * j + "1"
    nBy = len(padding) // 8
    for i in range(nBy):
        tmp = padding[8*i: 8*i+8][::-1]
        strRet += "%02x" % (int(tmp, 2))
    return strRet
print(pad(2))
# 0x9f	q == 1
print(pad(10))
# 0x1f80	q == 2
print(pad(18))
# 0x1f0080	q == 3
print(pad(26))
# 0x1f000080	q == 4

实现

https://github.com/C0deStarr/CryptoImp/tree/main/Hash/sha/:

  • sha3.h
  • sha3.c

参考资料

  • 原文档 https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf

  • https://csrc.nist.gov/publications/detail/fips/202/final

  • Keccak Team

  • 原版Keccak:http://keccak.noekeon.org/Keccak-reference-3.0.pdf

  • http://keccak.noekeon.org/Sakura.pdf

  • 海绵结构:http://sponge.noekeon.org/CSF-0.1.pdf

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用 Blackbox Exporter 监控 URL?

前言 监控域名和 URL 是可观察性的一个重要方面&#xff0c;主要用于诊断可用性问题。接下来会详细介绍如何使用 Blackbox Exporter 和 Prometheus 在 Kubernetes 中实现 URL 监控。 Blackbox Exporter 简介 Blackbox Exporter 是 Prometheus 的一个可选组件&#xff0c;像其…

离散变量贝叶斯决策简介

贝叶斯决策 最小风险&#xff1a; min⁡R(αi∣x)∑j1cλ(αi∣ωj)P(ωj∣x)\min R\left(\alpha_i \mid \mathrm{x}\right)\sum_{j1}^c \lambda\left(\alpha_i \mid \omega_j\right) P\left(\omega_j \mid \mathrm{x}\right) minR(αi​∣x)j1∑c​λ(αi​∣ωj​)P(ωj​∣x…

django笔记《内置用户认证系统》

文章目录1 前言2 django.contrib.auth3 使用django的用户认证系统3.1 创建一个新的django项目3.2 做数据库迁移3.3 auth_user表结构3.4 创建一个新用户3.5 User对象3.5.1 创建用户 create_user3.5.2 request.user3.5.3 用户在视图函数中登录3.5.4 关键函数3.6 保护视图函数的方…

每日一问-ChapGPT-20221231-关于中医的各国看法

文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20221231-关于中医的各国看法各个国家对伤寒论的看法日本对于中医的看法韩国对于中医的看法欧美对于中医的看法中国对于中医的看法当日总结每日一问-ChapGPT系列起因 近来看了新闻&#xff0c;看了各种媒体&#xff0c;抖音…

程序员必须要了解的内存知识——硬件

最近阅读了Ulrich Drepper大牛的论文《What Every Programmer Should Know About Memory》&#xff0c;全文114页&#xff0c;尽管2007年出版&#xff0c;但如今看过来&#xff0c;仍干货满满。接来下对文中提及的知识&#xff0c;结合自己对内存知识的理解&#xff0c;对程序员…

前端面试题汇总-Vue篇

1. Vue的基本原理 当一个Vue实例创建时&#xff0c;Vue会遍历data中的属性&#xff0c;用 Object.defineProperty&#xff08;vue3.0使用proxy &#xff09;将它们转为 getter/setter&#xff0c;并且在内部追踪相关依赖&#xff0c;在属性被访问和修改时通知变化。 每个组件实…

APP专项测试

一、安装/卸载/升级更新 分类测试点安装1. 通过第三方软件协助安装是否正常 2. 在不同的操作系统下安装是否正常 3. 安装过程中断网&#xff0c;安装是否正常 4. 安装后的文件夹以及文件是否写到了指定的目录里 5. 软件安装过程是否可以取消&#xff0c;点击取消后&#xff0c…

Windows 10/11玩游戏时第二显示器延迟怎么办?

现在很多人都会给自己的电脑外接一个显示屏&#xff0c;来提高工作效率&#xff0c;或增强游戏体验&#xff0c;但有时候第二块显示器会出现延迟、卡顿、掉帧等问题。 不过驱动小百科整理了几个缓解Win 10/Win 11上第二显示器延迟的方法&#xff1a; 更改显示器刷新率关闭占用…

阿里云物联网智能视频服务接入

物联网视频服务&#xff08;LinkVisual&#xff09;支持视频流上云、存储、转发、告警事件等视频基础能力&#xff0c;提供丰富的视频算法以及云边协同&#xff08;算法云端训练、云端下发、边缘计算推理&#xff09;服务。旨在帮助视频设备厂商、方案商与服务提供商&#xff0…

Mac退出移动硬盘时显示“磁盘无法推出,因为一个或多个程序正在使用它”解决方案

解决方法1. 重启访达2. 重启电脑3. 终端命令行方法4. df -lh不显示移动磁盘名称时的解决方法1. 重启访达 按住option键&#xff0c;在底部程序坞的访达图标右键&#xff0c;选择重新启动。此时访达app会重启&#xff0c;之后尝试推出即可。 或&#xff1a;点击左上角苹果标&a…

CSDN 2021-2022年微博情感数据分析

微博情感分析是一种用于提取微博文本中的情感倾向的方法。它可以帮助企业了解人们对于某个主题的看法和态度。 如果要进行微博情感分析&#xff0c;需要准备一些微博数据。可以使用爬虫程序爬取相关微博数据&#xff0c;这里使用的 Scrapy 框架进行的数据爬虫。可以使用文本分…

JavaWeb:Servlet概述

1.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现&#xff0c;根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&#xff0c;将来我们需要定义Servle…

产品经理的需求分析四个层次

产品经理的需求分析四个层次&#xff1a; 1、第一层次是实现需求&#xff0c;即客户要啥做啥。 2、第二层次是分析转换需求&#xff0c;即客户的真正需求&#xff0c;可能实际和他提的需求不一样&#xff0c;比如客户只是要过河&#xff0c;却提出造一个轮船。所以产品经理需要…

MPS | 简单易用的工业电源模块

工业与医疗应用中&#xff0c;在较高输入电压条件下&#xff0c;输出正压和负压的应用需求越来越多。 在应对输出负压条件时&#xff0c;传统解决方案电路复杂且体积庞大&#xff0c;研发周期较长。以半导体测试为例&#xff0c;新一代的测试机通常需要具备以下特点&#xff1…

TCP三次握手四次挥手详解

三次握手 第一次&#xff1a;客户端发送请求连接的报文&#xff1b;SYN1&#xff0c;表请求建立连接的报文&#xff1b;seq,序列号&#xff0c;随机。 第二次&#xff1a;服务端发送请求连接和同意连接的报文&#xff1b;ACK1&#xff0c;表示确认号有用&#xff1b;ackx1&am…

【一起从0开始学习人工智能】0x01机器学习基础+初次实践

从零开始----到敲出一个推荐系统 文章目录人工智能概述流派能做什么什么是机器学习数据集构成机器学习算法分类机器学习开发流程学习框架和资料怎么做机器学习库与框架可用数据集sklearn使用自带数据集sklearn数据集使用拿到的数据是否全部用来训练模型人工智能概述 人工智能-…

Linux下对文件权限的理解

一、权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受限制 普通用户&#xff1a;在linux下做有限的事情。 超级用户的命令提示符是“#”&#xff0c;普通用户的命…

【Python爬虫 • selenium】selenium4新版本自动获取驱动的常见问题

文章目录前言一、安装驱动二、使用步骤1.导入包2.生成驱动3.打开网站二、selenium闪退问题处理1. selenium版本与代码不匹配2. selenium代码异常三、代码示例1.selenium4代码示例1. Chrome2. Chromium3. Brave4. Firefox5. IE6. Edge7. Opera2.selenium3代码示例1. Chrome2. Ch…

蓄热式加热炉燃烧技术

通过阅读前辈们的一些文章&#xff0c;关于蓄热式加热炉燃烧技术方面进行了总结。 一个蓄热燃烧单元至少由两个烧嘴本体、两个体积紧凑的蓄热室、换向阀和与之配套的控制系统组成&#xff0c;即应用蓄热式 (高温空气 )燃烧技术的炉子烧嘴需成对安装&#xff0c;当烧嘴 A 工作时…

【云原生】K8s PSP 和 securityContext 介绍与使用

文章目录一、概述二、PodSecurityPolicy 的发展1&#xff09;以前为什么需要 PodSecurityPolicy&#xff1f;2&#xff09;现在为什么 PodSecurityPolicy 要消失&#xff1f;三、PSP 简单使用1&#xff09;开启PSP2&#xff09;示例演示1、没有PSP场景测试2、定义PSP【1】资源限…