*本文原作者:苗苗Xi、怀,本文属于FreeBuf原创奖励计划,未经许可禁止转载。
0×00前言
椭圆曲线加密算法是一种基于椭圆曲线数学的公钥加密算法。随着大整数分解方法的进步和完善,计算机计算速度的提高和网络的发展,RSA的利用率越来越高。其密钥的长度一直受到保守的批评,于是新算法ECC逐渐走上了加密算法的大舞台,其利用率和重要性也在逐年提高。所以今天,我们将通过这篇文章介绍椭圆曲线加密算法的数学基础。
0×01正文数学基础1.1椭圆曲线方程
椭圆曲线是指一个齐次方程:
数形结合确定的平面曲线,其中系数AI 定义在某个域中,可以是有理数域、无理数域、复数域、有限域GF,这些域在ECC密码系统中都是在有限域中定义的。
一个称为无穷远的特殊点和椭圆上的所有点一起构成一个集合,通过定义的加法运算构成阿贝尔群
曲线上的每一点都必须是非奇异的,所谓“非奇异”或“光滑”,就是指数学上曲线上的任意一点都有切线。
等式1:
在这个等数中,我们可以看到,当我们知道M和P的时候很容易找到点Q,但是当我们只知道Q和P的时候就很难找到M,这个问题在离散对数问题中叫做椭圆曲线上的点群。
我们所学的椭圆曲线密码系统就是利用上述难题设计的。
椭圆曲线的形状不是椭圆,是因为椭圆曲线的描述方程类似于计算椭圆周长的方程。
数学基础1.2阿贝尔群是什么?在数学中,群是由集合和二元运算组成的代数结构。如果一个集合或操作是一个组!必须满足以下条件
关闭
结合性
单位元
逆元素
并且满足数学中的交换定律定律:
有一个定义是取椭圆中的两点P和Q,使一条直线与椭圆的一个点A相交,使Y轴的一条平行线与另一个点b相交。
这样加法的和也在椭圆上,也满足交换定律和联想定律。
由上可知,由于Abe群是所有点和特殊点的和,如果有m个相同的点p加在一起,则写成mP,得到方程1:
数学基础1.3椭圆曲线中的有限域
从上面的介绍中,我们对椭圆曲线有了一定的了解。但是椭圆是连续的,点与点之间似乎没有联系。怎么加密?
给出了有限域Fq的描述及其元素的表示。q是奇数或2的幂。当q是奇素数p时,p >:2^191;当q是2 ^ 2m的幂时,m >: 192,是素数。
素数域Fp:
1)当q为奇素数p时,素数域Fp中的元素使用整数0;1;2;;P1代表。
a)加法单位元素为整数0;
b)乘法单位为整数1;
c)定义域元素的加法是整数的模p加法,即如果a;B∈Fp,那么a+b =mod p;
d)域元素的乘法是整数的模P乘法,即如果A;B∈Fp,那么a.b = mod p。
2)Fp上定义的椭圆曲线方程为:
和
椭圆曲线E定义为:
并满足该等式
其中o是无穷远点。
椭圆曲线E上的点数用#E表示,称为椭圆曲线E的阶数。
如果在椭圆曲线上的一个点p处有一个最小正整数n,从而使次数NP = 0∩,那么n就叫p的阶,如果n不存在,我们说p是无穷的。
事实上,有限域上定义的椭圆曲线上的所有点的阶n是存在的。
0×02加密
为了描述Fp上的椭圆曲线,通常使用六个参数:T=。
用来确定一条椭圆曲线,p是素数域中的点数,a和b是其中的两个大数;
x和y是g基点的坐标,也是两个大数;
n是G点基点的阶数;
以上六个量可以描述一条椭圆曲线,有时我们也用H。
现在我们描述一个使用椭圆曲线加密通信的过程:
1.机器a选择一条椭圆曲线Ep,并将椭圆曲线上的一点作为基点g..
2.机器a选择一个私钥K并生成一个公钥K=kG。
机器a将Ep和k,g点传送给用户B..
4.B机收到信息后,将待传输的明文编码到Ep上的一个点m,生成一个随机整数r。
5、乙机计算
6.机器乙将C1和C2点传送给机器甲..
7.收到信息后,a计算C1-kC2,结果是点m。因为
然后,对m点进行解码就可以得到明文。
在这种加密通信中,如果有偷窥狂h,他只能看到Ep,k,g,C1,C2,但是通过k,g或者r通过C2,g找到k相对比较困难,所以h得不到a和B之间传输的明文信息..
代码实现:ecies.py
导入hashlib
从openssl_wrapper导入openssl
从struct导入包,解包
#1.生成临时电子商务密钥对
#我们在二维码场景中使用短且无专利的EC曲线,即‘secp 160 R1’
PUBKEY = ' 02 c 500146 EC 52 c 4 fdae 22 c 1c 18d 81 b 3679 cf 70397 fdaab 8 f 0014 BAC 0 efaf 80 ce 2 EC 719 ba 1 bcaa 53530 BF 03d 6d 95 '
PRIVKEY = ' 02c 500147 BD 49 a3 ea 78 ba 2d 5a 06920 f 4326 e 693002419685 '
#PUBKEY=PUBKEY.decode
#PRIVKEY=PRIVKEY.decode
def gen_ec_keypair:
#此函数生成电子商务密钥对
尝试:
曲线=OpenSSL.curves
key = OpenSSL。EC_KEY_new_by_curve_name
OpenSSL。EC_KEY_generate_key
_pubkey_x = OpenSSL。BN_new
_pubkey_y = OpenSSL。BN_new
_privkey = OpenSSL。EC_KEY_get0_private_key
_pubkey = OpenSSL。EC_KEY_get0_public_key
_group = OpenSSL。EC_KEY_get0_group
OpenSSL。EC _ POINT _ get _仿射_坐标_GFp
privkey = OpenSSL.malloc)
pubkeyx = OpenSSL.malloc)
publikey y = OpenSSL . malloc)
OpenSSL。BN_bn2bin
privkey = privkey.raw
OpenSSL。BN_bn2bin
pubkeyx = pubkeyx.raw
OpenSSL。BN_bn2bin
pubkeyy = pubkeyy.raw
#self.raw_check_key
full_privkey=pack+装) + privkey
full_pubkey=pack+装) + pubkeyx + pack)+pubceyy
返回full_privkey,full_pubkey
最后:
#释放c指针
OpenSSL。无密钥
OpenSSL。BN_free
OpenSSL。BN_free
def ecdh_key:
#键应该是二进制格式
a_curve=int。编码,16)
b_curve=int。编码,16)
if _ curve!= b_curve:
引发异常
sx=int。编码,16)
sy=int。编码,16)
pub_x,pub_y = b_pubkey,b_pubkey
b_key=OpenSSL。EC _ KEY _ new _ by _ curve _ name
_pub_x=OpenSSL。BN_bin2bn
_pub_y=OpenSSL。BN_bin2bn
_group=OpenSSL。EC_KEY_get0_group
_pubkey=OpenSSL。EC_POINT_new
OpenSSL。EC _ POINT _ set _仿射_坐标_GFp
OpenSSL。EC_KEY_set_public_key
#OpenSSL。EC_KEY_check_key
s=int,16)
priv=a_privkey
a_key=OpenSSL。EC _ KEY _ new _ by _ curve _ name
_privkey=OpenSSL。BN_bin2bn,0)
OpenSSL。EC_KEY_set_private_key
#ECDH
OpenSSL。ECDH_set_method)
ecdh_buf = OpenSSL.malloc#计算的缓冲区大小应与密钥长度相同
ecdh_keylen=OpenSSL。ecdh _计算_密钥
返回ecdh_buf.raw
来自加密。密码导入AES
def encrypt:
ecdp=ecdh_key
shared_key=hashlib.md5。我们的二维码场景需要128位密钥
obj = AES.new
密文= obj.encrypt
QR =。编码
返回qr
def decrypt:
qr=qr.decode
sx=int,16)
sy=int,16)
a_pubkey=qr
密文=qr
ecdh2=ecdh_key
shared_key=hashlib.md5。摘要
obj = AES.new
content = obj.decrypt
返回内容
a = gen _ EC _ keypair#密钥是短暂的,每次都会生成
b = gen _ EC _ keypair#在实际代码中,该密钥对应该来自服务器,客户端只有其公钥
打印“为ECDH密钥交换生成的电子商务对:”
打印'爱丽丝->;Private:'+ a。编码,'公共:'+ a。编码
打印'鲍勃->;Private:' + b。编码,'公共:'+ b。编码
e1= ecdh_key
e2=ecdh_key #e2仅用于服务器代码
打印e1.encode
打印e2.encode
bm=buffer
qr=加密
打印'二维码大小为',len,':',二维码
#导入二维码
#qrcode.make。显示
#服务器执行以下操作:
内容=解密
打印“解密后,内容为”,内容
openssl_wrapper.py
#!/usr/bin/env python
# -*-编码:utf-8 -*-
导入系统
导入ctypes
import ctypes.util
OpenSSL =无
类别密码名称:
def __init__:
自我。_name = name
自我。_指针=指针
自我。_blocksize = blocksize
def __str__:
返回“密码:“+自我”。_ name+" | Blocksize:“+str+" | Foaction指针:"+ str
def get_pointer:
回归自我。指针
def get_name:
回归自我。名称
def get_blocksize:
回归自我。块大小
class _OpenSSL:
"""
使用ctypes的OpenSSL包装器
"""
def __init__:
"""
构建包装
"""
自我。_lib = ctypes。CDLL
self.pointer = ctypes.pointer
self.c_int = ctypes.c_int
self.byref = ctypes.byref
self . create _ string _ buffer = ctypes . create _ string _ buffer
自我。BN_new = self。_lib。BN_new
自我。BN _ new . rest type = ctypes . c _ void _ p
自我。BN_new.argtypes =
自我。BN_free = self。_lib。BN_free
自我。BN _ free.restype =无
自我。BN _ free . arg types =
自我。BN_num_bits = self。_lib。BN _ num _ bits
自我。BN _ num _ bits . rest type = ctypes . c _ int
自我。BN _ num _ bits . arg types =
自我。BN_bn2bin = self。_lib。BN_bn2bin
自我。BN _ BN 2 bin . rest type = ctypes . c _ int
自我。BN _ BN 2 bin . arg types =
自我。BN_bin2bn = self。_lib。BN_bin2bn
自我。BN _ bin2bn . rest type = ctypes . c _ void _ p
自我。BN _ bin2bn . arg types =
自我。EC_KEY_free = self。_lib。EC_KEY_free
自我。EC _ KEY _ free.restype =无
自我。EC _ KEY _ free . arg types =
自我。EC_KEY_new_by_curve_name = self。_lib。EC_KEY_new_by_curve_name
自我。EC _ KEY _ new _ by _ curve _ name . rest type = ctypes . c _ void _ p
自我。EC _ KEY _ new _ by _ curve _ name . arg types =
自我。EC_KEY_generate_key = self。_lib。EC_KEY_generate_key
自我。EC _ KEY _ generate _ KeY . rest type = ctypes . c _ int
自我。EC _ KEY _ generate _ KeY . arg types =
自我。EC_KEY_check_key = self。_lib。EC_KEY_check_key
自我。EC _ KEY _ check _ KeY . rest type = ctypes . c _ int
自我。EC _ KEY _ check _ KeY . arg types =
自我。EC_KEY_get0_private_key = self。_lib。EC_KEY_get0_private_key
自我。EC _ KEY _ get0 _ private _ KeY . rest type = ctypes . c _ void _ p
自我。EC _ KEY _ get0 _ private _ KeY . arg types =
自我。EC_KEY_get0_public_key = self。_lib。EC_KEY_get0_public_key
自我。EC _ KEY _ get0 _ public _ KeY . rest type = ctypes . c _ void _ p
自我。EC _ KEY _ get0 _ public _ KeY . arg types =
自我。EC_KEY_get0_group = self。_lib。EC_KEY_get0_group
自我。EC _ KEY _ get0 _ group . rest type = ctypes . c _ void _ p
自我。EC _ KEY _ get0 _ group . arg types =
自我。EC _ POINT _ get _仿射_坐标_GFp = self。_lib。EC _ POINT _ get _仿射_坐标_GFp
自我。EC _ POINT _ get _仿射_坐标_ GFp . rest type = ctypes . c _ int
自我。EC _ POINT _ get _仿射_坐标_GFp.argtypes =
自我。EC_KEY_set_private_key = self。_lib。EC_KEY_set_private_key
自我。EC _ KEY _ set _ private _ KeY . rest type = ctypes . c _ int
自我。EC _ KEY _ set _ private _ KeY . arg types =
自我。EC_KEY_set_public_key = self。_lib。EC_KEY_set_public_key
自我。EC _ KEY _ set _ public _ KeY . rest type = ctypes . c _ int
自我。EC _ KEY _ set _ public _ KeY . arg types =
自我。EC_KEY_set_group = self。_lib。EC_KEY_set_group
自我。EC _ KEY _ set _ group . rest type = ctypes . c _ int
自我。EC _ KEY _ set _ group . arg types =
自我。EC _ POINT _ set _仿射_坐标_GFp = self。_lib。EC _ POINT _ set _仿射_坐标_GFp
自我。EC _ POINT _ set _仿射_坐标_ GFp . rest type = ctypes . c _ int
自我。EC _ POINT _ set _仿射_坐标_GFp.argtypes =
自我。EC_POINT_new = self。_lib。EC_POINT_new
自我。EC _ POINT _ new . rest type = ctypes . c _ void _ p
自我。EC _ PONT _ new . arg types =
自我。EC_POINT_free = self。_lib。EC_POINT_free
自我。EC _ POINT _ free.restype = None
自我。EC _ POINT _ free . arg types =
自我。EC_KEY_set_private_key = self。_lib。EC_KEY_set_private_key
自我。EC _ KEY _ set _ private _ KeY . rest type = ctypes . c _ int
自我。EC _ KEY _ set _ private _ KeY . arg types =
自我。ECDH_OpenSSL = self。_lib。ECDH_OpenSSL
自我。_lib。ECDH _ OpenSSL . rest type = ctypes . c _ void _ p
自我。_lib。ECDH_OpenSSL.argtypes =
自我。ECDH _设置_方法=自我。_lib。ECDH _集合_方法
自我。_lib。ECDH _ set _ method . rest type = ctypes . c _ int
自我。_lib。ECDH _ set _ method . arg types =
自我。ECDH _计算_键=自我。_lib。ECDH _计算_密钥
自我。ECDH _ compute _ key . rest type = ctypes . c _ int
自我。ECDH _ compute _ key . arg types =
自我。EVP_CipherInit_ex = self。_lib。EVP_CipherInit_ex
自我。EVP _ Cipherinit _ ex . rest type = ctypes . c _ int
自我。EVP _ Cipherinit _ ex . arg types =
自我。EVP_CIPHER_CTX_new = self。_lib。EVP _ CIPHER _ CTX _新
自我。EVP _ CIPHER _ CTX _ new . rest type = ctypes . c _ void _ p
自我。EVP_CIPHER_CTX_new.argtypes =
#密码
自我。EVP_aes_128_cfb128 = self。_lib。EVP_aes_128_cfb128
自我。EVP _ AES _ 128 _ CFB 128 . rest type = ctypes . c _ void _ p
自我。EVP_aes_128_cfb128.argtypes =
自我。EVP_aes_256_cfb128 = self。_lib。EVP_aes_256_cfb128
自我。EVP _ AES _ 256 _ CFB 128 . rest type = ctypes . c _ void _ p
自我。EVP_aes_256_cfb128.argtypes =
自我。EVP_aes_128_cbc = self。_lib。EVP_aes_128_cbc
自我。EVP _ AES _ 128 _ CBC . rest type = ctypes . c _ void _ p
自我。EVP_aes_128_cbc.argtypes =
自我。EVP_aes_256_cbc = self。_lib。EVP_aes_256_cbc
自我。EVP _ AES _ 256 _ CBC . rest type = ctypes . c _ void _ p
自我。EVP_aes_256_cbc.argtypes =
#自我。EVP _ aes _ 128 _ ctr = self。_lib。EVP_aes_128_ctr
#自我。EVP _ AES _ 128 _ ctrl . rest type = ctypes . c _ void _ p
#自我。EVP _ AES _ 128 _ ctrl . arg types =
#自我。EVP _ aes _ 256 _ ctr = self。_lib。EVP_aes_256_ctr
#自我。EVP _ AES _ 256 _ ctrl . rest type = ctypes . c _ void _ p
#自我。EVP _ AES _ 256 _ ctrl . arg types =
自我。EVP_aes_128_ofb = self。_lib。EVP_aes_128_ofb
自我。EVP _ AES _ 128 _ ofb . rest type = ctypes . c _ void _ p
自我。EVP_aes_128_ofb.argtypes =
自我。EVP_aes_256_ofb = self。_lib。EVP_aes_256_ofb
自我。EVP _ AES _ 256 _ ofb . rest type = ctypes . c _ void _ p
自我。EVP_aes_256_ofb.argtypes =
自我。EVP_bf_cbc = self。_lib。EVP_bf_cbc
自我。EVP _ BF _ CBC . rest type = ctypes . c _ void _ p
自我。EVP_bf_cbc.argtypes =
自我。EVP_bf_cfb64 = self。_lib。EVP_bf_cfb64
自我。EVP _ BF _ CFB 64 . rest type = ctypes . c _ void _ p
自我。EVP_bf_cfb64.argtypes =
自我。EVP_rc4 = self。_lib。EVP_rc4
自我。EVP _ RC 4 . rest type = ctypes . c _ void _ p
自我。EVP_rc4.argtypes =
自我。EVP_CIPHER_CTX_cleanup = self。_lib。EVP _ CIPHER _ CTX _清理
自我。EVP _ CIPHER _ CTX _ clean up . rest type = ctypes . c _ int
自我。EVP _ CIPHER _ CTX _ clean up . arg types =
自我。EVP_CIPHER_CTX_free = self。_lib。免费CTX
自我。EVP _ CIPHER _ CTX _ free . rest type = None
自我。EVP _ CIPHER _ CTX _ free . arg types =
自我。EVP _ CipherUpdate = self。_lib。EVP _密码更新
自我。EVP _ FierUpdate . rest type = ctypes . c _ int
自我。EVP _ FierUpdate . arg types =
自我。EVP_CipherFinal_ex = self。_lib。EVP _密码最终_ex
自我。EVP _ FierField _ ex . rest type = ctypes . c _ int
自我。EVP _ CipherFinal _ ex . arg types =
自我。EVP_DigestInit = self。_lib。EVP_DigestInit
自我。EVP _ digest init . rest type = ctypes . c _ int
自我。_lib。EVP _ digest init . arg types =
自我。EVP_DigestUpdate = self。_lib。EVP_DigestUpdate
自我。EVP _ digestupdate . rest type = ctypes . c _ int
自我。EVP _ digestupdate . arg types =
自我。EVP_DigestFinal = self。_lib。EVP_DigestFinal
自我。EVP _ digest final . rest type = ctypes . c _ int
自我。EVP _ digest final . arg types =
自我。EVP_ecdsa = self。_lib。EVP_ecdsa
自我。_lib。EVP _ ECD sa . rest type = ctypes . c _ void _ p
自我。_lib。EVP_ecdsa.argtypes =
自我。ECDSA_sign = self。_lib。ECDSA_sign
自我。ECDSA _ sign . rest type = ctypes . c _ int
自我。ECDSA _ sign . arg types =
自我。ECDSA_verify = self。_lib。ECDSA _验证
自我。ECDSA _ verify . rest type = ctypes . c _ int
自我。ECDSA _ verify . arg types =
自我。EVP_MD_CTX_create = self。_lib。EVP _ MD _ CTX _创建
自我。EVP _ MD _ CTX _ create . restype = ctypes . c _ void _ p
自我。EVP_MD_CTX_create.argtypes =
自我。EVP_MD_CTX_init = self。_lib。EVP_MD_CTX_init
自我。EVP _ MD _ CTX _ init . rest type =无
自我。EVP _ MD _ CTX _ init . arg types =
自我。EVP_MD_CTX_destroy = self。_lib。EVP _ MD _ CTX _破坏
自我。EVP _ MD _ CTX _ destroy . rest type = None
自我。EVP _ MD _ CTX _ destroy . arg types =
自我。RAND_bytes = self。_lib。RAND _字节
自我。RAND _ bytes.restype =无
自我。RAND _ bytes . arg types =
自我。EVP_sha256 = self。_lib。EVP_sha256
自我。EVP _ sha 256 . rest type = ctypes . c _ void _ p
自我。EVP_sha256.argtypes =
自我。EVP_sha512 = self。_lib。EVP_sha512
自我。EVP _ sha 512 . rest type = ctypes . c _ void _ p
自我。EVP_sha512.argtypes =
自我。HMAC =自我。_lib。HMAC
自我。HMAC . rest type = ctypes . c _ void _ p
自我。HMAC.argtypes =
#自我。PKCS5_PBKDF2_HMAC =自我。_lib。PKCS5_PBKDF2_HMAC
#自我。PKCS5 _ PBKDF 2 _ HMAC . rest type = ctypes . c _ int
#自我。PKCS5 _ PBKDF 2 _ HMAC . arg types =
自我。_set_ciphers
自我。_set_curves
def _set_ciphers:
self.cipher_algo = {
' aes-128-cbc ':密码名,
“aes-256-cbc”:密码名,
' aes-128-cfb ':密码名,
“aes-256-cfb”:密码名,
“aes-128-ofb”:密码名,
“aes-256-ofb”:密码名,
#'aes-128-ctr ':密码名,
#'aes-256-ctr ':密码名,
' bf-cfb ':密码名,
' bf-cbc ':密码名,
' rc4 ':密码名,# 128是初始化大小,不是块大小
}
def _set_curves:
self.curves = {
secp112r1': 704,
secp112r2': 705,
secp128r1': 706,
secp128r2': 707,
secp160k1': 708,
secp160r1': 709,
secp160r2': 710,
secp192k1': 711,
secp224k1': 712,
secp224r1': 713,
secp256k1': 714,
secp384r1': 715,
secp521r1': 716,
第113r1节:717,
section 113 r 2 ':718,
section 131 R1 ':719,
section 131 r 2 ':720,
section 163 k1 ':721,
第163r1节:722,
section 163 r 2 ':723,
section 193 r 1 ':724,
section 193 r 2 ':725,
section 233 k1 ':726,
第233r1节:727,
section 239 k1 ':728,
section 283 k1 ':729,
第283r1节:730,
section 409 k1 ':731,
section 409 R1 ':732,
section 571 k1 ':733,
section 571 R1 ':734,
prime256v1': 415,
}
def _ BN _ num _ bytes:
"""
返回一个字符串的长度
"""
return int + 7) / 8)
def get_cipher:
"""
返回OpenSSL密码实例
"""
如果名称不在self.cipher_algo中:
引发异常
return self.cipher_algo
def get_curve:
"""
返回椭圆曲线的id
"""
如果名称不在自我曲线中:
引发异常
返回self.curves
def get_curve_by_id:
"""
返回带有id的椭圆曲线的名称
"""
res =无
自我曲线中的我:
if self.curves == id:
res = i
打破
如果分辨率为无:
引发异常
返回资源
def rand:
"""
OpenSSL随机函数
"""
buffer = self.malloc
自我。RAND _字节
返回缓冲区. raw
def malloc:
"""
返回create_string_buffer
"""
缓冲=无
if数据!= 0:
如果sys.version_info.major == 3且isinstance):
data = data.encode
buffer = self . create _ string _ buffer
else:
buffer = self . create _ string _ buffer
返回缓冲器
libname = ctypes . util . find _ library
如果库名为“无”:
#对于Windows...
libname = ctypes . util . find _ library
如果库名为“无”:
引发异常
OpenSSL = _OpenSSL
Python代码下载链接:https://pan.baidu.com/s/1nvbyl3F密码:02km
0×03汇总
一般来说,椭圆曲线是密码学中的硬骨头,类似于传统的大整数分解、离散对数等问题。由于难度较大,本文先在这里举报一个失败,下期会带来对ECC的深入了解。
*本文原作者:苗苗Xi、怀,本文属于FreeBuf原创奖励计划,未经许可禁止转载。
1.《ecc 椭圆曲线算法(ECC)学习(一)》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《ecc 椭圆曲线算法(ECC)学习(一)》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/1686487.html