草庐IT

Python加密库 Crypto.Cipher包中 ChaCha20 介绍

奋斗的小农 2023-03-28 原文

该软件包包含用于保护机密性的算法 的数据。Crypto.Cipher

有三种类型的加密算法:

  1. 对称密码:所有各方都使用相同的密钥 解密和加密数据。 对称密码通常非常快,可以处理 非常大量的数据。
  2. 非对称密码:发送方和接收方使用不同的密钥。 发送方使用公钥(非机密)加密,而接收方 使用私钥(机密)解密。 非对称密码通常非常慢,可以处理 只有非常小的有效载荷。示例:PKCS#1 OAEP (RSA)。
  3. 混合密码:上述两种类型的密码可以组合使用 在继承两者优点的结构中。 非对称密码用于保护短期 对称键, 和对称密码(在该密钥下)加密 实际消息。

对称密码

有两种类型的对称密码:

  • 流密码:最自然的密码类型: 它们一次加密一个字节的数据。 参见ChaCha20和XChaCha20和Salsa20

  • 分组密码:只能以固定数量操作的密码 的数据。最重要的分组密码是AES,它具有 块大小为 128 位(16 字节)。

    通常,分组密码通常仅与 一种操作模式,允许加密 可变数量的数据。某些模式(如点击率)可以有效地转动 将分组密码转换为流密码。

广泛的共识是,密码提供 只有机密性,没有任何形式的身份验证,是不可取的。 相反,基元已被定义为集成对称加密和 身份验证 (MAC)。例如:

ChaCha20 和 XChaCha20

ChaCha20是由Daniel J. Bernstein设计的流密码。 密钥长度为 256 位(32 字节)。 密码需要随机数,不得重复使用 跨使用同一密钥执行的加密。

有三种变体,由随机数的长度定义:

随机数长度描述最大数据如果随机随机数和相同的键
8 字节(默认) 由伯恩斯坦设计的原始ChaCha20。 无限制 最多 200 000 条消息
12 字节 RFC7539 中定义的 TLS ChaCha20。 256 千兆字节 最多 130 亿条消息
24 字节 XChaCha20,仍处于草稿阶段 256 千兆字节 无限制
这是ChaCha20(Bernstein的版本)如何加密数据的一个例子:

import json
from base64 import b64encode
from Crypto.Cipher import ChaCha20
from Crypto.Random import get_random_bytes

plaintext = b'Attack at dawn'
key = get_random_bytes(32)
cipher = ChaCha20.new(key=key)
ciphertext = cipher.encrypt(plaintext)

nonce = b64encode(cipher.nonce).decode('utf-8')
ct = b64encode(ciphertext).decode('utf-8')
result = json.dumps({'nonce':nonce, 'ciphertext':ct})
print(result)
{"nonce": "IZScZh28fDo=", "ciphertext": "ZatgU1f30WDHriaN8ts="}
这就是您解密它的方式:

import json
from base64 import b64decode
from Crypto.Cipher import ChaCha20

# We assume that the key was somehow securely shared
try:
    b64 = json.loads(json_input)
    nonce = b64decode(b64['nonce'])
    ciphertext = b64decode(b64['ciphertext'])
    cipher = ChaCha20.new(key=key, nonce=nonce)
    plaintext = cipher.decrypt(ciphertext)
   print("The message was " + plaintext)
except (ValueError, KeyError):
    print("Incorrect decryption")
为了拥有符合 RFC7539 标准的 ChaCha20 密码, 您需要显式生成 96 位(12 字节)参数并将其传递给:noncenew()

nonce_rfc7539 = get_random_bytes(12)
cipher = ChaCha20.new(key=key, nonce=nonce_rfc7539)

 

警告

ChaCha20不保证您解密的数据的真实性! 换句话说,攻击者可能会操纵传输中的数据。 为了防止这种情况,您还必须使用消息身份验证 用于验证密文的代码(如 HMAC) (加密然后 Mac)。或者,您可以使用ChaCha20_Poly1305

.classCrypto.Cipher.ChaCha20.ChaCha20Cipher(随机数)

ChaCha20(或XChaCha20)密码对象。 不要直接创建它。请改用 new()。

变量: 随机数 (字节)– 长度为 8、12 或 24 字节的随机数
decrypt(密文输出=无)

解密一段数据。

参数: 密文 (字节/字节数组/内存视图)– 要解密的数据,任何大小。
关键字参数:
  输出 (字节/字节数组/内存视图)– 明文的位置 被写到。如果为 ,则返回明文。None
返回: 如果是,则明文返回为 。 否则。outputNonebytesNone
encrypt(纯文本输出 = 无)

加密一段数据。

参数: 明文 (字节/字节数组/内存视图)– 要加密的数据,任何大小。
关键字参数:
  输出 (字节/字节数组/内存视图)– 密文的位置 被写到。如果为 ,则返回密文。None
返回: 如果是,则密文返回为 。 否则。outputNonebytesNone
seek(位置)

查找密钥流中的某个位置。

参数: 位置 (整数)– 密钥流中的绝对位置,以字节为单位。
Crypto.Cipher.ChaCha20.new(**夸格斯)

创建新的 ChaCha20 或 XChaCha20 密码

关键字参数:
 
  • key (bytes/bytearray/memoryview) – 要使用的密钥。 它必须为 32 字节长。
  • nonce(bytes/bytearray/memoryview) –

    强制值 不得重用于任何其他加密 使用此密钥完成。

    对于 ChaCha20,它必须为 8 或 12 个字节。

    对于 XChaCha20,它必须为 24 字节长。

    如果未提供,将随机生成 8 个字节 (您可以在属性中找到它们)。nonce

返回:

一个 Crypto.Cipher.ChaCha20.ChaCha20Cipher 对象

转载:ChaCha20 和 XChaCha20 — PyCryptodome 3.17.0 文档

ChaCha20-Poly1305 和 XChaCha20-Poly1305

ChaCha20-Poly1305 是具有关联数据 (AEAD) 的经过身份验证的密码。 它与一个 32 字节的密钥和一个随机数一起工作 绝不能在同一密钥下执行的加密中重复使用。 密码生成一个 16 字节标记,接收方必须使用该标记来验证消息。

该算法有三种变体,由随机数的长度定义:

随机数长度描述最大明文数如果随机随机数和相同的键
8 字节 基于伯恩斯坦的原始ChaCha20。 无限制 最多 200 000 条消息
12 字节(默认) 在 TLS 中使用并在 RFC7539 中指定的版本。 256 千兆字节 最多 130 亿条消息
24 字节 XChaCha20-Poly1305,仍处于草稿阶段 256 千兆字节 无限制

密码的 API 及其有限状态机与分组密码的现代操作模式相同。

通过调用 Crypto.Cipher.ChaCha20_Poly1305.new() 创建新密码。

以下是 ChaCha20-Poly1305(TLS 版本)如何加密和验证数据的示例:

 import json
 from base64 import b64encode
 from Crypto.Cipher import ChaCha20_Poly1305
 from Crypto.Random import get_random_bytes

 header = b"header"
 plaintext = b'Attack at dawn'
 key = get_random_bytes(32)
 cipher = ChaCha20_Poly1305.new(key=key)
 cipher.update(header)
 ciphertext, tag = cipher.encrypt_and_digest(plaintext)

 jk = [ 'nonce', 'header', 'ciphertext', 'tag' ]
 jv = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ]
 result = json.dumps(dict(zip(jk, jv)))
 print(result)
{"nonce": "4EE/9uqhoZ3mQXmm", "header": "aGVhZGVy", "ciphertext": "Wmmo4Vzn+eS3tUPv2a8=", "tag": "/FgVbM8qhzssPRY80T0iVA=="}
在上面的示例中,会自动创建一个 96 位(12 字节)随机数。 可以将其作为对象中的成员进行访问。noncecipher

这是您解密数据并检查其真实性的方式:

 import json
 from base64 import b64decode
 from Crypto.Cipher import ChaCha20_Poly1305

 # We assume that the key was securely shared beforehand
 try:
     b64 = json.loads(json_input)
     jk = [ 'nonce', 'header', 'ciphertext', 'tag' ]
    jv = {k:b64decode(b64[k]) for k in jk}

    cipher = ChaCha20_Poly1305.new(key=key, nonce=jv['nonce'])
    cipher.update(jv['header'])
    plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag'])
    print("The message was: " + plaintext)
 except (ValueError, KeyError):
    print("Incorrect decryption")

 

.classCrypto.Cipher.ChaCha20_Poly1305.ChaCha20Poly1305Cipher(随机数)

ChaCha20-Poly1305 和 XChaCha20-Poly1305 密码对象。 不要直接创建它。请改用 new()。

变量: 随机数 (字节字符串)– 长度为 8、12 或 24 字节的随机数
decrypt(密文输出=无)

解密一段数据。

参数: 密文 (字节/字节数组/内存视图)– 要解密的数据,任何大小。
关键字参数:
  输出 (字节/字节数组/内存视图)– 明文的位置 被写到。如果为 ,则返回明文。None
返回: 如果是,则明文返回为 。 否则。outputNonebytesNone
decrypt_and_verify(密文received_mac_tag)

一步执行 decrypt() 和 verify()。

参数:
  • 密文(字节/字节数组/内存视图)– 要解密的数据片段。
  • received_mac_tag(字节)— 这是从发送方接收的 16 字节二进制 MAC。
返回:

解密的数据(作为bytes)

提高:

值错误 – 如果 MAC 不匹配。邮件已被篡改 或者密钥不正确。

digest()

计算二进制身份验证标记 (MAC)。

返回: MAC 标记,作为 16 .bytes
encrypt(纯文本输出 = 无)

加密一段数据。

参数: 明文 (字节/字节数组/内存视图)– 要加密的数据,任何大小。
关键字参数:
  输出 (字节/字节数组/内存视图)– 密文的位置 被写到。如果为 ,则返回密文。None
返回: 如果是,则密文返回为 。 否则。outputNonebytesNone
encrypt_and_digest(明文)

在一个步骤中执行 encrypt() 和 digest()。

参数: 明文 (字节/字节数组/内存视图)– 要加密的数据,任何大小。
返回: 包含两个对象的元组:bytes
  • 密文,长度与明文相同
  • 16 字节 MAC 标签
hexdigest()

计算可打印的身份验证标记 (MAC)。

此方法类似于摘要()。

返回: MAC 标记,作为十六进制字符串。
hexverify(hex_mac_tag)

验证可打印的身份验证标记 (MAC)。

此方法类似于 verify()。

参数: hex_mac_tag (字符串)– 这是可打印的 MAC。
提高值错误:
  如果 MAC 不匹配。邮件已被篡改 或者密钥不正确。
update(数据)

保护关联的数据。

关联数据(也称为其他经过身份验证的数据 - AAD) 是必须保持清晰的信息部分,而 仍然允许接收器验证其完整性。 数据包标头就是一个例子。

关联的数据(可能拆分为多个段)为 在调用 decrypt() 或 encrypt() 之前输入到 update() 中。 如果没有关联的数据,则不调用 update()。

参数: assoc_data (字节/字节数组/内存视图)– 一段关联数据。它的大小没有限制。
verify(received_mac_tag)

验证二进制身份验证标记 (MAC)。

接收方在最后调用此方法, 检查相关数据(如果有)和解密 消息有效。

参数: received_mac_tag (字节/字节数组/内存视图)– 这是从发送方收到的 16 字节二进制 MAC。
提高值错误:
  如果 MAC 不匹配。邮件已被篡改 或者密钥不正确。
Crypto.Cipher.ChaCha20_Poly1305.new(**夸格斯)

创建新的 ChaCha20-Poly1305 或 XChaCha20-Poly1305 AEAD 密码。

关键字参数:
 
  • key – 要使用的密钥。它必须为 32 字节长。
  • 随机数 –

    不得重用于任何其他加密的值 使用此密钥完成。

    对于 ChaCha20-Poly1305,它的长度必须为 8 或 12 个字节。

    对于 XChaCha20-Poly1305,它必须为 24 字节长。

    如果未提供,将随机生成 12 个 (您可以在属性中找到它们)。bytesnonce

返回:

一个对象Crypto.Cipher.ChaCha20.ChaCha20Poly1305Cipher

有关Python加密库 Crypto.Cipher包中 ChaCha20 介绍的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  3. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  4. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  5. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  6. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  7. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  8. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  9. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  10. Python 刷Leetcode题库,顺带学英语单词(31) - 2

    ValidPalindromeGivenastring,determineifitisapalindrome,consideringonlyalphanumericcharactersandignoringcases. [#125]Example:"Aman,aplan,acanal:Panama"isapalindrome."raceacar"isnotapalindrome.Haveyouconsiderthatthestringmightbeempty?Thisisagoodquestiontoaskduringaninterview.Forthepurposeofthisproblem

随机推荐