ECC密码与RSA

news2024/11/22 21:17:05

一、ECC密码(椭圆曲线密码)

     1.基本知识

              定义:

       ECC 全称为椭圆曲线加密,EllipseCurve Cryptography,是一种基于椭圆曲线数学的公钥密码。与传统的基于大质数因子分解困难性的加密方法不同,ECC 依赖于解决椭圆曲线离散对数问题的困难性。它的优势主要在于相对于其它方法,它可以在使用较短密钥长度的同时保持相同的密码强度。

      目前椭圆曲线主要采用的有限域有

  • 以素数为模的整数域 GF(p),通常在通用处理器上更为有效。
  • 特征为 2 的伽罗华域 GF(2^m),可以设计专门的硬件。

     

椭圆曲线的确定

描述一条Fp上的椭圆曲线,常用到六个参数:
T=(p,a,b,G,n,h)。
p 、a 、b 用来确定一条椭圆曲线,
G为基点,
n为点G的阶,
h 是椭圆曲线上所有点的个数m与n相除的整数部分。
这几个参数取值的选择,直接影响了加密的安全性。参数值一般要求满足以下几个条件:

p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;
p≠n×h;
pt≠1 (mod n),1≤t<20;
4a3 + 27b2 ≠ 0 (mod p);
n 为素数;
h≤4

    

公钥


    椭圆曲线的公钥实际上是曲线上的一个点,可以用坐标点(x,y)表示,通常是将x和y的值分别转换成字符串来存储和传输,如下是一个公钥的例子
57E1174B773A91E743BC719C9C8B24C8F25096411744C0EB09C13AAD4073D547
BBD7DA078002F7C84441B196A8B8532E0046BA8ED71DED0B9E2BEACA31F1EE9A
其中57E1174B773A91E743BC719C9C8B24C8F25096411744C0EB09C13AAD4073D547为公钥的x点坐标,BBD7DA078002F7C84441B196A8B8532E0046BA8ED71DED0B9E2BEACA31F1EE9A为公钥的y点坐标,实际在计算的时候,需要把这些字符串中的元素按照其字面的值转为对应的十六进制,如:0x57,0xE1…
上述是公钥的非压缩表示,通常需要还在坐标点前加上一个字节0x04用于表示使用非压缩的方式,即0457E1174B773A91E743BC719C9C8B24C8F25096411744C0EB09C13AAD4073D547BBD7DA078002F7C84441B196A8B8532E0046BA8ED71DED0B9E2BEACA31F1EE9A。
还有一种压缩的表示方式。根据椭圆曲线方程,我们只需要知道 x 坐标,就可以通过方程计算出 y 坐标,这样就不用同时保存x,y的值,减少了存储和带宽。但是如果只知道x,带入方程会求出两个y,一正一负,对应两个不同的点,所以还必须有一个标志来区别实际使用的是哪个。所以通常采用下面的约定,具体格式为:

前缀02 + x (当y为偶数)
前缀03 + x (当y为奇数)
可以仅用一个坐标长度+1bit表示整个公钥,比如:
02f54ba86dc1ccb5bed0224d23f01ed87e4a443c47fc690d7797a13d41d2340e1a

私钥


私钥是一个随机数,通常是把其十六进制下的数据当作字符串保存(和公钥的保存形式一样),如下:
0A7ECE7EFCA5C5A186FF7340125E2E1F1754D8F27922573F66ABA43D8DA3ECDE
这个私钥其实就是0x0A,0x7E,0xCE…

     椭圆曲线方程

这是在有限域GF(p)上,p为一个很多的素数

椭圆曲线上的运算:
     

      加法:如果椭圆曲线上的三个点位于同一直线上,那么它们的和为O,

O 为加法的单位元,对于椭圆曲线上的任意一点p,有p+ O =p;

椭圆曲线上的一点p=(Xp,Yp),它的加法的逆元-p=(-Xp,-Yp)。这两个点可以用一条垂直的线连起来p+(-p)=p-p=O;

     

密钥生成

    用户 A 先选择一条椭圆曲线Eq(a,b) ,然后选择其上的一个生成元 G,假设其阶为 n,之后再选择一个正整数na 作为密钥,计算Pa=naG

其中,Eq(a,b),q,G都会被公开。公钥为Pa,私钥为 $n_a $。

加密过程

 官方说法,用户 B 在向用户 A 发送消息 m,这里假设消息 m 已经被编码为椭圆曲线上的点,其加密步骤如下

  1. 查询用户 A 的公钥Eq(a,b),q,Pa,
  2. 在 (1,q-1) 的区间内选择随机数 k 。
  3. 根据 A 的公钥计算点(x1,y1)=kG。
  4. 计算点(x2,y2)=kPa
  5. 如果为 O,则从第二步重新开始。
  6. 计算C=m+(x2,y2)
  7. 将((x1,y1),C)
  8. 发送给 A。

解密过程

  1. 利用私钥计算点na(x1,y1)=nakG=kPa=(x2,y2)。
  2. 计算消息m=C−(x2,y2)。

二、RSA密码与ECC密码的区别

      RSA:RSA加密算法是应用较早的算法之一,它在密码学领域具有奠基性地位。相较于后来出现的ECC算法,RSA在兼容性和普遍适用性上表现出更强的优势,在传统的数字签名场景中广泛部署。

       ECC:在提供相同安全级别的情况下,ECC所需的密钥长度更短,有效降低了计算资源消耗和存储需求,提高了加密与解密的速度。尽管RSA目前在兼容性和普遍性上仍占有优势,但随着硬件性能的发展以及对效率要求的提升,ECC加密算法因其高效特性而逐渐受到更多关注并得到广泛应用。

三、ECC与SM2

      SM2于2016年成为中国国家密码标准,在商用密码体系中,SM2主要用于替换RSA加密算法。

四、例题

          

[watevrCTF 2019]ECC-RSA

我们可以知道了是RSA和ECC的共同解密

from fastecdsa.curve import P521 as Curve
from fastecdsa.point import Point      #椭圆曲线的操作

from Crypto.Util.number import bytes_to_long, isPrime   #数字转换和素数检测

from os import urandom
from random import getrandbits      #用于生成随机数



def gen_rsa_primes(G):
	urand = bytes_to_long(urandom(521//8))
	while True:
		s = getrandbits(521) ^ urand        #生成随机数

#坐标轴

		Q = s*G
		if isPrime(Q.x) and isPrime(Q.y):
			print("ECC Private key:", hex(s))
			print("RSA primes:", hex(Q.x), hex(Q.y))
			print("Modulo:", hex(Q.x * Q.y))
			return (Q.x, Q.y)




         #这里的p,q相当于ECC中的x,y


flag = int.from_bytes(input(), byteorder="big")

ecc_p = Curve.p
a = Curve.a
b = Curve.b

Gx = Curve.gx
Gy = Curve.gy
G = Point(Gx, Gy, curve=Curve)


e = 0x10001
p, q = gen_rsa_primes(G)
n = p*q


file_out = open("downloads/ecc-rsa.txt", "w")

file_out.write("ECC Curve Prime: " + hex(ecc_p) + "\n")
file_out.write("Curve a: " + hex(a) + "\n")
file_out.write("Curve b: " + hex(b) + "\n")
file_out.write("Gx: " + hex(Gx) + "\n")
file_out.write("Gy: " + hex(Gy) + "\n")

file_out.write("e: " + hex(e) + "\n")
file_out.write("p * q: " + hex(n) + "\n")

c = pow(flag, e, n)
file_out.write("ciphertext: " + hex(c) + "\n")

椭圆曲线点的坐标不一定是素数

      满足了椭圆方程  :    y^2=x^3+a*x+b;      p,q相当于里面的x,y

n=p*q

   化成了,q^2=p^3+a*p+b,

继续化简得到了:
        n*n=p^5+a*p^3+b*p^2

那么就开是解题了:
      在Sage:

a=-0x3      #十六进制的-3

b=0x51953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00

n=0x118aaa1add80bdd0a1788b375e6b04426c50bb3f9cae0b173b382e3723fc858ce7932fb499cd92f5f675d4a2b05d2c575fc685f6cf08a490d6c6a8a6741e8be4572adfcba233da791ccc0aee033677b72788d57004a776909f6d699a0164af514728431b5aed704b289719f09d591f5c1f9d2ed36a58448a9d57567bd232702e9b28f

p0=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff      #定义了一个非常大的素数

R.<x>=Zmod(p0)[]      #创建一个模p0的整数环上的多项式环R[x] 

f=x**5+a*x**3+b*x**2-n*n

f.roots()       #计算多项式在模p0下的根

最终的p:

4573744216059593260686660411936793507327994800883645562370166075007970317346237399760397301505506131100113886281839847419425482918932436139080837246914736557

接下来就是RSA的常规计算:
 

from gmpy2 import*
from libnum import*
n = 0x118aaa1add80bdd0a1788b375e6b04426c50bb3f9cae0b173b382e3723fc858ce7932fb499cd92f5f675d4a2b05d2c575fc685f6cf08a490d6c6a8a6741e8be4572adfcba233da791ccc0aee033677b72788d57004a776909f6d699a0164af514728431b5aed704b289719f09d591f5c1f9d2ed36a58448a9d57567bd232702e9b28f
c = 0x3862c872480bdd067c0c68cfee4527a063166620c97cca4c99baff6eb0cf5d42421b8f8d8300df5f8c7663adb5d21b47c8cb4ca5aab892006d7d44a1c5b5f5242d88c6e325064adf9b969c7dfc52a034495fe67b5424e1678ca4332d59225855b7a9cb42db2b1db95a90ab6834395397e305078c5baff78c4b7252d7966365afed9e

p = 4573744216059593260686660411936793507327994800883645562370166075007970317346237399760397301505506131100113886281839847419425482918932436139080837246914736557
e = 0x10001
q  = n//p

phi = (p-1)*(q-1)
d = invert(e,phi)
m = pow(c,d,n)
print(n2s(m))      

#使用 libnum 的 n2s 函数将解密后的整数 m 转换为字符串并打印出来。
这假设 m 是一个以某种方式编码(如ASCII或UTF-8)的字符串的数值表示

    这里出现了问题:

            

      报错说明了经过,m=pow(c,d,n)后面它的数据类型已经变为了gmpy2.mpz,然而libnum

期待·的数据类型是Python的原生整数(int型),一般直接进行转换就可以了

那么加上:

# 将 m 转换为 Python 原生整数
m_int = int(m)

   

   最终就可以得到了flag

[第五空间 2021]ecc

这个题目看起来比较简单,主要分为三个部分来解答,

第一部分比较简单,

  


from Crypto.Util.number import *
p = 146808027458411567
a = 46056180
b = 2316783294673
E = EllipticCurve(GF(p),(a,b))
P = E(119851377153561800,50725039619018388)
Q = E(22306318711744209,111808951703508717)

num1 =  discrete_log(Q,P,operation = '+')

第二部分:
 


p = 1256438680873352167711863680253958927079458741172412327087203
a = 377999945830334462584412960368612
b = 604811648267717218711247799143415167229480
E = EllipticCurve(GF(p),[a,b])
P = E(550637390822762334900354060650869238926454800955557622817950,700751312208881169841494663466728684704743091638451132521079)
Q = E(1152079922659509908913443110457333432642379532625238229329830,819973744403969324837069647827669815566569448190043645544592) 
# Q = k * P
n = E.order()

def Pohlig_Hellman(n,P,Q):
    factors, exponents = zip(*factor(n))
    primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-1]
    print(primes)
    dlogs = []
    for fac in primes:
        t = int(int(P.order()) // int(fac))
        dlog = discrete_log(t*Q,t*P,operation="+")
        dlogs += [dlog]
        print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
    num2 = crt(dlogs,primes)
    return num2

num2 = Pohlig_Hellman(n,P,Q)

第三部分:
 


p = 0xd3ceec4c84af8fa5f3e9af91e00cabacaaaecec3da619400e29a25abececfdc9bd678e2708a58acb1bd15370acc39c596807dab6229dca11fd3a217510258d1b
A = 0x95fc77eb3119991a0022168c83eee7178e6c3eeaf75e0fdf1853b8ef4cb97a9058c271ee193b8b27938a07052f918c35eccb027b0b168b4e2566b247b91dc07
B = 0x926b0e42376d112ca971569a8d3b3eda12172dfb4929aea13da7f10fb81f3b96bf1e28b4a396a1fcf38d80b463582e45d06a548e0dc0d567fc668bd119c346b2
E = EllipticCurve(GF(p),[A,B])
P = E(10121571443191913072732572831490534620810835306892634555532657696255506898960536955568544782337611042739846570602400973952350443413585203452769205144937861,8425218582467077730409837945083571362745388328043930511865174847436798990397124804357982565055918658197831123970115905304092351218676660067914209199149610)
Q = E(964864009142237137341389653756165935542611153576641370639729304570649749004810980672415306977194223081235401355646820597987366171212332294914445469010927,5162185780511783278449342529269970453734248460302908455520831950343371147566682530583160574217543701164101226640565768860451999819324219344705421407572537)

def SmartAttack(P,Q,p):
    E = P.curve()
    Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])

    P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
    for P_Qp in P_Qps:
        if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
            break

    Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
    for Q_Qp in Q_Qps:
        if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
            break

    p_times_P = p*P_Qp
    p_times_Q = p*Q_Qp

    x_P,y_P = p_times_P.xy()
    x_Q,y_Q = p_times_Q.xy()

    phi_P = -(x_P/y_P)
    phi_Q = -(x_Q/y_Q)
    k = phi_Q/phi_P
    return ZZ(k)

num3 = SmartAttack(P, Q, p)

拼接起来,最终得到了:

print(long_to_bytes(num1) + long_to_bytes(num2) + long_to_bytes(num3))

# NSSCTF{025ab3d9-2521-4a81-9957-8c3381622434}

仔细研究一下大神的脚本,

     里面涉及了pohlig_hellman算法,接下来学习一下,Pohlig-Hellman算法主要是去破解这个群的阶为光滑数的离散对数,所以使用这个算法的前提是椭圆曲线所在的阶的是不是光滑数

      光滑数,如果一个数的所有质因数都小于等于B,那么我们称这个数为B-光滑数(B-Smooth Integer)

    

例如:2×32×53×7=15750因为15750的所有质因数为{3,5,7},
其中7为质因数最大的值,所以该15750是一个7−光滑数需要注意的是,
一个数如果被称之为B−光滑数,那么这个B不一定是这个数的质因数例如上面的式子,
他也可以叫做8−光滑数、13−光滑数等。

在sagemath上,实现该算法,

def PohligHellman(p,a,b,P,G):
    E = EllipticCurve(GF(p),[a,b]) 
    n = E.order()
 factors = factor(n)
    print(factors)
    result = []
    factors = [4 ,3 , 1170811] #  
    for f1  in factors:
       t = n //f1
       res = discrete_log(t*P,t*G,operation='+')
       result  += [res]
    print(result)
    k = crt(result,factors)
    return k


第三部分里面还使用了Smart' Attack

    

    异常子群

      异常子群是椭圆曲线上哪些整个子群的阶,是有限域的模数p的整倍数的点的集合。

因为异常曲线的阶就等于p,所以异常曲线本身就是一个异常子群。

    Smart’s 攻击

          异常曲线可以被特定的攻击方式所破解,其中一个著名的是所谓的Smart’s 攻击。

Smart’s 攻击利用了椭圆曲线上的点可以通过一个同态映射(有限域同态映射)映射到有限域的模数p的加法群上去。

p = 
A = 
B = 
E = EllipticCurve(GF(p),[A,B])
P = E(,)
Q = E(,)
def SmartAttack(P,Q,p):
    E = P.curve()
    Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])

    P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
    for P_Qp in P_Qps:
        if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
            break

    Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
    for Q_Qp in Q_Qps:
        if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
            break

    p_times_P = p*P_Qp
    p_times_Q = p*Q_Qp

    x_P,y_P = p_times_P.xy()
    x_Q,y_Q = p_times_Q.xy()

    phi_P = -(x_P/y_P)
    phi_Q = -(x_Q/y_Q)
    k = phi_Q/phi_P
    return ZZ(k)

r = SmartAttack(P, Q, p)
print(r)


    接下来就来看看其他的,

       超奇异椭圆曲线(MOV攻击)

          对于有限域Fq​上的椭圆曲线E,如果Fq​的特性p整除t,那么称这个椭圆曲线为超奇异椭圆曲线。假设这个域为素数域也就是说q为素数,那么他的特性p就是q。

      假设E(Fq​)为n,那么t=q+1−n。也就是说:t=0  (modp)q+1−n=0  (modq)满足这个式子,它就是超奇异椭圆曲线。

sagemath脚本,

    

### MOV攻击脚本    取之https://zhuanlan.zhihu.com/p/421541257
# 初始化椭圆曲线的参数A2, B2, P2x, P2y, Q2x, Q2y以及质数p2
A2 =    			#需要填写     
B2 =      			#需要填写 
P2x =                #需要填写 
P2y =               #需要填写 
Q2x =                 #需要填写 
Q2y =                    #需要填写 

p2 =                  #需要填写 

k = 2                # 嵌入度,需要填写   嵌入度k是满足k>=2,且阶n整除p^k−1的最小k。 
# 如果n= q+1 的情况下,当k等于2 ,那么p^2 - 1 =(p-1)*(p+1),所以n一定整除p^k-1,所以k一般为2。

_P2 = (P2x,P2y)      # 定义点P2的坐标
_Q2 = (Q2x,Q2y)      # 定义点Q2的坐标

# Pohlig Hellman算法的注释示例
# d2p = P2p.discrete_log(Q2p) # 离散对数的示例值
# d2p = 64863796476861801236088764479

# 定义有限域F1
F1 = GF(p2)
# 在有限域F1上创建椭圆曲线E1
E1 = EllipticCurve(F1, [0, 0, 0, A2, B2])
# 定义扩展有限域F2
F2 = GF(p2^k)
# 创建从F1到F2的同态映射phi
phi = Hom(F1, F2)(F1.gen().minpoly().roots(F2)[0][0])
# 在扩展有限域F2上创建椭圆曲线E2
E2 = EllipticCurve(F2 ,[0, 0, 0, A2, B2])

# 计算椭圆曲线E1的阶
n = E1.order()

# 定义E1上的点P1和R1
P1 = E1(_P2)
R1 = E1(_Q2)

# 将点P1和R1映射到扩展椭圆曲线E2上的点P2和R2
P2 = E2(phi(P1.xy()[0]), phi(P1.xy()[1]))
R2 = E2(phi(R1.xy()[0]), phi(R1.xy()[1]))

# 计算系数
cn1 = p2 + 1
coeff = ZZ(cn1 / n)

# 在椭圆曲线E2上生成一个随机点Q
Q = coeff * E2.random_point()
# 计算点P2和Q的Weil配对alpha
alpha = P2.weil_pairing(Q, n)
# 计算点R2和Q的Weil配对beta
beta = R2.weil_pairing(Q, n)
# 计算离散对数d
d = beta.log(alpha)

# 打印离散对数d
print(d)

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

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

相关文章

@antv/x6 要求不显示水平滚动条,并且如果水平方向上显示不全的节点,则要求自动显示全部节点,垂直方向可以出现滚动条来滚动显示所有的节点。

1、要求一共有二个&#xff1a; 要求一&#xff1a;水平滚动条不显示。之前的文章中就已经发表过&#xff0c;可以用Scroller的className来处理。要求二&#xff1a;水平方向上显示全部节点&#xff0c;如果有显示不全的节点&#xff08;即看不到的节点&#xff09;要求能够显示…

asp.net实验:数据库写入不成功

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

国庆节微信头像怎么制作?制作国庆国旗节日头像的4个方法

国庆将至&#xff0c;不少朋友的微信头像都换成了渐变红旗头像&#xff0c;是不是觉得超酷呢&#xff1f;如果你也想拥有这样的头像&#xff0c;那就跟着这篇文章一起操作吧&#xff01; 国庆节前夕&#xff0c;让我们先来了解一下如何制作渐变红旗头像。首先&#xff0c;我们需…

基于Python的Flask框架实战全流程从新建到部署【2】

本项目是基于win10系统运行以及操作的&#xff0c;部署在win7系统。 Flask 是一个轻量级的可定制框架&#xff0c;使用Python语言编写&#xff0c;较其他同类型框架更为灵活、轻便、安全且容易上手。 本文是flask框架实战项目&#xff0c;从新建、运行、测试、部署项目…

C/C++的内存分布、动态内存管理等的介绍

文章目录 前言一、C/C的内存分布二、C/C动态内存管理总结 前言 C/C的内存分布、动态内存管理等的介绍 一、C/C的内存分布 因为程序在运行过程中需要存储一些不同的数据&#xff0c;所以需要对内存空间进行分类 二、C/C动态内存管理 C语言动态内存管理是malloc / calloc / rea…

光降解水凝胶:三色光响应

大家好&#xff0c;今天来了解一种三色可见光波长选择性光降解水凝胶生物材料——《Tricolor visible wavelength-selective photodegradable hydrogel biomaterials》发表于《Nature Communications》&#xff0c;其交联剂Rubiq、Rubp和oNB对低能可见光&#xff08;400 - 617n…

洛科威岩棉板重塑屋面应用,以多重优势成为“优选材料”

屋面作为建筑物的“外衣”&#xff0c;不仅承载着遮风挡雨的基本功能&#xff0c;更在保温隔热、防火安全、防潮隔音等方面发挥着举足轻重的作用。然而&#xff0c;面对极端气候、自然灾害以及日益严苛的环保标准&#xff0c;传统屋面材料逐渐暴露出其局限性&#xff0c;保温效…

JVM垃圾判定算法

垃圾收集技术是Java的一堵高墙。Java堆内存中存放着几乎所有的对象实例&#xff0c;垃圾收集器在对堆内存进行回收前&#xff0c;第一件事情就是要确定这些对象中哪些还存活&#xff0c;哪些已经死去&#xff08;即不可能再被任何途径使用的对象&#xff09;。也就是判定垃圾。…

STM32 使用8720 通过LWIP发送数据

一、硬件IOC 1、GPIO 2、NVIC 3、SYS 4、RCC 5、ETH 6、USART 7、LWIP 二、软件函数 1、Main /* USER CODE BEGIN Includes */ #include "ytcesys.h" /* USER CODE END Includes *//* USER CODE BEGIN 2 */ ethreset(); MX_LWIP_Init(); OPEN_USART1…

chunqiude

CVE-2022-28512 靶标介绍&#xff1a; Fantastic Blog (CMS)是一个绝对出色的博客/文章网络内容管理系统。它使您可以轻松地管理您的网站或博客&#xff0c;它为您提供了广泛的功能来定制您的博客以满足您的需求。它具有强大的功能&#xff0c;您无需接触任何代码即可启动并运…

【Java开发】Maven安装配置详细教程

原创文章&#xff0c;不得转载。 文章目录 产生背景用途安装配置本地仓库配置镜像 产生背景 在Java应用程序开发中&#xff0c;随着项目规模的不断扩大和复杂性增加&#xff0c;项目依赖的库、插件和配置文件也变得愈加复杂。传统的项目构建工具&#xff08;如Ant&#xff09;…

简单选择排序例题

从上面题目看出&#xff0c;如果排序方法可保证在排序前后排序码相同的相对位置不变&#xff0c;也就是四个选项里&#xff0c;21和21*之间不会交换 简单选择排序方法是&#xff1a;首先在所有记录中找到排序吗最小的记录&#xff0c;把它与第一个记录交换&#xff0c;然后在其…

EXO:模型最终验证的地方;infer_tensor;step;MLXDynamicShardInferenceEngine

目录 EXO:模型最终验证的地方 EXO:infer_tensor EXO:step MXNet的 mx.array 类型是什么 NDArray优化了什么 1. 异步计算和内存优化 2. 高效的数学和线性代数运算 3. 稀疏数据支持 4. 自动化求导 举例说明 EXO:模型最终验证的地方 EXO:infer_tensor 这段代码定…

【科技前沿】用深度强化学习优化电网,让电力调度更聪明!

Hey小伙伴们&#xff0c;今天我要跟大家分享一个超级酷炫的技术应用——深度强化学习在电网优化中的典型案例&#xff01;如果你对机器学习感兴趣&#xff0c;或是正寻找如何用AI技术解决实际问题的方法&#xff0c;这篇分享绝对不容错过&#xff01;&#x1f469;‍&#x1f4…

Pyqt5高级技巧2:Tab顺序、伙伴快捷键、各类常用控件的事件、可移动的卡片式布局(含基础Demo)

目录 一、编辑Tab顺序 二、编辑伙伴 三、设置快捷键&#xff08;仅MainWindow可用&#xff09; 四、信号槽 【基本介绍】 【常用信号槽】控件对窗体&#xff08;拖地&#xff09; 【常用信号槽】控件对控件 【自定义信号槽】步骤 五、设计文件的转化 六、GUI的运行 1…

【研发日记】吃透新能源充电协议(一)——GB27930实例报文解析

文章目录 前言 背景介绍 充电协议框架 充电握手阶段 充电准备阶段 充电传输阶段 充电结束阶段 错误处理阶段 总结 参考资料 前言 近期在一个嵌入式开发项目中&#xff0c;用到了新能源充电协议&#xff0c;期间在翻阅各种资料文件时&#xff0c;一些地方还是容易理解…

包装和类练习 Stack的使用

目录 1.最小栈 2.有效的括号 3.栈的压入、弹出序列 4.逆波兰表达式求值 5.链栈与顺序栈相比&#xff0c;比较明显的优点是&#xff08; &#xff09; 1.最小栈 2.有效的括号 class Solution {public boolean isValid(String s) {Stack<Character> st new Stack<&g…

I/O方式

目录 一、程序查询方式 1.程序查询方式的特点 2.程序查询方式可分类 ①独占查询 ②定时查询 二、中断方式 1.中断I/O流程 2.例题 三、DMA方式 1.DMA控制器 2.特点 3. DMA的传送方式 ①停止CPU ②周期挪用 ③DMA和CPU交替访存 4.传送流程 ①预处理 ②数据传…

AIGC时代算法工程师的面试秘籍(第二十一式2024.8.19-9.1) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试经验&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

海外云服务器安装 JDK8 (Ubuntu 18.04 记录篇)

本文首发于 秋码记录 曾几何时&#xff0c;我可是国内云厂商的忠实用户啊。 而今&#xff0c;却不再为云服务器&#xff08;尤指国内云厂商&#xff09;续费了&#xff0c;作为我的个人网站 秋码记录 选择了托管在 gitlab.com Pages服务上。 国内云厂商对新老用户持有两种截…