常见的同态加密算法收集

随着对crypten与密码学的了解,我们将逐渐深入学习相关知识。今天,我们将跟随同态加密的发展历程对相关算法进行简单的收集整理 。

目录

同态加密概念

RSA算法

ElGamal算法

ELGamal签名算法

Paillier算法

BGN方案

Gentry 方案

BGV 方案

BFV 方案

GSW 方案

CKKS方案


同态加密概念

同态加密是基于数学难题与计算复杂性理论的密码学技术。

它是指密文状态下对加密信息进行计算得到一个输出,将这一输出进行解密,其结果与用同一方法处理未加密的明文信息计算得到的输出结果是一致的。

同态加密分为半同态加密和全同态加密。其中:

半同态加密:允许在加密数据上执行特定的算术运算,加法乘法。

全同态加密:支持对密文进行任意形式的加法乘法运算。

半同态加密

全同态加密

乘法同态

加法同态

有限次数全同态

第一代

第二代

第二代

第三代

可实现浮点数近似计算,适合机器学习建模场景

RSA算法

ElGamal算法

Paillier算法

Boneh-Goh-Nissim方案

Gentry方案

BGV方案

BFV方案

GSW方案

CKKS方案

RSA算法

RSA算法是一种公钥算法体制,即每一位用户都有一对密钥,一个是可以公开的,另一个则是秘密的,(分为加密密钥Ka和解密密钥Kd)。加密密钥控制加密,解密密钥控制解密,由计算复杂性原理保证加密钥Ka不能通过计算推出解密钥。这样,就实现了即使将Ka公开也不会暴露Kd。

RSA算法描述:

  1. 任意选取两个不同的大素数p和q(经典值为1024位)计算乘积n=pq,z=(p-1)(q-1);
  2. 任意选取一个大整数e,满足gcd(e,z)=1,即e和z互质。整数e用作加密钥。(注意:e的选取是很容易,例如,所有大于p和q的素数都可用)
  3. 确定解密钥d。满足(de)modz=1,即de=kz+1,(因此,若知道e和z,则很容易计算出d)
  4. 公开整数n和e,秘密保存d。

加密算法(明文m,m为小于n的整数,加密为密文c)

c=m^emodn

解密算法(将密文c解密为明文m)

m=c^dmodn

代码示例:

import random

def fastExpMod(b, n, m):

    '''

    return : b^n mod m

    '''

    result = 1

    while n != 0:

        if (n & 1) == 1:  # 按位与操作

            result = (result * b) % m

        b = (b * b) % m

        n = n >> 1  # 位数右移操作

    return result



def Euclid(a, b):

    '''

    欧几里得算法 ax + by = gcd(a,b)

    Return : [x , y , gcd(a,b)]

    '''

    X = [1, 0, a]

    Y = [0, 1, b]

    while Y[2] != 0:

        Q = X[2] // Y[2]

        NEW_Y = [i * Q for i in Y]

        T = list(map(lambda x: x[0] - x[1], zip(X, NEW_Y)))

        X = Y.copy()

        Y = T.copy()

    return X



def fermatPrimeTest(m, k):

    '''

    费马素性检验算法

    m : 给定整数

    k : 安全参数,重复K次

    '''

    if m % 2 == 0:

        return False

    for i in range(k):

        a = random.randint(2, m - 2)

        g = Euclid(a, m)

        if g[2] == 1:

            r = fastExpMod(a, m - 1, m)

            if r == 1:

                continue

            else:

                return False

        else:

            return False

    return True



def findPrime(lower, upper):

    '''

    return : 一个位于upper和lower之间的素数

    '''

    while True:

        n = random.randint(lower, upper)

        if fermatPrimeTest(n, 6) == True:

            return n



def selectE(fn):

    '''

    fn : euler function

    Return : e

    '''

    while True:

        e = random.randint(1, fn)

        temp = Euclid(e, fn)

        if temp[2] == 1:

            return e



def keyGenerate(lower, upper):

    '''

    给定两个素数p和q生成的区间

    return : e,n,d

    '''

    p = findPrime(lower, upper)

    q = findPrime(lower, upper)

    print("p:" + str(p) + "   q:" + str(q))

    # print("q:"+str(q))

    n = p * q

    fn = (p - 1) * (q - 1)

    e = selectE(fn)

    temp = Euclid(e, fn)  # 欧几里得算法求逆元

    d = temp[0]

    if d < 0:  # 由于e和fn互素故一定存在逆元

        d = d + fn  # 保证d为正数

    return e, n, d



def Encryption_Decryption():

    e, n, d = keyGenerate(1000, 10000)  # 密钥生成

    # 更改keyGenerate函数的两个参数,可以改变生成素数的位数大小。

    print("public key (e,n):", end="")

    print("(" + str(e) + "  ,  " + str(n) + ")\n")

    print("private key d: " + str(d) + "\n")

    m = random.randint(1, n)  # m < n m为明文

    print("Plaintext: " + str(m))

    c = fastExpMod(m, e, n)  # 加密  c为密文 m^e mod n

    print("\nEncryption of PlainText: " + str(c))

    x = fastExpMod(c, d, n)  # 解密 c^d mod n

    print("\nDecryption of CipherText: " + str(x))

    if x == m:

        print("\nThe plaintext and ciphertext are the same.")





if __name__ == "__main__":

Encryption_Decryption()

运行结果:

这段代码通过生成RSA密钥对,加密一个随机生成的明文,然后解密密文,验证了加密和解密的正确性。具体步骤包括生成素数、计算 n 和 ϕ(n)、选择公钥 e、计算私钥 d、加密明文、解密密文,并最终验证解密后的明文与原始明文是否相同。

ElGamal算法

EIGamal密码是除了RSA密码之外最有代表性的公开密钥密码。

与RSA算法不同,RSA是基于因数分解的公钥体制密码,而EIGamal是建立在离散对数的困难问题上的一种公钥体制密码。

EIGamal算法描述

  1. 选取一个素数p,以及小于p的两个随机数g和x;
  2. 计算y=g^xmodp;
  3. 公钥为(y,g,p),私钥为x;

加密算法 M为明文

  1. 选取一个与p-1互质的整数k;
  2. C1=g^kmodp
  3. C2=y^kMmodp
  4. (C1,C2)即为密文

解密算法

C2/C1^x modp=Mmodp

举例:

取p=11, g=5, x=2

则 y = g^xmodp = 3

取 k 为 7, m为10

则C1 = g^kmodp = 3

C2 = y^k*m mod p = 2

则C1^xmodp= 9

9在模11下的逆元为5

所以 C 2 /C 1^ x=2∗5mod10 =10mod10,所以解密成功

示例代码:

import random



# 判断一个数是否为素数

def is_prime(n):

    if n <= 1:

        return False

    if n <= 3:

        return True

    if n % 2 == 0 or n % 3 == 0:

        return False

    i = 5

    while i * i <= n:

        if n % i == 0 or n % (i + 2) == 0:

            return False

        i += 6

    return True



# 生成一个随机的素数

def generate_prime():

    while True:

        p = random.randint(100, 1000)

        if is_prime(p):

            return p



# 生成一个原根

def generate_generator(p):

    phi = p - 1

    factors = []

    for i in range(2, int(phi ** 0.5) + 1):

        if phi % i == 0:

            factors.append(i)

            while phi % i == 0:

                phi //= i

    if phi > 1:

        factors.append(phi)

    for g in range(2, p):

        is_generator = True

        for factor in factors:

            if pow(g, phi // factor, p) == 1:

                is_generator = False

                break

        if is_generator:

            return g



# 生成ElGamal公私钥对

def generate_keys():

    p = generate_prime()

    g = generate_generator(p)

    a = random.randint(2, p - 1)

    h = pow(g, a, p)

    return (p, g, h, a)



keys = generate_keys()

print("公钥:(p, g, h) =", keys[0], ",", keys[1], ",", keys[2])

print("私钥:a =", keys[3])

运行结果:

这段代码实现了 ElGamal 密码体制的公私钥对生成,包括生成随机素数、原根和计算公私钥。生成的公钥 (p, g, h) 和私钥 a 可以用于后续的加密和解密操作。

ELGamal签名算法

密钥产生

确定一个大素数p

取p的一个本原根g

在Zp域上选择一个随机数x

y = gxmodp

(y, g, p)为公钥,x为私钥

签名算法

设待签名的消息为m

取一个与p-1互质的k

C1=gkmodp

C2=(H(m)-x*C1) * k-1mod(p-1)

输出签名(C1,C2)和消息m

代码示例

import random

from sympy import isprime, mod_inverse



# 选择一个素数p和生成元g

def generate_prime_and_generator():

    while True:

        p = random.randint(2 ** 10, 2 ** 11)  # p的范围

        if isprime(p):

            break

    while True:

        g = random.randint(2, p - 2)

        if pow(g, (p - 1), p) == 1:

            break

    return p, g



# 生成密钥对

def generate_key_pair(p, g):

    x = random.randint(2, p - 2)

    y = pow(g, x, p)

    return x, y



# 签署消息

def sign_message(p, g, x, m):

    k = random.randint(1, p - 2)

    r = pow(g, k, p)

    s = (m - x * r) * mod_inverse(k, p - 1) % (p - 1)

    return (r, s)



# 验证签名

def verify_signature(p, g, y, m, r, s):

    if not (0 < r < p and 0 < s < p - 1):

        return False

    left = pow(y, r, p) * pow(r, s, p) % p

    right = pow(g, m, p)

    return left == right



# 输出签名详细过程

def print_signature_process(p, g, x, m, r, s):

    print("--------------------签名过程--------------------")

    print(f"签名消息为: {m}")

    print(f"私钥x为: {x}")

    print(f"随机数k为: {k}")

    print(f"签名结果r为: {r}")

    print(f"签名结果s为: {s}")



# 主程序

if __name__ == "__main__":

    # 生成素数和生成元

    p, g = generate_prime_and_generator()

    # Alice生成密钥对

    x_alice, y_alice = generate_key_pair(p, g)

    # 输出参数

    print("--------------------参数生成过程--------------------")

    print(f"素数p为: {p}")

    print(f"生成元g为: {g}")

    print(f"Alice的公钥y为: {y_alice}")



    # Alice签署消息

    message = 20240301

    k = random.randint(1, p - 2)

    r, s = sign_message(p, g, x_alice, message)



    # 输出签名详细过程

    print_signature_process(p, g, x_alice, message, r, s)



    # 用户输入签名

    print("--------------------验证签名过程--------------------")

    user_r = int(input("请输入r的值: "))

    user_s = int(input("请输入s的值: "))



    # 验证签名

    if verify_signature(p, g, y_alice, message, user_r, user_s):

        print("签名有效")

    else:

        print("签名无效")

运行结果:

这段代码实现了 ElGamal 签名方案的生成、签署和验证过程。通过生成素数 p 和生成元 g,生成密钥对,签署消息,并验证签名,确保了数字签名的安全性和有效性。

Paillier算法

Paillier 同态加密算法是一种非对称加密算法,该算法利用了数论中的复合剩余类的数学性质。

Paillier算法描述

1.随机选择两个大质数p和q满足gcd(pq,(p-1)(q-1))=1。 这个属性是保证两个质数长度相等。

2.计算 n = pq和λ= lcm (p - 1,q-1)。

3.选择随机整数g(g属于Z*n^2),使得满足n整除g的阶。

4.公钥为(n,g)

5.私钥为λ。

加密算法

m属于Zn,r为[1,n-1]的随机数,转换成密文:

C=g^m·r^n modn^2;

解密算法

代码示例:

from phe import paillier

import gmpy2 as gy



# 生成 Paillier 密钥对

public_key, private_key = paillier.generate_paillier_keypair(n_length=128)

print("n: ", public_key.n)

print("g: ", public_key.g)

print("p: ",private_key.p)

print("q: ",private_key.q)



a = 15

b = 20

print("a: ",a)

print("b: ",b)

# 加密 a 和 b

a_enc = public_key.encrypt(a)

print("a_enc: ",a_enc.ciphertext())

b_enc = public_key.encrypt(b)

print("b_enc: ",b_enc.ciphertext())



print("同态加")

print("a + b = ",a+b)

c_enc = a_enc + b_enc

print("c_enc = a_enc + b_enc: ",c_enc.ciphertext())

c_dec = private_key.decrypt(c_enc)

print("c_dec = a + b: ",c_dec)



print("同态数乘")

print("a * b = ",a*b)

c1_enc = a * b_enc

print("c1_enc = a * b_enc: ",c1_enc.ciphertext())

c2_enc = b * a_enc

print("c2_enc = b * a_enc: ",c2_enc.ciphertext())

c1_dec = private_key.decrypt(c1_enc)

c2_dec = private_key.decrypt(c2_enc)

print("c1_dec = a * b: ",c1_dec)

print("c2_dec = b * a: ",c2_dec)

运行结果:

这段代码展示了如何使用 Paillier 同态加密算法进行基本的同态加法和数乘操作。Paillier 同态加密算法是一种加法同态加密算法,支持对密文的加法和数乘操作。

BGN方案

BGN是一种同态加密方案,是Bonel h等人在2005提出的一种具有全同态性质的加密方案。和传统的仅能支持单同态的elgamal和paillier加密方案不一样,BGN能够同时支持加同态和一次乘同态运算。

1.选择椭圆曲线和生成元

2.选择一个椭圆曲线 E 和一个生成元 P,使得 E 的阶为 q,且 q 是一个大素数。

3.选择一个随机的私钥 s,范围在 1 到 q−1 之间。

4.计算公钥 Ppub=sP

生成密钥对

公钥(E,P,Ppub)

私钥s

加密算法

选择随机数

选择一个随机数 r,范围在 1 到 q−1 之间。

加密消息

对于消息 m,计算密文 C

C=(rP,rPpub+mP)

其中,C 是一个二元组,第一个元素是 rP,第二个元素是 rPpub+mP解密算法

解密密文

对于密文 C=(C1,C2),计算:mP=C2sC1

由于 C1=rP 和 C2=rPpub+mP,可以推导出:

mP=(rPpub+mP)−s(rP)=r(sP)+mPs(rP)=mP

通过椭圆曲线上的点 mP 恢复消息 m

 同态加法

同态加法

对于两个密文 C1=(C11,C12) 和 C2=(C21,C22),计算:

C1+C2=(C11+C21,C12+C22)

解密结果为:

m1+m2=(C12+C22)−s(C11+C21)=(m1P+m2P)=(m1+m2)P

同态数乘

同态数乘

对于一个密文 C=(C1,C2) 和一个标量 k,计算:

kC=(kC1,kC2)

解密结果为:

km=k(C2sC1)=k(mP)=(km)P

代码示例:

from ecdsa import NIST384p, SigningKey, VerifyingKey

from ecdsa.util import randrange_from_seed__trytryagain

import os



# 生成密钥对

def generate_keys():

    sk = SigningKey.generate(curve=NIST384p)

    vk = sk.verifying_key

    return sk, vk



# 加密消息

def encrypt(vk, m):

    # 生成一个在有效范围内的随机数 r

    r = randrange_from_seed__trytryagain(os.urandom(32), NIST384p.order)

    C1 = r * NIST384p.generator

    C2 = (r * vk.pubkey.point) + (m * NIST384p.generator)

    return C1, C2



# 解密消息

def decrypt(sk, C1, C2):

    # 计算 -sC1

    neg_sC1 = -(sk.privkey.secret_multiplier * C1)

    # 计算 C2 + (-sC1)

    mP = C2 + neg_sC1

    # 通过椭圆曲线上的点 mP 恢复消息 m

    m = mP.x() % NIST384p.order

    return m



# 同态加法

def homomorphic_add(C1, C2, D1, D2):

    return C1 + D1, C2 + D2



# 同态数乘

def homomorphic_mul(C1, C2, k):

    return k * C1, k * C2



# 主程序

if __name__ == "__main__":

    # 生成密钥对

    sk, vk = generate_keys()

    print("公钥:", vk.to_string().hex())

    print("私钥:", sk.to_string().hex())



    # 加密消息

    m1 = 15

    m2 = 20

    C1, C2 = encrypt(vk, m1)

    D1, D2 = encrypt(vk, m2)

    print("C1:", C1.x(), C1.y())

    print("C2:", C2.x(), C2.y())

    print("D1:", D1.x(), D1.y())

    print("D2:", D2.x(), D2.y())



    # 同态加法

    E1, E2 = homomorphic_add(C1, C2, D1, D2)

    m3 = decrypt(sk, E1, E2)

    print("同态加法结果:", m3)



    # 同态数乘

    k = 3

    F1, F2 = homomorphic_mul(C1, C2, k)

    m4 = decrypt(sk, F1, F2)

print("同态数乘结果:", m4)

运行结果:

BGN 同态加密方案通过椭圆曲线上的点运算实现了对密文的加法和数乘操作。通过生成密钥对、加密消息、解密消息、同态加法和同态数乘,可以实现对密文的高效计算。

Gentry 方案

提出者及背景:2009 年,由 Craig Gentry提出,这是全同态加密领域的重要突破,解决了自公钥加密发明以来一直困扰科学家们的难题。

(在传统加密中,数据一旦加密,就很难在密文状态下进行各种类型的计算。例如,对于常规的 RSA 或 AES 加密,加密后的数据只能进行有限的操作,如存储、传输等。而全同态加密允许在密文上直接进行任意次数的加法和乘法等计算,并且解密后的结果与在明文上进行相同计算再解密的结果相同。)

Gentry 方案之前,全同态加密的概念虽然被提出,但一直没有有效的实现方式。Gentry 利用基于理想格的复杂数学结构,设计出了首个可行的全同态加密方案。

核心原理:基于理想格的数学对象,利用 “双盲” 设计,可以检测加密漏洞并进行修复,而不会造成信息泄露。

方案特点:最初的方案依赖矩阵和矢量进行加密,计算复杂,实用性不强。但它为后续全同态加密方案的研究奠定了基础,具有开创性意义。

局限性:随着计算步骤的增加,连续加密的计算结果质量下降,需要系统实现一定量的计算来进行数据清理实现全同态,且计算复杂。

BGV 方案

提出者及背景:由 Brakerski、Gentry 和 Vaikuntanathan 提出,是第二代全同态加密方案中的重要代表。

核心原理:基于更弱的假设来提高性能和安全性,使用 LWE 或 RLWE 问题构建一个基本的 GLWE 加密方案,再利用 “重线性化” 和 “维度缩减” 技术进行改进,还使用了 “模数切换” 技术来实现同态加法和同态乘法操作并有效减少计算复杂度和存储需求。

方案特点:不需要 Gentry 的自举过程,提供了基于 LWE 或 RLWE 问题的 FHE 方案选择,在选择适当的方案时具有更大灵活性,其安全性和效率都有一定的提升。

局限性:虽然避免了自举过程,但在实际应用中,对于大规模数据和复杂计算,其性能仍有待进一步提高。

BFV 方案

提出者及背景:最初的 LWE 形式由 Brakerski 给出,后在此基础上给出了更实用的 RLWE 形式,是第二代同态加密中的核心方案之一,微软的全同态加密软件 SEAL 最初就是实现的 BFV 方案。

核心原理:在明文空间的高 bit 位编码信息,使用的编码结构,通过密钥生成、加密、解密和同态运算等算法来实现同态加密。

方案特点:同态加法相对简单,就是向量加法。同态乘法较为复杂,需要引入 “重线性化” 技术将乘法破坏的解密结构恢复成线性结构。

局限性:乘法运算的复杂性导致其在处理复杂计算时效率可能较低,且重线性化过程可能会引入一定的误差和计算开销。

GSW 方案

提出者及背景:由 Gentry、Sahai 和 Waters 提出,是一种基于近似特征向量的全同态加密方案。

核心原理:利用近似特征向量的相关性质,将加密、解密和同态运算等操作与矩阵的运算相结合,通过对密文进行特定的矩阵变换来实现同态计算。

方案特点:同态运算更加高效,为矩阵的加、乘运算,且不会引起密文维度的膨胀,无需借助其他技术来控制密文维度的增长,密文噪声的控制更加简洁、有效。

局限性:不支持 SIMD 同态操作,自举实现依赖的安全假设强度较第二代有所弱化,且困难问题的近似因子仅为维度 n 的多项式。

这些方案在同态加密领域的发展中逐代递进,从Gentry的首次证明FHE的存在性,到BGV、BFV和GSW方案的不断优化和简化,逐步提高了同态加密的效率和实用性。每个方案都在前一个方案的基础上进行了改进,引入了新的技术和方法。

CKKS方案

CKKS方案是由Jung Hee Cheon、Kyoohyung Han、Duhyeong Kim、Moon Sung Lee和Yongsoo Song在2019年提出的一种同态加密方案。

它是第一个支持复数运算的同态加密方案。这使得它在处理复数和多项式运算时非常高效,特别适用于需要进行复数运算的应用场景,如信号处理、图像处理和机器学习。CKKS方案基于环上学习带误差问题(Ring-LWE),这是一种高效的构造方法,减少了密文的大小和计算复杂度。同时,CKKS方案引入了多模数技术,支持在不同模数下进行同态操作,提高了灵活性和效率。

算法步骤

1.选择参数:

选择一个合适的环 R 和一个模数 q

选择一个生成元 g 和一个随机的私钥 s

2.生成公钥

计算公钥 h=gsmodq

生成密钥对 (h,s)。

加密算法

选择一个随机数 r

加密消息

对于消息 m,计算密文 C

C=(r·g,r·h+m)modq

解密算法

解密密文

对于密文 C=(C1,C2),计算:

m=C2s·C1modq

同态加法

同态加法

对于两个密文 C1=(C11,C12) 和 C2=(C21,C22),计算:

C1+C2=(C11+C21,C12+C22)modq

同态数乘

同态数乘

对于一个密文 C=(C1,C2) 和一个标量 k,计算:

kC=(k·C1,k·C2)modq

代码示例:

import tenseal as ts



# 生成密钥对

def generate_keys():

    # 创建 CKKS 上下文

    context = ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 60])

    # 生成密钥

    context.generate_galois_keys()

    context.global_scale = 2 ** 40

    return context



# 加密消息

def encrypt(context, message):

    # 创建张量

    tensor = ts.plain_tensor(message)

    # 加密张量

    encrypted_tensor = ts.ckks_tensor(context, tensor)

    return encrypted_tensor



# 解密消息

def decrypt(context, encrypted_tensor):

    # 解密张量

    decrypted_tensor = encrypted_tensor.decrypt()

    return decrypted_tensor



# 同态加法

def homomorphic_add(encrypted_tensor1, encrypted_tensor2):

    return encrypted_tensor1 + encrypted_tensor2



# 同态数乘

def homomorphic_mul(encrypted_tensor, scalar):

    return encrypted_tensor * scalar



# 主程序

if __name__ == "__main__":

    # 生成密钥对

    context = generate_keys()

    print("密钥生成完成")



    # 加密消息

    message1 = [1, 2, 3, 4]

    message2 = [5, 6, 7, 8]

    encrypted_tensor1 = encrypt(context, message1)

    encrypted_tensor2 = encrypt(context, message2)

    print("消息加密完成")



    # 同态加法

    encrypted_sum = homomorphic_add(encrypted_tensor1, encrypted_tensor2)

    decrypted_sum = decrypt(context, encrypted_sum)

    print("同态加法结果:", decrypted_sum.tolist())



    # 同态数乘

    scalar = 3

    encrypted_mul = homomorphic_mul(encrypted_tensor1, scalar)

    decrypted_mul = decrypt(context, encrypted_mul)

print("同态数乘结果:", decrypted_mul.tolist())

运行结果:

这段代码实现了一个基于 CKKS 同态加密方案的示例,支持对密文的加法和数乘操作。通过生成密钥对、加密消息、解密消息、同态加法和同态数乘,可以实现对密文的高效计算。


 本篇简单介绍了随着同态加密的发展而产生的几种同态加密算法,同态加密的发展是向着高效化、功能化的方向前进的,其应用前景十分广阔。通过对同态加密的了解,我们一定能够实现更高效的技术。

本篇借鉴来源于Kimi 是一个有着超大“内存”的智能助手,可以一口气读完二十万字的小说,还会上网冲浪,快来跟他聊聊吧

同态加密技术概览-CSDN博客 

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

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

相关文章

aws(学习笔记第二十六课) 使用AWS Elastic Beanstalk

aws(学习笔记第二十六课) 使用aws Elastic Beanstalk 学习内容&#xff1a; AWS Elastic Beanstalk整体架构AWS Elastic Beanstalk的hands onAWS Elastic Beanstalk部署node.js程序包练习使用AWS Elastic Beanstalk的ebcli 1. AWS Elastic Beanstalk整体架构 官方的guide AWS…

FastAPI + GraphQL + SQLAlchemy 实现博客系统

本文将详细介绍如何使用 FastAPI、GraphQL&#xff08;Strawberry&#xff09;和 SQLAlchemy 实现一个带有认证功能的博客系统。 技术栈 FastAPI&#xff1a;高性能的 Python Web 框架Strawberry&#xff1a;Python GraphQL 库SQLAlchemy&#xff1a;Python ORM 框架JWT&…

C语言连接Mysql

目录 C语言连接Mysql下载 mysql 开发库 方法介绍mysql_init()mysql_real_connect()mysql_query()mysql_store_result()mysql_num_fields()mysql_fetch_fields()mysql_fetch_row()mysql_free_result()mysql_close() 完整代码 C语言连接Mysql 下载 mysql 开发库 方法一&#xf…

嵌入式知识点总结 Linux驱动 (二)-uboot bootloader

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.什么是bootloader&#xff1f; 2.Bootloader的两个阶段 3.uboot启动过程中做了哪些事&#xff1f; 4.uboot和内核kernel如何完成参数传递&#xff1f; 5.为什么要给内核传递…

JVM对象分配内存如何保证线程安全?

大家好&#xff0c;我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全?】面试题。希望对大家有帮助&#xff1b; JVM对象分配内存如何保证线程安全? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中&#xff0c;对象的内存分配是通过堆内存进行的。…

利用飞书机器人进行 - ArXiv自动化检索推荐

相关作者的Github仓库 ArXivToday-Lark 使用教程 Step1 新建机器人 根据飞书官方机器人使用手册&#xff0c;新建自定义机器人&#xff0c;并记录好webhook地址&#xff0c;后续将在配置文件中更新该地址。 可以先完成到后续步骤之前&#xff0c;后续的步骤与安全相关&…

OpenCV:在图像中添加噪声(瑞利、伽马、脉冲、泊松)

目录 简述 1. 瑞利噪声 2. 伽马噪声 3. 脉冲噪声 4. 泊松噪声 总结 相关阅读 OpenCV&#xff1a;在图像中添加高斯噪声、胡椒噪声-CSDN博客 OpenCV&#xff1a;高通滤波之索贝尔、沙尔和拉普拉斯-CSDN博客 OpenCV&#xff1a;图像处理中的低通滤波-CSDN博客 OpenCV&…

github制作静态网页

打开gihub并新建仓库 命名仓库&#xff1a;xxx.github.io 点击create repository进行创建 点击蓝色字体“creating a new file”创建文件 文件命名为index.html, 并编写html 右上角提交 找到setttings/pages&#xff0c;修改路径&#xff0c;点击保存&#xff0c;等…

从 SAP 功能顾问到解决方案架构师:破茧成蝶之路

目录 行业瞭望&#xff1a;架构师崭露头角 现状剖析&#xff1a;功能顾问的局限与机遇 能力跃迁&#xff1a;转型的核心要素 &#xff08;一&#xff09;专业深度的掘进 &#xff08;二&#xff09;集成能力的拓展 &#xff08;三&#xff09;知识广度的延伸 &#xff0…

unity学习23:场景scene相关,场景信息,场景跳转

目录 1 默认场景和Assets里的场景 1.1 scene的作用 1.2 scene作为project的入口 1.3 默认场景 2 场景scene相关 2.1 创建scene 2.2 切换场景 2.3 build中的场景&#xff0c;在构建中包含的场景 &#xff08;否则会认为是失效的Scene&#xff09; 2.4 Scenes in Bui…

36、【OS】【Nuttx】OSTest分析(2):环境变量测试

背景 2025.1.29 蛇年快乐&#xff01; 接之前wiki 35、【OS】【Nuttx】OSTest分析&#xff08;1&#xff09;&#xff1a;stdio测试&#xff08;五&#xff09; 已经分析完了第一个测试项&#xff0c;输入输出端口测试&#xff0c;接下来分析下环境变量测试&#xff0c;也比较…

使用Ollama本地部署DeepSeek R1

前言 DeepSeek是一款开源的智能搜索引擎&#xff0c;能够通过深度学习技术提高搜索的智能化水平。如果你正在寻找一种方式来将DeepSeek部署在本地环境中&#xff0c;Ollama是一个非常方便的工具&#xff0c;它允许你在本地快速部署并管理各种基于AI的模型。 在本篇博客中&…

libOnvif通过组播不能发现相机

使用libOnvif库OnvifDiscoveryClient类&#xff0c; auto discovery new OnvifDiscoveryClient(QUrl(“soap.udp://239.255.255.250:3702”), cb.Build()); 会有错误&#xff1a; end of file or no input: message transfer interrupted or timed out(30 sec max recv delay)…

Visual Studio使用GitHub Copilot提高.NET开发工作效率

GitHub Copilot介绍 GitHub Copilot 是一款 AI 编码助手&#xff0c;可帮助你更快、更省力地编写代码&#xff0c;从而将更多精力集中在问题解决和协作上。 GitHub Copilot Free包含哪些功能&#xff1f; 每月 2000 代码补全&#xff0c;帮助开发者快速完成代码编写。 每月 …

HTB:Forest[WriteUP]

连接至HTB服务器并启动靶机 分配IP&#xff1a;10.10.16.21 靶机IP&#xff1a;10.10.10.161 靶机Domain&#xff1a;forest.htb 目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端…

项目集成GateWay

文章目录 1.环境搭建1.创建sunrays-common-cloud-gateway-starter模块2.目录结构3.自动配置1.GateWayAutoConfiguration.java2.spring.factories 3.pom.xml4.注意&#xff1a;GateWay不能跟Web一起引入&#xff01; 1.环境搭建 1.创建sunrays-common-cloud-gateway-starter模块…

STM32 PWM驱动直流电机

接线图&#xff1a; 代码配置&#xff1a; 根据驱动舵机的代码来写&#xff0c;与舵机不同的是&#xff0c;这次的引脚接到了PA2上&#xff0c;所以需要改一下引脚以及改为OC3通道。 另外还需在配置两个GPIO引脚&#xff0c;来控制电机的旋转方向&#xff0c;这里连接到了PA4与…

强大到工业层面的软件

电脑数据删不干净&#xff0c;简直是一种让人抓狂的折磨&#xff01;明明已经把文件扔进了回收站&#xff0c;清空了&#xff0c;可那些残留的数据就像牛皮癣一样&#xff0c;怎么也除不掉。这种烦恼简直无处不在&#xff0c;让人从头到脚都感到无比烦躁。 首先&#xff0c;心…

一分钟搭建promehteus+grafana+alertmanager监控平台

为什么要自己搭建一个监控平台 平时进行后端开发&#xff0c;特别是微服务的后端可开发&#xff0c;一定少不了对接监控平台&#xff0c;但是平时进行一些小功能的测试又没有必要每次都手动安装那么多软件进行一个小功能的测试&#xff0c;这里我使用docker-compose搭建了一个…

记一次STM32编译生成BIN文件过大的问题(基于STM32CubeIDE)

文章目录 问题描述解决方法更多拓展 问题描述 最近在一个项目中使用了 STM32H743 单片机&#xff08;基于 STM32CubeIDE GCC 开发&#xff09;&#xff0c;它的内存分为了 DTCMRAM RAM_D1 RAM_D2 …等很多部分。其中 DTCM 的速度是比通常的内存要快的&#xff0c;缺点是不支持…