返回顶部
首页 > 资讯 > 后端开发 > Python >如何在python中实现ECDSA你知道吗
  • 646
分享到

如何在python中实现ECDSA你知道吗

2024-04-02 19:04:59 646人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

import six import timeit#查找任何特定代码执行的确切时间 from ecdsa.curves import curves #定义do函数,计算时间


import six
import timeit#查找任何特定代码执行的确切时间
from ecdsa.curves import curves

#定义do函数,计算时间
def do(setup_statements, statement):
    # extracted from timeit.py
    t = timeit.Timer(stmt=statement, setup="\n".join(setup_statements))
    # determine number so that 0.2 <= total time < 2.0
    for i in range(1, 10):
        number = 10 ** i #**为次方
        x = t.timeit(number)
        if x >= 0.2:
            break
    return x / number

NIST为数字测试套件关于NIST详解

GF§ (素数域)曲线,密钥长度为192、224、256、384和521bit

OpenSSL工具openssl ecparam -list_curves)所知道的这些曲线的 "简称 "是:prime192v1secp224r1prime256v1secp384r1secp521r1。它包括比特币使用的256位曲线secp256k1。它还支持160到512位的Brainpool曲线的常规(非扭曲)变体。这些曲线的 "简称 "是:BrainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1。少数来自SEC标准的小曲线也包括在内(主要是为了加快库的测试),它们是:secp112r1, secp112r2, secp128r1, 和secp160r1。没有包括其他的曲线,但要增加对更多素数域的曲线的支持并不难。


#不是很懂 sep=":",unit="s",fORM=".5f",form_inv=".2f",
prnt_form = (
    "{name:>16}{sep:1} {siglen:>6} {keygen:>9{form}}{unit:1} "
    "{keygen_inv:>9{form_inv}} {sign:>9{form}}{unit:1} "
    "{sign_inv:>9{form_inv}} {verify:>9{form}}{unit:1} "
    "{verify_inv:>9{form_inv}} {verify_single:>13{form}}{unit:1} "
    "{verify_single_inv:>14{form_inv}}"
)
print(
    prnt_form.format(
        siglen="siglen",
        keygen="keygen",
        keygen_inv="keygen/s",
        sign="sign",
        sign_inv="sign/s",
        verify="verify",
        verify_inv="verify/s",
        verify_single="no PC verify",
        verify_single_inv="no PC verify/s",
        name="",
        sep="",
        unit="",
        form="",
        form_inv="",
    )
)
for curve in [i.name for i in curves]:
    S1 = "import six; from ecdsa import SigningKey, %s" % curve
    S2 = "sk = SigningKey.generate(%s)" % curve #产生私钥
    S3 = "msg = six.b('msg')" #消息
    S4 = "sig = sk.sign(msg)" #签名
    S5 = "vk = sk.get_verifying_key()"#公钥由私钥得出  get_verifying_key()函数
    S6 = "vk.precompute()"#不懂
    S7 = "vk.verify(sig, msg)"#用公钥验证签名
    # 我们碰巧知道.generate()也在计算验证密钥,这是最耗时的部分。如果将代码改为懒惰地计算vk,我们就需要将这个基准改为在S5上循环,而不是在S2上。
    keygen = do([S1], S2)
    sign = do([S1, S2, S3], S4)
    verf = do([S1, S2, S3, S4, S5, S6], S7)
    verf_single = do([S1, S2, S3, S4, S5], S7)
    import ecdsa
    c = getattr(ecdsa, curve)#从名字上看获取属性值
    sig = ecdsa.SigningKey.generate(c).sign(six.b("msg"))
    #密钥对(keygen)、签署数据(sign)、验证这些签名(verify)、共享秘密(ecdh)以及在没有特定密钥预计算的情况下验证签名(no PC verify)、原始签名的大小(通常是签名可以被编码的最小方式)也在siglen栏中提供
    print(
        prnt_form.format(
            name=curve,#所有的曲线
            sep=":",
            siglen=len(sig),
            unit="s",
            keygen=keygen,
            keygen_inv=1.0 / keygen,
            sign=sign,
            sign_inv=1.0 / sign,
            verify=verf,
            verify_inv=1.0 / verf,
            verify_single=verf_single,
            verify_single_inv=1.0 / verf_single,
            form=".5f",#小数点后面为5位
            form_inv=".2f",#小数点后面为2位
        )
    )

print("")

ED25519和Cureve5519


ecdh_form = "{name:>16}{sep:1} {ecdh:>9{form}}{unit:1} {ecdh_inv:>9{form_inv}}"
print(
    ecdh_form.format(
        ecdh="ecdh",
        ecdh_inv="ecdh/s",
        name="",
        sep="",
        unit="",
        form="",
        form_inv="",
    )
)
for curve in [i.name for i in curves]:
    if curve == "Ed25519" or curve == "Ed448":
        continue
    S1 = "from ecdsa import SigningKey, ECDH, {0}".format(curve)
    S2 = "our = SigningKey.generate({0})".format(curve)#私钥
    S3 = "remote = SigningKey.generate({0}).verifying_key".format(curve)#公钥
    S4 = "ecdh = ECDH(private_key=our, public_key=remote)"
    S5 = "ecdh.generate_sharedsecret_bytes()"#产生共享密钥
    ecdh = do([S1, S2, S3, S4], S5)
    print(
        ecdh_form.format(
            name=curve,
            sep=":",
            unit="s",
            form=".5f",
            form_inv=".2f",
            ecdh=ecdh,
            ecdh_inv=1.0 / ecdh,
        )
    )

在这里插入图片描述

在这里插入图片描述


from ecdsa import SigningKey
sk = SigningKey.generate() # uses NIST192p生成私钥
vk = sk.verifying_key#在私钥的基础上生成公钥
signature = sk.sign(b"message")#用私钥对消息进行签名
assert vk.verify(signature, b"message")#用公钥去验证。assert为一断言函数:不满足条件直接触发异常忙不执行接下来的代码,括号中为condition

from ecdsa import SigningKey, NIST384p#384位NIST素域椭圆曲线,其中私钥/公钥都与特定的曲线相关联,更长的曲线更安全,但时间长,密钥和签名也长
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")

#将签名密钥(私钥)序列化成不同的格式。
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_string = sk.to_string()#最短的调用,然后再重新创建私钥。to_string():将括号内的数字转化为字符串,实际返回的类型bytes
sk2 = SigningKey.from_string(sk_string, curve=NIST384p)#重新创建私钥,第一个参数是我们要处理的字符,如果点编码无效或不在指定曲线上,from_string()将引发MalformedPointError
print(sk_string.hex())
print(sk2.to_string().hex())

from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_pem = sk.to_pem()#sk.to_pem()和sk.to_der()将把签名密钥序列化为OpenSSL使用的相同格式
sk2 = SigningKey.from_pem(sk_pem)#SigningKey.from_pem()/.from_der()将撤销这种序列化。这些格式包括了曲线名称,所以你不需要向反序列化器传递曲线标识符。如果文件是畸形的,from_der()和from_pem()将引发UnexpectedDER或MalformedPointError。
# sk and sk2 are the same key

from ecdsa import SigningKey, VerifyingKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
vk_string = vk.to_string()#公钥可以用同样的方式进行序列化
vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)
# vk and vk2 are the same key

from ecdsa import SigningKey, VerifyingKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
vk_pem = vk.to_pem()
vk2 = VerifyingKey.from_pem(vk_pem)
# vk and vk2 are the same key

import os
from ecdsa import NIST384p, SigningKey
from ecdsa.util import randrange_from_seed__trytryagain#产生随机数
def make_key(seed):
  secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
  return SigningKey.from_secret_exponent(secexp, curve=NIST384p)
seed = os.urandom(NIST384p.baselen) # or other starting point,返回一个适合加密的比特串
sk1a = make_key(seed)
sk1b = make_key(seed)
# note: sk1a and sk1b are the same key
assert sk1a.to_string() == sk1b.to_string()
sk2 = make_key(b"2-"+seed)  # different key  b为比特
assert sk1a.to_string() != sk2.to_string()
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
vk.precompute()
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")

# openssl ecparam -name prime256v1 -genkey -out sk.pem
# openssl ec -in sk.pem -pubout -out vk.pem
# echo "data for signing" > data
# openssl dgst -sha256 -sign sk.pem -out data.sig data
# openssl dgst -sha256 -verify vk.pem -signature data.sig data
# openssl dgst -sha256 -prverify sk.pem -signature data.sig data
#OpenSSL 使用 PEM 文件格式存储证书和密钥。PEM 实质上是 Base64 编码的二进制内容
import hashlib#
from ecdsa import SigningKey, VerifyingKey
from ecdsa.util import sigencode_der, sigdecode_der#从ecdsa.util写入和读取签名
with open("vk.pem") as f:#公钥文件
   vk = VerifyingKey.from_pem(f.read())
with open("data", "rb") as f:#open()为读取模式,with语句直接调用close方法,r为读模式,w/wb为写模式,rb模式打开二进制文件,消息data
   data = f.read()
with open("data.sig", "rb") as f:#消息签名可读模式
   signature = f.read()
assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)#公钥验证签名,
with open("sk.pem") as f:#私钥文件
   sk = SigningKey.from_pem(f.read(), hashlib.sha256)
new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)#用私钥签名生成一个新的签名
with open("data.sig2", "wb") as f:#写模式
   f.write(new_signature)

# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data
#如果需要与OpenSSL 1.0.0或更早的版本兼容,可以使用ecdsa.util中的sigencode_string和sigdecode_string来分别写入和读取签名。
from ecdsa import SigningKey, VerifyingKey
with open("sk.pem") as f:
    sk = SigningKey.from_pem(f.read())
with open("sk.pem", "wb") as f:
    f.write(sk.to_pem())
with open("vk.pem") as f:
    vk = VerifyingKey.from_pem(f.read())
with open("vk.pem", "wb") as f:
    f.write(vk.to_pem())

#ecdsa.util.PRNG 工具在这里很方便:它需要一个种子并从中产生一个强的伪随机流。
#os.urandom的函数作为entropy=参数来做不同的事情
#ECDSA的签名生成也需要一个随机数,而且每个签名都必须使用不同的随机数(两次使用相同的数字会立即暴露出私人签名密钥)。
# sk.sign()方法需要一个entropy=参数,其行为与SigningKey.generate(entropy=)相同。
from ecdsa.util import PRNG
from ecdsa import SigningKey
rng1 = PRNG(b"seed")
sk1 = SigningKey.generate(entropy=rng1)
rng2 = PRNG(b"seed")
sk2 = SigningKey.generate(entropy=rng2)
# sk1 and sk2 are the same key

#如果你调用SigningKey.sign_deterministic(data)而不是.sign(data),代码将生成一个确定性的签名,而不是随机的。
# 这使用RFC6979中的算法来安全地生成一个唯一的K值,该值来自于私钥和被签名的信息。每次你用相同的密钥签署相同的信息时,你将得到相同的签名(使用相同的k)。
#创建一个NIST521p密钥对
from ecdsa import SigningKey, NIST521p
sk = SigningKey.generate(curve=NIST521p)
vk = sk.verifying_key
#从一个主种子创建三个独立的签名密钥
from ecdsa import NIST192p, SigningKey
from ecdsa.util import randrange_from_seed__trytryagain
def make_key_from_seed(seed, curve=NIST192p):
    secexp = randrange_from_seed__trytryagain(seed, curve.order)
    return SigningKey.from_secret_exponent(secexp, curve)
sk1 = make_key_from_seed("1:%s" % seed)
sk2 = make_key_from_seed("2:%s" % seed)
sk3 = make_key_from_seed("3:%s" % seed)
#从磁盘上加载一个验证密钥,并使用十六进制编码以未压缩和压缩的格式打印出来(在X9.62和SEC1标准中定义)。
from ecdsa import VerifyingKey
with open("public.pem") as f:#加载验证密钥
    vk = VerifyingKey.from_pem(f.read())
print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
print("compressed: {0}".format(vk.to_string("compressed").hex()))
#从压缩格式的十六进制字符串中加载验证密钥,以未压缩的格式输出。
from ecdsa import VerifyingKey, NIST256p
comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759'
vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p)
print(vk.to_string("uncompressed").hex())
#与远程方进行ECDH密钥交换。
from ecdsa import ECDH, NIST256p
ecdh = ECDH(curve=NIST256p)
ecdh.generate_private_key()
local_public_key = ecdh.get_public_key()
#send `local_public_key` to remote party and receive `remote_public_key` from remote party
with open("remote_public_key.pem") as e:
    remote_public_key = e.read()
ecdh.load_received_public_key_pem(remote_public_key)
secret = ecdh.generate_sharedsecret_bytes()

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: 如何在python中实现ECDSA你知道吗

本文链接: https://lsjlt.com/news/158051.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何在python中实现ECDSA你知道吗
    import six import timeit#查找任何特定代码执行的确切时间 from ecdsa.curves import curves #定义do函数,计算时间...
    99+
    2024-04-02
  • 你知道如何在ASP IDE中实现对象同步吗?
    当今的软件开发行业越来越依赖于对象导向编程。ASP.NET提供了一个集成开发环境(IDE),可以帮助程序员管理对象、类和方法。在ASP IDE中实现对象同步是一项非常重要的任务,因为它可以确保代码的正确性和可靠性。 在本文中,我们将探讨如何...
    99+
    2023-06-21
    ide 同步 对象
  • 你知道如何在Python教程中加载npm吗?
    当你在学习 Python 时,你可能会遇到需要使用 npm(Node.js 包管理器)的情况。虽然 Python 和 Node.js 是不同的编程语言,但是两者之间的交互是非常常见的。在本文中,我们将介绍如何在 Python 教程中加载 n...
    99+
    2023-06-20
    教程 npm load
  • 你知道如何在 Laravel 中使用 Python 接口吗?
    当今软件开发领域中,Laravel 是一个备受追捧的 PHP Web 开发框架,而 Python 则是一门功能强大且易于使用的编程语言。那么,如何在 Laravel 中使用 Python 接口呢?本文将为你提供一些有用的指导。 为什么使用 ...
    99+
    2023-09-06
    接口 laravel path
  • 你知道如何在Windows中使用Python和npm吗?
    当今,Python和npm已成为程序员们日常工作中必不可少的工具。在Windows系统中使用Python和npm可以大大提高工作效率。但是,很多初学者对于如何在Windows中使用Python和npm还不够熟悉。因此,在本文中,我们将为大家...
    99+
    2023-10-14
    npm shell windows
  • 如何在C++中调用python代码你知道吗
    目录一、环境设置二、VS项目中设置(1)首先在acaconda中找到include文件夹和libs文件夹,如图所示(2)点击链接器,然后输入,附加依赖项,添加python36_d.l...
    99+
    2024-04-02
  • 你知道如何在 shell 中使用 Python 编程吗?
    当我们在 shell 中进行命令行操作时,有时候会需要进行一些简单的编程操作,这时候 Python 就是一个很好的选择。Python 作为一种高级编程语言,拥有丰富的库和函数,能够帮助我们完成很多复杂的任务。在本文中,我们将会探讨如何在 s...
    99+
    2023-08-07
    编程算法 shell linux
  • 你知道如何在 JavaScript 中实现 Go 中的数组接口吗?
    JavaScript 作为一门广泛应用于前端开发的语言,其在数据处理方面的能力也是非常强大的。然而,在处理大规模数据时,JavaScript 的性能可能会受到一定的影响。而 Go 语言,则在处理大规模数据时表现出色,其原因在于其数组接口的设...
    99+
    2023-07-01
    数组 javascript 接口
  • 你知道如何在Go中使用Git吗?
    Go是一种非常流行的编程语言,它的简洁、高效、安全和易于学习的特点让它成为了许多开发者的选择。Git则是一种非常强大的版本控制系统,它可以让我们更加方便地管理代码。那么,你知道如何在Go中使用Git吗?本文将为你详细介绍。 一、安装Git ...
    99+
    2023-11-15
    git 索引 并发
  • 你知道如何在Python中优雅地处理Bash IDE吗?
    当今软件开发行业中,Python已经成为了最流行的语言之一。而Bash IDE则是一个功能强大的集成开发环境,可以为Python开发者提供良好的编程体验。本文将探讨如何在Python中优雅地处理Bash IDE,帮助Python开发者更好地...
    99+
    2023-09-16
    load bash ide
  • 你知道如何在NumPy中使用Python数据类型吗?
    当我们使用NumPy库进行数值计算时,我们通常使用NumPy中的数组(ndarray)来表示数据。而这些数组可以存储不同种类的数据,包括Python的内置数据类型,例如整数、浮点数、布尔值等。 在本文中,我们将介绍如何在NumPy中使用Py...
    99+
    2023-06-02
    numpy 数据类型 leetcode
  • 你知道如何在Java IDE中使用Bash吗?
    在现代软件开发中,Java是一种极其流行的编程语言。Java开发人员经常使用Java集成开发环境(IDE)来编写、调试和测试Java代码。同时,Bash是一种流行的Unix shell,它提供了强大的命令行工具和脚本语言。虽然Java开发...
    99+
    2023-06-17
    ide bash javascript
  • 你知道如何在Go中设置路径吗?
    当我们在使用Go语言进行编程时,经常需要设置路径来引用其他的包或文件。但是,如果不了解如何设置路径,就会出现无法找到文件或包的情况。本文将介绍如何在Go中设置路径,以便更有效地进行编程。 在Go中设置路径的方法有很多种,下面我们将逐一介绍。...
    99+
    2023-06-19
    path 对象 编程算法
  • 你知道如何在 Go 中处理路径吗?
    当我们在编写 Go 代码时,处理文件路径是一个很常见的需求。路径通常用于访问文件系统中的文件和目录,或者用于网络请求中的 URL。在本文中,我们将讨论如何在 Go 中处理路径。 Go 中使用的路径分隔符是斜杠(/),这与 Unix 和 Li...
    99+
    2023-09-23
    http shell path
  • 你知道如何在Laravel中使用对象吗?
    Laravel是一种流行的PHP Web应用程序框架,它提供了一系列的工具和服务来帮助开发者快速构建高质量的Web应用程序。在Laravel中,对象是一种非常重要的概念。本文将介绍如何在Laravel中使用对象。 在Laravel中,对象是...
    99+
    2023-09-25
    编程算法 laravel 对象
  • 你知道如何在 Go 中使用数组吗?
    当我们编写程序时,经常需要使用到数组。在 Go 语言中,数组是一种简单而强大的数据结构,它可以存储一组相同类型的数据。在本文中,我们将探讨如何在 Go 中使用数组。 声明数组 在 Go 中,声明数组的语法如下: var a [5]int...
    99+
    2023-08-18
    开发技术 数组 关键字
  • 你知道如何在PHP中加载外壳吗?
    PHP是一种流行的服务器端编程语言,它可以实现许多功能,比如生成动态网页、处理表单数据、操作数据库等等。在PHP中,加载外壳是一种常见的技术,可以帮助我们更好地管理代码和资源。本文将介绍什么是外壳,为什么需要外壳以及如何在PHP中加载外壳。...
    99+
    2023-11-02
    load shell 数组
  • 你知道如何在Git中打包代码吗?
    当你需要在Git中打包代码时,你可能会遇到一些困难。在本文中,我们将向您展示如何使用Git打包代码以及一些使用Git打包代码时可能遇到的常见问题和解决方法。让我们开始吧! 什么是Git打包? 在Git中打包代码是将您的代码打包成一个文件并将...
    99+
    2023-10-30
    编程算法 git 打包
  • 你知道如何使用 Python 和 Django 实现实时打包吗?
    当今互联网时代,开发一个高效的应用程序,如何实现快速打包和部署,是一个非常重要的问题。Python和Django是我们常用的工具之一,那么如何使用Python和Django来实现实时打包呢? 一、什么是实时打包? 实时打包是一种将源代码打包...
    99+
    2023-08-29
    django 实时 打包
  • 你知道吗?NPM如何在Java中实现二维码编程算法
    你知道吗?NPM如何在Java中实现二维码编程算法 二维码编程算法是在现代数字通信中非常重要的一部分。它允许我们快速、简便地在数字世界中传递信息。在本文中,我们将介绍如何使用NPM在Java中实现二维码编程算法。 NPM简介 NPM是一...
    99+
    2023-10-21
    npm 二维码 编程算法
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作