Π“ΠžΠ‘Π’Π˜Πœ: P2P F2F E2EE IM Π·Π° Π΅Π΄ΠΈΠ½ Π²Π΅Ρ‡Π΅Ρ€ с Π“ΠžΠ‘Π’-криптография

ΠšΠ°Ρ‚ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ PyGOST Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° (Π“ΠžΠ‘Π’ криптографски ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²ΠΈ Π½Π° чист Python), чСсто ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌ Π²ΡŠΠΏΡ€ΠΎΡΠΈ ΠΊΠ°ΠΊ Π½Π° коляно Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌ прост бСзопасСн ΠΎΠ±ΠΌΠ΅Π½ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ. Много Ρ…ΠΎΡ€Π° считат ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ½Π°Ρ‚Π° криптография Π·Π° Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ проста Ρ€Π°Π±ΠΎΡ‚Π°, ΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° .encrypt() Π½Π° Π±Π»ΠΎΡ‡Π΅Π½ ΡˆΠΈΡ„ΡŠΡ€ Ρ‰Π΅ Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Π·Π° бСзопасно ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅ ΠΏΠΎ ΠΊΠΎΠΌΡƒΠ½ΠΈΠΊΠ°Ρ†ΠΈΠΎΠ½Π΅Π½ ΠΊΠ°Π½Π°Π». Π”Ρ€ΡƒΠ³ΠΈ пък смятат, Ρ‡Π΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ½Π°Ρ‚Π° криптография Π΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π° само Π·Π° ΠΌΠ°Π»Ρ†ΠΈΠ½Π° ΠΈ Π΅ ΠΏΡ€ΠΈΠ΅ΠΌΠ»ΠΈΠ²ΠΎ, Ρ‡Π΅ Π±ΠΎΠ³Π°Ρ‚ΠΈΡ‚Π΅ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΊΠ°Ρ‚ΠΎ Telegram с матСматичСски олимпиадисти Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚ бСзопасСн ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ».

Всичко Ρ‚ΠΎΠ²Π° ΠΌΠ΅ ΠΏΠΎΠ΄Ρ‚ΠΈΠΊΠ½Π° Π΄Π° напиша Ρ‚Π°Π·ΠΈ статия, Π·Π° Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ°, Ρ‡Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° криптографски ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ ΠΈ бСзопасСн IM Π½Π΅ Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° слоТна Π·Π°Π΄Π°Ρ‡Π°. ΠžΠ±Π°Ρ‡Π΅, Π½Π΅ Π΅ Ρ€Π°Π·ΡƒΠΌΠ½ΠΎ Π΄Π° сС изобрСтяват собствСни ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ Π·Π° удостовСряванС ΠΈ споразумяванС Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅.

Π“ΠžΠ‘Π’Π˜Πœ: P2P F2F E2EE IM Π·Π° Π΅Π΄ΠΈΠ½ Π²Π΅Ρ‡Π΅Ρ€ с Π“ΠžΠ‘Π’-криптография
Π’ статията Ρ‰Π΅ бъдС описан peer-to-peer, friend-to-friend, end-to-end ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°Π½ инстантСн ΠΌΠ΅ΡΡΠ΅Π½Π΄ΠΆΡŠΡ€ с SIGMA-I ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π·Π° удостовСряванС ΠΈ споразумяванС Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ (Π½Π° Π±Π°Π·Π°Ρ‚Π° Π½Π° ΠΊΠΎΠΉΡ‚ΠΎ Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ IPsec IKE), ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ изцяло Π“ΠžΠ‘Π’ криптографски Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΈ ΠΎΡ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° PyGOST ΠΈ ASN.1 ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° PyDERASN (Π·Π° която Π²Π΅Ρ‡Π΅ писах ΠΏΡ€Π΅Π΄ΠΈ). НСобходимо условиС: Ρ‚ΠΎΠΉ трябва Π΄Π° бъдС Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° прост, Ρ‡Π΅ Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС напишС ΠΎΡ‚ Π½ΡƒΠ»Π° Π·Π° Π΅Π΄ΠΈΠ½ Π²Π΅Ρ‡Π΅Ρ€ (ΠΈΠ»ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅Π½ Π΄Π΅Π½), ΠΈΠ½Π°Ρ‡Π΅ Ρ‚ΠΎΠ²Π° Π²Π΅Ρ‡Π΅ Π½Π΅ Π΅ проста ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°. Π’ нСя със сигурност ΠΈΠΌΠ° Π³Ρ€Π΅ΡˆΠΊΠΈ, излишна слоТност, нСдоразумСния, плюс Ρ‚ΠΎΠ²Π° Π΅ моята ΠΏΡŠΡ€Π²Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° с ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° asyncio.

Π”ΠΈΠ·Π°ΠΉΠ½ Π½Π° IM

ΠŸΡŠΡ€Π²ΠΎ, трябва Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΊΠ°ΠΊ Ρ‰Π΅ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Π½Π°ΡˆΠΈΡΡ‚ IM. Π—Π° простота, Π½Π΅ΠΊΠ° бъдС peer-to-peer ΠΌΡ€Π΅ΠΆΠ°, Π±Π΅Π· ΠΎΡ‚ΠΊΡ€ΠΈΠ²Π°Π½Π΅ Π½Π° участницитС. Π ΡŠΡ‡Π½ΠΎ Ρ‰Π΅ посочвамС Π½Π° какъв адрСс: ΠΏΠΎΡ€Ρ‚ Π΄Π° сС ΡΠ²ΡŠΡ€Π·Π²Π°ΠΌΠ΅ Π·Π° комуникация с Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π°.

Π Π°Π·Π±ΠΈΡ€Π°ΠΌ, Ρ‡Π΅ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π·Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅Ρ‚ΠΎ Π½Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Π²Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΈ ΠΊΠΎΠΌΠΏΡŽΡ‚ΡŠΡ€Π° Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Π·Π° практичСския IM. Но ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚ всякакви NAT-травСрс ΠΊΠ°ΠΏΠ°Π½ΠΈ, Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΠΏΠΎ-дълго Ρ‰Π΅ останСм Π² IPv4 ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ с Ρ€Π°Π·ΠΎΡ‡Π°Ρ€ΠΎΠ²Π°Ρ‰Π°Ρ‚Π° вСроятност Π·Π° Π²Ρ€ΡŠΠ·ΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΈ ΠΊΠΎΠΌΠΏΡŽΡ‚Ρ€ΠΈ. Как ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ‚ΠΎΠ»Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ ΠΎΡ‚ΡΡŠΡΡ‚Π²ΠΈΠ΅Ρ‚ΠΎ Π½Π° IPv6 Ρƒ Π΄ΠΎΠΌΠ° ΠΈ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°?

Π©Π΅ ΠΈΠΌΠ°ΠΌΠ΅ friend-to-friend ΠΌΡ€Π΅ΠΆΠ°: всички възмоТни ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈ трябва Π΄Π° са извСстни ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ. ΠŸΡŠΡ€Π²ΠΎ, Ρ‚ΠΎΠ²Π° Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ улСснява всичко: прСдставямС сС, Π½Π°ΠΌΠΈΡ€Π°ΠΌΠ΅ ΠΈΠ»ΠΈ Π½Π΅ Π½Π°ΠΌΠΈΡ€Π°ΠΌΠ΅ ΠΈΠΌΠ΅/ΠΊΠ»ΡŽΡ‡, ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π²Π°ΠΌΠ΅ ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ°Π²Π°ΠΌΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°, Π·Π½Π°Π΅ΠΉΠΊΠΈ събСсСдника. Π’Ρ‚ΠΎΡ€ΠΎ, ΠΏΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ, Ρ‚ΠΎΠ²Π° Π΅ сигурно ΠΈ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π²Π° мноТСство Π°Ρ‚Π°ΠΊΠΈ.

Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡŠΡ‚ Π½Π° IM-Π° Ρ‰Π΅ бъдС близък Π΄ΠΎ класичСскитС Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ. suckless-ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠΈ харСсват Π·Π°Ρ€Π°Π΄ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΠ·ΠΌΠ° си ΠΈ философията Π½Π° Unix-way. IM ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π·Π° всСки събСсСдник създава дирСктория с Ρ‚Ρ€ΠΈ Unix domain socket:

  • in β€” Π² Π½Π΅Π³ΠΎ сС записват ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½ΠΈΡ‚Π΅ Π½Π° събСсСдника ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ;
  • out β€” ΠΎΡ‚ Π½Π΅Π³ΠΎ сС Ρ‡Π΅Ρ‚Π°Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½ΠΈΡ‚Π΅ ΠΎΡ‚ събСсСдника ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ;
  • state β€” Ρ‡Π΅Ρ‚Π΅ΠΉΠΊΠΈ ΠΎΡ‚ Π½Π΅Π³ΠΎ, Ρ€Π°Π·Π±ΠΈΡ€Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΠΊΡŠΡ‚ Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π°, адрСс/ΠΏΠΎΡ€Ρ‚ Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ.

ОсвСн Ρ‚ΠΎΠ²Π°, сС създава conn сокСт, записвайки Π² Π½Π΅Π³ΠΎ хост ΠΏΠΎΡ€Ρ‚Π°, ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€Π°ΠΌΠ΅ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ с отдалСчСния събСсСдник.

|-- alice
|   |-- in
|   |-- out
|   `-- state
|-- bob
|   |-- in
|   |-- out
|   `-- state
`- conn

Π’ΠΎΠ·ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ позволява нСзависими Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π° IM транспорта ΠΈ потрСбитСлския интСрфСйс, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Π½Π° вкус ΠΈ Ρ†Π²Π΅Ρ‚ приятСли няма, Π½Π΅ моТСш Π΄Π° ΡƒΠ³ΠΎΠ΄ΠΈΡˆ Π½Π° всички. Използвайки tmux ΠΈ/ΠΈΠ»ΠΈ multitail, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠ°Π½Π΅Π»Π΅Π½ интСрфСйс с синтактична подсвСтка. А с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° rlwrap ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ Ρ€Π΅Π΄ Π·Π° въвСТданС Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ с GNU Readline.

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ‚Π΅ Π½Π° suckless ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ FIFO-Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅. Π›ΠΈΡ‡Π½ΠΎ Π°Π· Π½Π΅ успях Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π° ΠΊΠ°ΠΊ Π΄Π° работя с Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ Π² asyncio Π±Π΅Π· Ρ€ΡŠΡ‡Π½ΠΎ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½Π΅ ΠΎΡ‚ спСциални нишки (Π·Π° Ρ‚Π°ΠΊΠΈΠ²Π° Π½Π΅Ρ‰Π° ΠΎΡ‚Π΄Π°Π²Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ Π΅Π·ΠΈΠΊ Go). Π—Π°Ρ‚ΠΎΠ²Π° Ρ€Π΅ΡˆΠΈΡ… Π΄Π° сС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π°Π²Π°ΠΌ с Unix domain сокСти. Π—Π° съТалСниС, Ρ‚ΠΎΠ²Π° лишава Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π° Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ echo 2001:470:dead::babe 6666 > conn. Π Π΅ΡˆΠΈΡ… Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ socat: echo 2001:470:dead::babe 6666 | socat β€” UNIX-CONNECT:conn, socat READLINE UNIX-CONNECT:alice/in.

ΠŸΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π΅Π½ нСбСзопасСн ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»

ΠšΠ°Ρ‚ΠΎ транспорт сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° TCP: Ρ‚ΠΎΠΉ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π° доставката ΠΈ Ρ€Π΅Π΄Π° ѝ. UDP Π½Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π° Π½ΠΈΡ‚ΠΎ Π΅Π΄Π½ΠΎ ΠΎΡ‚ Π΄Π²Π΅Ρ‚Π΅ (ΠΊΠΎΠ΅Ρ‚ΠΎ Π±ΠΈ Π±ΠΈΠ»ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ сС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠΈ криптография), Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ°Ρ‚Π° Π½Π° SCTP Π² Python ΠΎΡ‚ кутията я няма.

Π—Π° съТалСниС, Π² TCP няма концСпция Π·Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅, Π° само ΠΏΠΎΡ‚ΠΎΠΊ ΠΎΡ‚ Π±Π°ΠΉΡ‚ΠΎΠ²Π΅. Π—Π°Ρ‚ΠΎΠ²Π° Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° измислим Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π³ΠΈ раздСлямС Π² Ρ‚ΠΎΠ·ΠΈ ΠΏΠΎΡ‚ΠΎΠΊ. МоТСм Π΄Π° сС Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ символ Π·Π° Π½ΠΎΠ² Ρ€Π΅Π΄. Π—Π° Π½Π°Ρ‡Π°Π»ΠΎ Ρ‰Π΅ Π΅ подходящо, Π½ΠΎ ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ Π΄Π° ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡΡ‚Π° си, Ρ‚ΠΎΠ·ΠΈ символ ΠΌΠΎΠΆΠ΅ Π΄Π° сС появи навсякъдС Π² криптотСкста. Π’ ΠΌΡ€Π΅ΠΆΠΈΡ‚Π΅ Π·Π°Ρ‚ΠΎΠ²Π° са популярни ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΏΡŠΡ€Π²ΠΎ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ Π΄ΡŠΠ»ΠΆΠΈΠ½Π°Ρ‚Π° Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π² Π±Π°ΠΉΡ‚ΠΎΠ²Π΅. НапримСр, Π² Python ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ ΠΈΠΌΠ° xdrlib, която позволява Ρ€Π°Π±ΠΎΡ‚Π° с ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚. XDR.

Няма Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ ΠΈ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ със Ρ‡Π΅Ρ‚Π΅Π½Π΅Ρ‚ΠΎ ΠΎΡ‚ TCP β€” Ρ‰Π΅ опростим ΠΊΠΎΠ΄Π°. Π§Π΅Ρ‚Π΅ΠΌ Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ» Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ сокСта, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ Π½Π΅ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡŠΠ»Π½ΠΎΡ‚ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅. ΠšΠ°Ρ‚ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΈ JSON с XML. Но, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ криптография, Π΄Π°Π½Π½ΠΈΡ‚Π΅ Ρ‰Π΅ трябва Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ подписани ΠΈ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½ΠΈ β€” Π° Ρ‚ΠΎΠ²Π° Ρ‰Π΅ изисква Π±Π°ΠΉΡ‚-Π²-Π±Π°ΠΉΡ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½ΠΎ прСдставянС Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈΡ‚Π΅, ΠΊΠΎΠ΅Ρ‚ΠΎ JSON/XML Π½Π΅ осигуряват (готовият Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Ρ€Π°Π·Π»ΠΈΡ‡Π°Π²Π°).

XDR Π΅ подходящ Π·Π° Ρ‚Π°Π·ΠΈ Π·Π°Π΄Π°Ρ‡Π°, Π½ΠΎ Π°Π· ΠΈΠ·Π±ΠΈΡ€Π°ΠΌ ASN.1 с DER-ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅ ΠΈ PyDERASN Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π°, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‰Π΅ Ρ€Π°Π·ΠΏΠΎΠ»Π°Π³Π°ΠΌΠ΅ с високостСпСнни ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, с ΠΊΠΎΠΈΡ‚ΠΎ чСсто Π΅ ΠΏΠΎ-приятно ΠΈ ΡƒΠ΄ΠΎΠ±Π½ΠΎ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌ. Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ бСзсхСмни bencode, MessagePack ΠΈΠ»ΠΈ CBOR, ASN.1 Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ Ρ‰Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈ Π΄Π°Π½Π½ΠΈΡ‚Π΅ срСщу строго Π·Π°Π΄Π°Π΄Π΅Π½Π° схСма.

# Msg ::= CHOICE {
#       text      MsgText,
#       handshake [0] EXPLICIT MsgHandshake }
class Msg(Choice):
    schema = ((
        ("text", MsgText()),
        ("handshake", MsgHandshake(expl=tag_ctxc(0))),
    ))

# MsgText ::= SEQUENCE {
#       text UTF8String (SIZE(1..MaxTextLen))}
class MsgText(Sequence):
    schema = ((
        ("text", UTF8String(bounds=(1, MaxTextLen))),
    ))

# MsgHandshake ::= SEQUENCE {
#       peerName UTF8String (SIZE(1..256)) }
class MsgHandshake(Sequence):
    schema = ((
        ("peerName", UTF8String(bounds=(1, 256))),
    ))

ΠŸΡ€ΠΈΠ΅ΠΌΠ°Π½ΠΎΡ‚ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Ρ‰Π΅ бъдС Msg: ΠΈΠ»ΠΈ тСкстово MsgText (Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° с Π΅Π΄Π½ΠΎ тСкстово ΠΏΠΎΠ»Π΅), ΠΈΠ»ΠΈ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅ MsgHandshake (Π² ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΏΡ€Π΅Π΄Π°Π²Π° ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° събСсСдника). Π’ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΡ€Π΅ΠΊΠ°Π»Π΅Π½ΠΎ слоТно, Π½ΠΎ Ρ‚ΠΎΠ²Π° Π΅ основа Π·Π° Π±ΡŠΠ΄Π΅Ρ‰Π΅Ρ‚ΠΎ.

     β”Œβ”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”
     β”‚PeerAβ”‚            β”‚PeerBβ”‚
     β””β”€β”€β”¬β”€β”€β”˜            β””β”€β”€β”¬β”€β”€β”˜
        β”‚MsgHandshake(IdA) β”‚
        │─────────────────>β”‚
        β”‚                  β”‚
        β”‚MsgHandshake(IdB) β”‚
        β”‚β”‚
        β”‚                  β”‚
        β”‚    MsgText()     β”‚
        β”‚<─────────────────│
        β”‚                  β”‚

IM Π±Π΅Π· криптография

ΠšΠ°ΠΊΡ‚ΠΎ Π²Π΅Ρ‡Π΅ ΠΊΠ°Π·Π°Ρ…, Π·Π° всички ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ със сокСти Ρ‰Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° asyncio. Π”Π° обявим ΠΊΠ°ΠΊΠ²ΠΎ ΠΎΡ‡Π°ΠΊΠ²Π°ΠΌΠ΅ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° стартиранС:

parser = argparse.ArgumentParser(description="GOSTIM")
parser.add_argument(
    "--our-name",
    required=True,
    help="ΠΠ°ΡˆΠ΅Ρ‚ΠΎ ΠΈΠΌΠ΅ Π½Π° Π²Ρ€ΡŠΡΡ‚Π½ΠΈΠΊΠ°",
)
parser.add_argument(
    "--their-names",
    required=True,
    help="Нами Π½Π° Π²Ρ€ΡŠΡΡ‚Π½ΠΈΡ†ΠΈΡ‚Π΅, Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ΠΈ с запСтая",
)
parser.add_argument(
    "--bind",
    default="::1",
    help="АдрСс Π·Π° ΡΠ»ΡƒΡˆΠ°Π½Π΅",
)
parser.add_argument(
    "--port",
    type=int,
    default=6666,
    help="ΠŸΠΎΡ€Ρ‚ Π·Π° ΡΠ»ΡƒΡˆΠ°Π½Π΅",
)
args = parser.parse_args()
OUR_NAME = UTF8String(args.our_name)
THEIR_NAMES = set(args.their_names.split(","))

Π—Π°Π΄Π°Π²Π° сС собствСно ΠΈΠΌΠ΅ (β€”our-name alice). Π§Ρ€Π΅Π· запСтая сС изброяват всички ΠΎΡ‡Π°ΠΊΠ²Π°Π½ΠΈ Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΡ†ΠΈ (β€”their-names bob,eve). Π—Π° всСки ΠΎΡ‚ Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΡ†ΠΈΡ‚Π΅ сС създава дирСктория с Unix сокСти, Π° ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° ΠΈ ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π·Π° всСки in, out, state:

for peer_name in THEIR_NAMES:
    makedirs(peer_name, mode=0o700, exist_ok=True)
    out_queue = asyncio.Queue()
    OUT_QUEUES[peer_name] = out_queue
    asyncio.ensure_future(asyncio.start_unix_server(
        partial(unixsock_out_processor, out_queue=out_queue),
        path.join(peer_name, "out"),
    ))
    in_queue = asyncio.Queue()
    IN_QUEUES[peer_name] = in_queue
    asyncio.ensure_future(asyncio.start_unix_server(
        partial(unixsock_in_processor, in_queue=in_queue),
        path.join(peer_name, "in"),
    ))
    asyncio.ensure_future(asyncio.start_unix_server(
        partial(unixsock_state_processor, peer_name=peer_name),
        path.join(peer_name, "state"),
    ))
asyncio.ensure_future(asyncio.start_unix_server(unixsock_conn_processor, "conn"))

ΠŸΡ€ΠΈΡ…ΠΎΠ΄ΡΡ‰ΠΈΡ‚Π΅ ΠΎΡ‚ потрСбитСля ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ ΠΎΡ‚ in сокСта сС ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ Π² IN_QUEUES ΠΎΠΏΠ°ΡˆΠΊΠΈΡ‚Π΅:

async def unixsock_in_processor(reader, writer, in_queue: asyncio.Queue) -> None:
    while True:
        text = await reader.read(MaxTextLen)
        if text == b"":
            break
        await in_queue.put(text.decode("utf-8"))

ΠŸΡ€ΠΈΡ…ΠΎΠ΄ΡΡ‰ΠΈΡ‚Π΅ ΠΎΡ‚ Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΡ†ΠΈΡ‚Π΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ сС ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ Π² OUT_QUEUES ΠΎΠΏΠ°ΡˆΠΊΠΈΡ‚Π΅, ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ Π΄Π°Π½Π½ΠΈΡ‚Π΅ сС записват Π² out сокСта:

async def unixsock_out_processor(reader, writer, out_queue: asyncio.Queue) -> None:
    while True:
        text = await out_queue.get()
        writer.write(("[%s] %s" % (datetime.now(), text)).encode("utf-8"))
        await writer.drain()

ΠŸΡ€ΠΈ Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΎΡ‚ state сокСта, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ‚ΡŠΡ€ΡΠΈ Π² PEER_ALIVE Ρ€Π΅Ρ‡Π½ΠΈΠΊΠ° адрСса Π½Π° Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΠΊΠ°. Ако няма ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ с Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΠΊΠ°, записва сС ΠΏΡ€Π°Π·Π΅Π½ Π½ΠΈΠ·.

async def unixsock_state_processor(reader, writer, peer_name: str) -> None:
    peer_writer = PEER_ALIVES.get(peer_name)
    writer.write(
        b"" if peer_writer is None else (" ".join([
            str(i) for i in peer_writer.get_extra_info("peername")[:2]
        ]).encode("utf-8") + b"n")
    )
    await writer.drain()
    writer.close()

ΠŸΡ€ΠΈ записванСто Π½Π° адрСса Π² conn сокСта стартира функцията Π½Π° β€žΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π°β€œ Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ:

async def unixsock_conn_processor(reader, writer) -> None:
    data = await reader.read(256)
    writer.close()
    host, port = data.decode("utf-8").split(" ")
    await initiator(host=host, port=int(port))

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π°. ΠŸΡŠΡ€Π²ΠΎ, Ρ‚ΠΎΠΉ ΠΎΡ‚ΠΊΡ€ΠΈΠ²Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ към посочСния хост/ΠΏΠΎΡ€Ρ‚ ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅ с ΠΈΠΌΠ΅Ρ‚ΠΎ си:

 130 async def initiator(host, port):
 131     _id = repr((host, port))
 132     logging.info("%s: dialing", _id)
 133     reader, writer = await asyncio.open_connection(host, port)
 134     # Handshake message {{{
 135     writer.write(Msg(("handshake", MsgHandshake((
 136         ("peerName", OUR_NAME),
 137     )))).encode())
 138     # }}}
 139     await writer.drain()

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΠΈΠ·Ρ‡Π°ΠΊΠ²Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ ΠΎΡ‚ ΠΎΡ‚Π΄Π°Π»Π΅Ρ‡Π΅Π½Π°Ρ‚Π° страна. ΠžΠΏΠΈΡ‚Π²Π° сС Π΄Π° Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ ΠΏΠΎ схСмата Msg ASN.1. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌ, Ρ‡Π΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Ρ‰Π΅ бъдС ΠΈΠ·ΠΏΡ€Π°Ρ‚Π΅Π½ΠΎ Π² Π΅Π΄ΠΈΠ½ TCP сСгмСнт ΠΈ Ρ‰Π΅ Π³ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π² Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅ ΠΏΡ€ΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° .read(). ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ наистина смС ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π·Π° handshake.

 141     # Π˜Π·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ Π½Π° Handshake ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ {{{
 142     data = await reader.read(256)
 143     if data == b"":
 144         logging.warning("%s: no answer, disconnecting", _id)
 145         writer.close()
 146         return
 147     try:
 148         msg, _ = Msg().decode(data)
 149     except ASN1Error:
 150         logging.warning("%s: undecodable answer, disconnecting", _id)
 151         writer.close()
 152         return
 153     logging.info("%s: got %s message", _id, msg.choice)
 154     if msg.choice != "handshake":
 155         logging.warning("%s: unexpected message, disconnecting", _id)
 156         writer.close()
 157         return
 158     # }}}

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΡ‚ΠΎ ΠΈΠΌΠ΅ Π½Π° събСсСдника Π½ΠΈ Π΅ извСстно. Ако Π½Π΅ Π΅, ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π°ΠΌΠ΅ Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ Π²Π΅Ρ‡Π΅ ΠΈΠΌΠ°ΠΌΠ΅ установСна Π²Ρ€ΡŠΠ·ΠΊΠ° с Π½Π΅Π³ΠΎ (ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΠΊΡŠΡ‚ ΠΎΡ‚Π½ΠΎΠ²ΠΎ Π΅ ΠΏΠΎΠ΄Π°Π» ΠΊΠΎΠΌΠ°Π½Π΄Π° Π·Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅) ΠΈ я затварямС. Π’ IN_QUEUES сС поставят Python Π½ΠΈΠ·ΠΎΠ²Π΅ с тСкста Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ, Π½ΠΎ ΠΈΠΌΠ° особСна стойност None, сигнализираща Π½Π° ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°Ρ‚Π° msg_sender Π΄Π° спрС Ρ€Π°Π±ΠΎΡ‚Π°, Π·Π° Π΄Π° Π·Π°Π±Ρ€Π°Π²ΠΈ Π·Π° своя writer, ΡΠ²ΡŠΡ€Π·Π°Π½ с остарялото TCP съСдинСниС.

 159     msg_handshake = msg.value
 160     peer_name = str(msg_handshake["peerName"])
 161     if peer_name not in THEIR_NAMES:
 162         logging.warning("unknown peer name: %s", peer_name)
 163         writer.close()
 164         return
 165     logging.info("%s: session established: %s", _id, peer_name)
 166     # Π‘Ρ‚Π°Ρ€Ρ‚ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‡Π° Π½Π° тСкстови ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ€Π° Π½Π° транспорта {{{
 167     peer_alive = PEER_ALIVES.pop(peer_name, None)
 168     if peer_alive is not None:
 169         peer_alive.close()
 170         await IN_QUEUES[peer_name].put(None)
 171     PEER_ALIVES[peer_name] = writer
 172     asyncio.ensure_future(msg_sender(peer_name, writer))
 173     # }}}

msg_sender ΠΏΡ€ΠΈΠ΅ΠΌΠ° изходящитС ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ (поставСни Π² ΠΎΠΏΠ°ΡˆΠΊΠ°Ρ‚Π° ΠΎΡ‚ входящия сокСт), сСриализира Π³ΠΈ Π² ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ MsgText ΠΈ Π³ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° ΠΏΠΎ TCP ΡΡŠΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ. Π’ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π΅ ΠΏΠΎ всяко Π²Ρ€Π΅ΠΌΠ΅ β€” ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΈΠ·Ρ€ΠΈΡ‡Π½ΠΎ уловявамС.

async def msg_sender(peer_name: str, writer) -> None:
    in_queue = IN_QUEUES[peer_name]
    while True:
        text = await in_queue.get()
        if text is None:
            break
        writer.write(Msg(("text", MsgText((
            ("text", UTF8String(text)),
        )))).encode())
        try:
            await writer.drain()
        except ConnectionResetError:
            del PEER_ALIVES[peer_name]
            return
        logging.info("%s: sent %d characters message", peer_name, len(text))

Π’ края ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ Π²Π»ΠΈΠ·Π° Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ» Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ ΠΎΡ‚ сокСта. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ²Π° Π΄Π°Π»ΠΈ са тСкстови ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ ΠΈ Π³ΠΈ поставя Π² OUT_QUEUES ΠΎΠΏΠ°ΡˆΠΊΠ°Ρ‚Π°, ΠΎΡ‚ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ ΠΈΠ·ΠΏΡ€Π°Ρ‚Π΅Π½ΠΈ Π² изходния сокСт Π½Π° ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΈΡ събСсСдник. Π—Π°Ρ‰ΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ просто Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ .read() ΠΈ Π΄Π° Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ? Π—Π°Ρ‰ΠΎΡ‚ΠΎ Π½Π΅ Π΅ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½Π° ситуацията, Π² която няколко ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ ΠΎΡ‚ потрСбитСля са Π°Π³Ρ€Π΅Π³ΠΈΡ€Π°Π½ΠΈ Π² Π±ΡƒΡ„Π΅Ρ€Π° Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° систСма ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‚Π΅Π½ΠΈ Π² Π΅Π΄ΠΈΠ½ TCP сСгмСнт. Π©Π΅ успССм Π΄Π° Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡŠΡ€Π²ΠΎΡ‚ΠΎ, Π° Π² Π±ΡƒΡ„Π΅Ρ€Π° ΠΌΠΎΠΆΠ΅ Π΄Π° останС част ΠΎΡ‚ слСдващото. ΠŸΡ€ΠΈ всяка ΠΈΠ·Π²ΡŠΠ½Ρ€Π΅Π΄Π½Π° ситуация затварямС TCP Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π° ΠΈ спирамС msg_sender ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°Ρ‚Π° (ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°ΠΉΠΊΠΈ None Π² OUT_QUEUES ΠΎΠΏΠ°ΡˆΠΊΠ°Ρ‚Π°).

 174     buf = b""
 175     # Π˜Π·Ρ‡Π°ΠΊΠ°ΠΉΡ‚Π΅ тСстови ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ {{{
 176     while True:
 177         data = await reader.read(MaxMsgLen)
 178         if data == b"":
 179             break
 180         buf += data
 181         if len(buf) > MaxMsgLen:
 182             logging.warning("%s: ΠΏΡ€Π΅Π²ΠΈΡˆΠ΅Π½Π° максимална Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° Π½Π° Π±ΡƒΡ„Π΅Ρ€Π°", _id)
 183             break
 184         try:
 185             msg, tail = Msg().decode(buf)
 186         except ASN1Error:
 187             continue
 188         buf = tail
 189         if msg.choice != "text":
 190             logging.warning("%s: Π½Π΅ΠΎΡ‡Π°ΠΊΠ²Π°Π½ΠΎ %s ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅", _id, msg.choice)
 191             break
 192         try:
 193             await msg_receiver(msg.value, peer_name)
 194         except ValueError as err:
 195             logging.warning("%s: %s", err)
 196             break
 197     # }}}
 198     logging.info("%s: ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°: %s", _id, peer_name)
 199     IN_QUEUES[peer_name].put(None)
 200     writer.close()

  66 async def msg_receiver(msg_text: MsgText, peer_name: str) -> None:
  67     text = str(msg_text["text"])
  68     logging.info("%s: ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ с %d Π·Π½Π°ΠΊΠ°", peer_name, len(text))
  69     await OUT_QUEUES[peer_name].put(text)

НСка сС Π²ΡŠΡ€Π½Π΅ΠΌ към основния ΠΊΠΎΠ΄. Π‘Π»Π΅Π΄ ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° всички ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½ΠΈ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° стартиранС Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, стартирамС TCP ΡΡŠΡ€Π²ΡŠΡ€. Π—Π° всяка установСна Π²Ρ€ΡŠΠ·ΠΊΠ° Ρ‚ΠΎΠΉ създава responder (ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€Π½ΠΈΠΊ) ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°.

logging.basicConfig(
    level=logging.INFO,
    format="%(levelname)s %(asctime)s: %(funcName)s: %(message)s",
)
loop = asyncio.get_event_loop()
server = loop.run_until_complete(asyncio.start_server(responder, args.bind, args.port))
logging.info("Π‘Π»ΡƒΡˆΠ°Π½Π΅ Π½Π°: %s", server.sockets[0].getsockname())
loop.run_forever()

responder Π΅ ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ Π½Π° initiator ΠΈ Π·Π΅Ρ€ΠΊΠ°Π»Π½ΠΎ изпълнява всички ΡΡŠΡ‰ΠΈΡ‚Π΅ дСйствия, Π½ΠΎ бСзкрайният Ρ†ΠΈΠΊΡŠΠ» Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ сС стартира Π²Π΅Π΄Π½Π°Π³Π°, Π·Π° ΠΏΠΎ-голяма простота. Π’ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΡŠΡ‚ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° ΠΏΠΎ Π΅Π΄Π½ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ ΠΎΡ‚ всяка страна, Π½ΠΎ впослСдствиС Ρ‰Π΅ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° ΠΏΠΎ Π΄Π²Π΅ ΠΎΡ‚ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π° Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°, слСд ΠΊΠΎΠ΅Ρ‚ΠΎ Π²Π΅Π΄Π½Π°Π³Π° Π΅ възмоТно ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅Ρ‚ΠΎ Π½Π° тСкстови.

  72 async def responder(reader, writer):
  73     _id = writer.get_extra_info("peername")
  74     logging.info("%s: connected", _id)
  75     buf = b""
  76     msg_expected = "handshake"
  77     peer_name = None
  78     while True:
  79         # Read until we get Msg message {{{
  80         data = await reader.read(MaxMsgLen)
  81         if data == b"":
  82             logging.info("%s: closed connection", _id)
  83             break
  84         buf += data
  85         if len(buf) > MaxMsgLen:
  86             logging.warning("%s: max buffer size exceeded", _id)
  87             break
  88         try:
  89             msg, tail = Msg().decode(buf)
  90         except ASN1Error:
  91             continue
  92         buf = tail
  93         # }}}
  94         if msg.choice != msg_expected:
  95             logging.warning("%s: unexpected %s message", _id, msg.choice)
  96             break
  97         if msg_expected == "text":
  98             try:
  99                 await msg_receiver(msg.value, peer_name)
 100             except ValueError as err:
 101                 logging.warning("%s: %s", err)
 102                 break
 103         # Process Handshake message {{{
 104         elif msg_expected == "handshake":
 105             logging.info("%s: got %s message", _id, msg_expected)
 106             msg_handshake = msg.value
 107             peer_name = str(msg_handshake["peerName"])
 108             if peer_name not in THEIR_NAMES:
 109                 logging.warning("unknown peer name: %s", peer_name)
 110                 break
 111             writer.write(Msg(("handshake", MsgHandshake((
 112                 ("peerName", OUR_NAME),
 113             )))).encode())
 114             await writer.drain()
 115             logging.info("%s: session established: %s", _id, peer_name)
 116             peer_alive = PEER_ALIVES.pop(peer_name, None)
 117             if peer_alive is not None:
 118                 peer_alive.close()
 119                 await IN_QUEUES[peer_name].put(None)
 120             PEER_ALIVES[peer_name] = writer
 121             asyncio.ensure_future(msg_sender(peer_name, writer))
 122             msg_expected = "text"
 123         # }}}
 124     logging.info("%s: disconnecting", _id)
 125     if msg_expected == "text":
 126         IN_QUEUES[peer_name].put(None)
 127     writer.close()

Π‘ΠΈΠ³ΡƒΡ€Π΅Π½ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»

Π’Ρ€Π΅ΠΌΠ΅ Π΅ Π΄Π° осигурим Π½Π°ΡˆΠ΅Ρ‚ΠΎ комуникация. Какво Ρ€Π°Π·Π±ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΠ΄ сигурност ΠΈ ΠΊΠ°ΠΊΠ²ΠΎ искамС:

  • конфидСнциалност Π½Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½ΠΈΡ‚Π΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ;
  • автСнтичност ΠΈ цСлостност Π½Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½ΠΈΡ‚Π΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ β€” всяка промяна трябва Π΄Π° бъдС установСна;
  • Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ Π°Ρ‚Π°ΠΊΠΈ с ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΠ·Π»ΡŠΡ‡Π²Π°Π½Π΅ (replay attack) β€” Ρ„Π°ΠΊΡ‚ΡŠΡ‚ Π·Π° Π·Π°Π³ΡƒΠ±Π° ΠΈΠ»ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π΅Π½ΠΈΠ΅ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ трябва Π΄Π° бъдС ΠΎΡ‚ΠΊΡ€ΠΈΡ‚ (ΠΈ Ρ€Π΅ΡˆΠ°Π²Π°ΠΌΠ΅ Π΄Π° ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π΅ΠΌ Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°);
  • идСнтификация ΠΈ автСнтикация Π½Π° участницитС ΠΏΠΎ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Π·Π°Π΄Π°Π΄Π΅Π½ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ β€” Π²Π΅Ρ‡Π΅ Ρ€Π΅ΡˆΠΈΡ…ΠΌΠ΅, Ρ‡Π΅ създавамС peer-to-peer ΠΌΡ€Π΅ΠΆΠ°. Π‘Π°ΠΌΠΎ слСд автСнтикация Ρ‰Π΅ Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ с ΠΊΠΎΠ³ΠΎ ΠΎΠ±Ρ‰ΡƒΠ²Π°ΠΌΠ΅;
  • Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΏΠ΅Ρ€Ρ„Π΅ΠΊΡ‚Π½Π° Π½Π°ΠΏΡ€Π΅Π΄Π½ΠΈΠ½Π° Ρ‚Π°ΠΉΠ½Π° свойства (PFS) β€” ΠΊΠΎΠΌΠΏΡ€ΠΎΠΌΠ΅Ρ‚ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° нашия Π΄ΡŠΠ»Π³ΠΎΡΡ€ΠΎΡ‡Π΅Π½ ΠΊΠ»ΡŽΡ‡ Π·Π° подписи Π½Π΅ трябва Π΄Π° Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ Π½Π° ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π° корСспондСнция. Π—Π°ΠΏΠΈΡΡŠΡ‚ Π½Π° прихванатия Ρ‚Ρ€Π°Ρ„ΠΈΠΊ става Π±Π΅Π·ΠΏΠΎΠ»Π΅Π·Π΅Π½;
  • валидността Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡΡ‚Π° (транспортнитС ΠΈ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅) Π²Π°ΠΆΠΈ само Π² ΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ Π½Π° Π΅Π΄Π½Π° TCP сСсия. Π’ΠΌΡŠΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ подписани/Π°Π²Ρ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½ΠΈ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π° сСсия (Π΄ΠΎΡ€ΠΈ с Ρ‚ΠΎΠ·ΠΈ ΡΡŠΡ‰ΠΈΡ събСсСдник) Π½Π΅ трябва Π΄Π° Π΅ възмоТно;
  • пасивният Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚Π΅Π» Π½Π΅ трябва Π΄Π° Π²ΠΈΠΆΠ΄Π° Π½ΠΈΡ‚ΠΎ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ Π½Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ, Π½ΠΈΡ‚ΠΎ ΠΏΡ€Π΅Π΄Π°Π²Π°Π½ΠΈ Π΄ΡŠΠ»Π³ΠΎΡΡ€ΠΎΡ‡Π½ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅, Π½ΠΈΡ‚ΠΎ Ρ…Π΅ΡˆΠΎΠ²Π΅ ΠΎΡ‚ тях. Някаква анонимност ΠΎΡ‚ пасивния Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚Π΅Π».

Π£Π΄ΠΈΠ²ΠΈΡ‚Π΅Π»Π½ΠΎ, Π½ΠΎ Ρ‚ΠΎΠ·ΠΈ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ практичСски всСки иска Π΄Π° ΠΈΠΌΠ° Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΈ Π΄Π° Π΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠ°Π»ΠΊΠΎ ΠΎΡ‚ ΠΈΠ·Π±Ρ€ΠΎΠ΅Π½ΠΎΡ‚ΠΎ Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка сС изпълнява Π·Π° "домашно" ΡΡŠΠ·Π΄Π°Π΄Π΅Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ. И сСга, Π΄Π° Π½Π΅ измислямС Π½ΠΎΠ²ΠΎ. Аз Π±ΠΈΡ… Π²ΠΈ ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π°Π» Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Noise framework Π·Π° ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ, Π½ΠΎ Π½Π΅ΠΊΠ° ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ Π½Π΅Ρ‰ΠΎ ΠΏΠΎ-просто.

Най-популярни са Π΄Π²Π° ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°:

  • TLS β€” Π½Π°ΠΉ-слоТният ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» с дълга история Π½Π° бъговС, ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ, уязвимости, лошо обмислянС, слоТноти ΠΈ пропуски (Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Ρ‚ΠΎΠ²Π° Π½Π΅ сС отнася Π΄ΠΎ TLS 1.3). Но Π½Π΅ Π³ΠΎ Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π°ΠΌΠ΅ Π·Π°Ρ€Π°Π΄ΠΈ ΠΏΡ€Π΅ΠΊΠ°Π»Π΅Π½Π° слоТност.
  • IPsec с IKE β€” нямат сСриозни криптографски ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ, Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ ΡΡŠΡ‰ΠΎ Π½Π΅ са прости. Ако ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ Π·Π° IKEv1 ΠΈ IKEv2, тСхният ΠΏΡ€ΠΎΠΈΠ·Ρ…ΠΎΠ΄ са STS, ISO/IEC IS 9798-3 ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈΡ‚Π΅ SIGMA (SIGn-and-MAc) β€” доста простички Π·Π° рСализация Π·Π° Π΅Π΄ΠΈΠ½ Π²Π΅Ρ‡Π΅Ρ€.

Какво ΠΏΡ€Π°Π²ΠΈ SIGMA, ΠΊΠ°Ρ‚ΠΎ послСдно Π·Π²Π΅Π½ΠΎ Π² Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠ΅Ρ‚ΠΎ Π½Π° STS/ISO ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈΡ‚Π΅, Π΄ΠΎΠ±Ρ€ΠΎ? Π’ΠΎΠΉ отговаря Π½Π° всичкитС Π½ΠΈ изисквания (Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ "скритиС" Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈΡ‚Π΅ Π½Π° ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈΡ‚Π΅), няма извСстни криптографски ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ. Π’ΠΎΠΉ Π΅ минималистичСн β€” ΠΏΡ€Π΅ΠΌΠ°Ρ…Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΠΎΠ½Π΅ Π΅Π΄ΠΈΠ½ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΎΡ‚ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Ρ‰Π΅ Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ Π½Π΅Π³ΠΎΠ²Π°Ρ‚Π° нСсигурност.

НСка ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ ΠΎΡ‚ Π½Π°ΠΉ-простия домашСн ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π΄ΠΎ SIGMA. Най-основната опСрация, която Π½ΠΈ интСрСсува, Π΅ ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅: функция, ΠΏΡ€ΠΈ която ΠΈ Π΄Π²Π°ΠΌΠ°Ρ‚Π° участници ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Ρ‚ Π΅Π΄Π½Π° ΠΈ ΡΡŠΡ‰Π° стойност, която ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΊΠ°Ρ‚ΠΎ симСтричСн ΠΊΠ»ΡŽΡ‡. Π‘Π΅Π· Π΄Π° Π½Π°Π²Π»ΠΈΠ·Π°ΠΌΠ΅ Π² подробности: всяка ΠΎΡ‚ странитС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° Π΅Ρ„ΠΈΠΌΠ΅Ρ€Π½Π° (ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π° само Π² ΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ Π½Π° Π΅Π΄Π½Π° сСсия) ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π° Π΄Π²ΠΎΠΉΠΊΠ° (ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ ΠΈ частСн ΠΊΠ»ΡŽΡ‡), обмСнят ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅, ΠΈΠ·Π²ΠΈΠΊΠ²Π°Ρ‚ функция Π·Π° ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½Π΅, Π½Π° Π²Ρ…ΠΎΠ΄Π° Π½Π° която ΠΏΠΎΠ΄Π°Π²Π°Ρ‚ своя частСн ΠΊΠ»ΡŽΡ‡ ΠΈ публичния ΠΊΠ»ΡŽΡ‡ Π½Π° събСсСдника.

β”Œβ”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”
β”‚PeerAβ”‚          β”‚PeerBβ”‚
β””β”€β”€β”¬β”€β”€β”˜          β””β”€β”€β”¬β”€β”€β”˜
   β”‚   IdA, PubA    β”‚ ╔════════════════════╗
   │───────────────>β”‚ β•‘PrvA, PubA = DHgen()β•‘
   β”‚                β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚   IdB, PubB    β”‚ ╔════════════════════╗
   β”‚<───────────────│ β•‘PrvB, PubB = DHgen()β•‘
   β”‚                β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   ────┐    ╔═══════╧════════════╗
       β”‚    β•‘Key = DH(PrvA, PubB)β•‘
   <β”€β”€β”€β”˜    β•šβ•β•β•β•β•β•β•β•€β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚                β”‚
   β”‚                β”‚

ВсС ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС намСсят ΠΈ Π΄Π° замСнят ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ със собствСнитС си β€” Π² Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» няма автСнтикация Π½Π° ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈΡ‚Π΅. НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ подпис с Π΄ΡŠΠ»Π³ΠΎΡΡ€ΠΎΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅.

β”Œβ”€β”€β”€β”€β”€β”                            β”Œβ”€β”€β”€β”€β”€β”
β”‚PeerAβ”‚                            β”‚PeerBβ”‚
β””β”€β”€β”¬β”€β”€β”˜                            β””β”€β”€β”¬β”€β”€β”˜
   β”‚IdA, PubA, sign(SignPrvA, (PubA)) β”‚ ╔═══════════════════════════╗
   │─────────────────────────────────>β”‚ β•‘SignPrvA, SignPubA = load()β•‘
   β”‚                                  β”‚ β•‘PrvA, PubA = DHgen()       β•‘
   β”‚                                  β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚IdB, PubB, sign(SignPrvB, (PubB)) β”‚ ╔═══════════════════════════╗
   β”‚<─────────────────────────────────│ β•‘SignPrvB, SignPubB = load()β•‘
   β”‚                                  β”‚ β•‘PrvB, PubB = DHgen()       β•‘
   β”‚                                  β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   ────┐    ╔═════════════════════╗   β”‚
       β”‚    β•‘verify(SignPubB, ...)β•‘   β”‚
   <β”€β”€β”€β”˜    β•‘Key = DH(PrvA, PubB) β•‘   β”‚
   β”‚        β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•   β”‚
   β”‚                                  β”‚

Вакъв подпис Π½Π΅ Π΅ подходящ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π½Π΅ Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½ с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Π° сСсия. Вакъв Ρ‚ΠΈΠΏ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ Ρ‰Π΅ β€žΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΡΡ‚β€œ ΠΈ Π·Π° сСсии с Π΄Ρ€ΡƒΠ³ΠΈ участници. ЦСлият контСкст трябва Π΄Π° бъдС подписан. Π’ΠΎΠ²Π° Π½Π°Π»Π°Π³Π° Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΎΡ‰Π΅ Π΅Π΄Π½ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ ΠΎΡ‚ A.

ОсвСн Ρ‚ΠΎΠ²Π°, Π΅ ΠΊΡ€ΠΈΡ‚ΠΈΡ‡Π½ΠΎ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΏΠΎΠ΄ подписа ΠΈ собствСн ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π΅Π½ случай ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΠΌ IdXXX ΠΈ Π΄Π° ΠΏΠ΅Ρ€Π΅ΠΏΠΎΠ΄ΠΏΠΈΡˆΠ΅ΠΌ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ с ΠΊΠ»ΡŽΡ‡Π° Π½Π° Π΄Ρ€ΡƒΠ³ извСстСн събСсСдник. Π—Π° Π΄Π° ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‚ΠΈΠΌ reflection Π°Ρ‚Π°ΠΊΠΈ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС ΡƒΠ²Π΅Ρ€ΠΈΡ‚Π΅, Ρ‡Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ ΠΏΠΎΠ΄ подписа са Ρ€Π°Π·ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈ Π½Π° строго ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ мСста спорСд своя смисъл: Π°ΠΊΠΎ A подписва (PubA, PubB), Ρ‚ΠΎ B трябва Π΄Π° подписва (PubB, PubA). Π’ΠΎΠ²Π° ΡΡŠΡ‰ΠΎ ΠΏΠΎΠ΄Ρ‡Π΅Ρ€Ρ‚Π°Π²Π° ваТността Π½Π° ΠΈΠ·Π±ΠΎΡ€Π° Π½Π° структура ΠΈ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π½Π° сСриализиранитС Π΄Π°Π½Π½ΠΈ. НапримСр, мноТСствата Π² ASN.1 DER ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅ сС сортират: SET OF(PubA, PubB) Ρ‰Π΅ бъдС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½ΠΎ Π½Π° SET OF(PubB, PubA).

β”Œβ”€β”€β”€β”€β”€β”                                       β”Œβ”€β”€β”€β”€β”€β”
β”‚PeerAβ”‚                                       β”‚PeerBβ”‚
β””β”€β”€β”¬β”€β”€β”˜                                       β””β”€β”€β”¬β”€β”€β”˜
   β”‚                 IdA, PubA                   β”‚ ╔═══════════════════════════╗
   │────────────────────────────────────────────>β”‚ β•‘SignPrvA, SignPubA = load()β•‘
   β”‚                                             β”‚ β•‘PrvA, PubA = DHgen()       β•‘
   β”‚                                             β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚IdB, PubB, sign(SignPrvB, (IdB, PubA, PubB)) β”‚ ╔═══════════════════════════╗
   β”‚<────────────────────────────────────────────│ β•‘SignPrvB, SignPubB = load()β•‘
   β”‚                                             β”‚ β•‘PrvB, PubB = DHgen()       β•‘
   β”‚                                             β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚     sign(SignPrvA, (IdA, PubB, PubA))       β”‚ ╔═════════════════════╗
   │────────────────────────────────────────────>β”‚ β•‘verify(SignPubB, ...)β•‘
   β”‚                                             β”‚ β•‘Key = DH(PrvA, PubB) β•‘
   β”‚                                             β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚                                             β”‚

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, всС ΠΎΡ‰Π΅ Π½Π΅ смС Β«Π΄ΠΎΠΊΠ°Π·Π°Π»ΠΈΒ», Ρ‡Π΅ смС ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π»ΠΈ Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ΠΈ ΠΎΠ±Ρ‰ ΠΊΠ»ΡŽΡ‡ Π·Π° Ρ‚Π°Π·ΠΈ сСсия. Π’ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΌΠΈΠ½Π΅ ΠΈ Π±Π΅Π· Ρ‚Π°Π·ΠΈ ΡΡ‚ΡŠΠΏΠΊΠ° β€” ΠΏΡŠΡ€Π²ΠΎΡ‚ΠΎ транспортно ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Ρ‰Π΅ бъдС Π½Π΅Π²Π°Π»ΠΈΠ΄Π½ΠΎ, Π½ΠΎ искамС, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅Ρ‚ΠΎ ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡ΠΈ, Π΄Π° смС ΡƒΠ²Π΅Ρ€Π΅Π½ΠΈ, Ρ‡Π΅ всичко дСйствитСлно Π΅ ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½ΠΎ. Към ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΈΠΌΠ°ΠΌΠ΅ ISO/IEC IS 9798-3 ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ».

МоТСм Π΄Π° подпишСм ΠΈ произвСдСния ΠΊΠ»ΡŽΡ‡. Π’ΠΎΠ²Π° Π΅ опасно, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π½Π΅ Π΅ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΎ Π² използвания Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ Π·Π° подписванС Π΄Π° ΠΈΠΌΠ° изтичания (Π΄ΠΎΡ€ΠΈ ΠΈ Π±ΠΈΡ‚ΠΎΠ²Π΅ Π·Π° подпис, Π½ΠΎ всС ΠΏΠ°ΠΊ изтичания). МоТСм Π΄Π° подпишСм Ρ…Π΅Ρˆ ΠΎΡ‚ произвСдСния ΠΊΠ»ΡŽΡ‡, Π½ΠΎ ΠΈΠ·Ρ‚ΠΈΡ‡Π°Π½Π΅Ρ‚ΠΎ Π΄ΠΎΡ€ΠΈ ΠΈ Π½Π° Ρ…Π΅ΡˆΠ° ΠΎΡ‚ произвСдСния ΠΊΠ»ΡŽΡ‡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° стойност ΠΏΡ€ΠΈ brute-force Π°Ρ‚Π°ΠΊΠ° срСщу функцията Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅. SIGMA ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° MAC функция, Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Ρ‰Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Π½Π° ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‡Π°.

β”Œβ”€β”€β”€β”€β”€β”                                            β”Œβ”€β”€β”€β”€β”€β”
β”‚PeerAβ”‚                                            β”‚PeerBβ”‚
β””β”€β”€β”¬β”€β”€β”˜                                            β””β”€β”€β”¬β”€β”€β”˜
   β”‚                    IdA, PubA                     β”‚ ╔═══════════════════════════╗
   │─────────────────────────────────────────────────>β”‚ β•‘SignPrvA, SignPubA = load()β•‘
   β”‚                                                  β”‚ β•‘PrvA, PubA = DHgen()       β•‘
   β”‚                                                  β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚IdB, PubB, sign(SignPrvB, (PubA, PubB)), MAC(IdB) β”‚ ╔═══════════════════════════╗
   β”‚<─────────────────────────────────────────────────│ β•‘SignPrvB, SignPubB = load()β•‘
   β”‚                                                  β”‚ β•‘PrvB, PubB = DHgen()       β•‘
   β”‚                                                  β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚                                                  β”‚ ╔═════════════════════╗
   β”‚     sign(SignPrvA, (PubB, PubA)), MAC(IdA)       β”‚ β•‘Key = DH(PrvA, PubB) β•‘
   │─────────────────────────────────────────────────>β”‚ β•‘verify(Key, IdB)     β•‘
   β”‚                                                  β”‚ β•‘verify(SignPubB, ...)β•‘
   β”‚                                                  β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚                                                  β”‚

ΠšΠ°Ρ‚ΠΎ оптимизация, някои ΠΌΠΎΠΆΠ΅ Π΄Π° ТСлаят Π΄Π° ΠΏΡ€Π΅ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ своитС Π΅Ρ„Π΅Ρ€Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ (ΠΊΠΎΠ΅Ρ‚ΠΎ, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π΅ ΠΆΠ°Π»ΠΊΠΎ Π·Π° PFS). НапримСр, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ…ΠΌΠ΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π° Π΄Π²ΠΎΠΉΠΊΠ°, ΠΎΠΏΠΈΡ‚Π°Ρ…ΠΌΠ΅ сС Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ΅ΠΌ, Π½ΠΎ TCP Π½Π΅ бСшС Π½Π°Π»ΠΈΡ‡Π΅Π½ ΠΈΠ»ΠΈ ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π°Ρ‚ някъдС ΠΏΠΎ срСдата Π½Π° ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°. Π–Π°Π»ΠΊΠΎ Π΅ Π΄Π° Ρ…Π°Ρ€Ρ‡ΠΈΠΌ Π²Π»ΠΎΠΆΠ΅Π½Π°Ρ‚Π° Снтропия ΠΈ рСсурси Π½Π° процСсора Π·Π° Π½ΠΎΠ²Π° Π΄Π²ΠΎΠΉΠΊΠ°. Π—Π°Ρ‚ΠΎΠ²Π° въвСТдамС Ρ‚.Π½Π°Ρ€. cookie β€” псСвдослучайна стойност, която Ρ‰Π΅ Π·Π°Ρ‰ΠΈΡ‚ΠΈ ΠΎΡ‚ възмоТни случайни replay Π°Ρ‚Π°ΠΊΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Π΅Ρ„Π΅Ρ€Π½ΠΈΡ‚Π΅ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅. ΠŸΠΎΡ€Π°Π΄ΠΈ ΡΠ²ΡŠΡ€Π·Π°Π½ΠΎΡΡ‚Ρ‚Π° ΠΌΠ΅ΠΆΠ΄Ρƒ cookie ΠΈ СфСрния ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ ΠΊΠ»ΡŽΡ‡, публичният ΠΊΠ»ΡŽΡ‡ Π½Π° ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΠΏΠΎΠ»ΠΎΠΆΠ½Π°Ρ‚Π° страна ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΏΡ€Π΅ΠΌΠ°Ρ…Π½Π°Ρ‚ ΠΎΡ‚ подписа Π±Π΅Π· нСобходимост.

β”Œβ”€β”€β”€β”€β”€β”                                                                 β”Œβ”€β”€β”€β”€β”€β”
β”‚PeerAβ”‚                                                                 β”‚PeerBβ”‚
β””β”€β”€β”¬β”€β”€β”˜                                                                 β””β”€β”€β”¬β”€β”€β”˜
   β”‚                          IdA, PubA, CookieA                           β”‚ ╔═══════════════════════════╗
   │──────────────────────────────────────────────────────────────────────>β”‚ β•‘SignPrvA, SignPubA = load()β•‘
   β”‚                                                                       β”‚ β•‘PrvA, PubA = DHgen()       β•‘
   β”‚                                                                       β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚IdB, PubB, CookieB, sign(SignPrvB, (CookieA, CookieB, PubB)), MAC(IdB) β”‚ ╔═══════════════════════════╗
   β”‚β”‚ β•‘verify(Key, IdB)     β•‘
   β”‚                                                                       β”‚ β•‘verify(SignPubB, ...)β•‘
   β”‚                                                                       β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
   β”‚                                                                       β”‚

Накрая, искамС Π΄Π° Π·Π°Ρ‰ΠΈΡ‚ΠΈΠΌ Π»ΠΈΡ‡Π½ΠΈΡ‚Π΅ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ Π½Π° Π½Π°ΡˆΠΈΡ‚Π΅ ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈ ΠΎΡ‚ пасивни Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚Π΅Π»ΠΈ. Π—Π°Ρ‚ΠΎΠ²Π° SIGMA ΠΏΡ€Π΅Π΄Π»Π°Π³Π° ΠΏΡŠΡ€Π²ΠΎ Π΄Π° ΠΎΠ±ΠΌΠ΅Π½ΠΈΠΌ Π΅Ρ„Π΅ΠΌΠ΅Ρ€Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ ΠΈ Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ ΠΎΠ±Ρ‰ ΠΊΠ»ΡŽΡ‡, с ΠΊΠΎΠΉΡ‚ΠΎ Π΄Π° ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°ΠΌΠ΅ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΎΠ½Π½ΠΈΡ‚Π΅ ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Ρ‰ΠΈΡ‚Π΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ. SIGMA описва Π΄Π²Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°:

  • SIGMA-I β€” Π·Π°Ρ‰ΠΈΡ‚Π°Π²Π° ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π° ΠΎΡ‚ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈ Π°Ρ‚Π°ΠΊΠΈ, Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€Π° ΠΎΡ‚ пасивни: ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€Π° ΠΈ, Π°ΠΊΠΎ Π½Π΅Ρ‰ΠΎ Π½Π΅ сС съвпада, Π½Π΅ Ρ€Π°Π·ΠΊΡ€ΠΈΠ²Π° своята идСнтификация. ΠžΡ‚Π³ΠΎΠ²ΠΎΡ€Π° ΠΎΠ±Π°Ρ‡Π΅ Ρ€Π°Π·ΠΊΡ€ΠΈΠ²Π° своята идСнтификация, Π°ΠΊΠΎ бъдС стартиран Π°ΠΊΡ‚ΠΈΠ²Π΅Π½ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ». ПассивСн Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚Π΅Π» Π½Π΅ Π½Π°ΡƒΡ‡Π°Π²Π° Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Π½ΠΈΡ‰ΠΎ;
    SIGMA-R β€” Π·Π°Ρ‰ΠΈΡ‚Π°Π²Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€Π° ΠΎΡ‚ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈ Π°Ρ‚Π°ΠΊΠΈ, Π° ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π° ΠΎΡ‚ пасивни. Всичко Π΅ Π² точност ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ, Π½ΠΎ Π² Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π²Π΅Ρ‡Π΅ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ Π½Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅.

    Π˜Π·Π±ΠΈΡ€Π°ΠΌΠ΅ SIGMA-I, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‚ΠΎΠΉ Π΅ ΠΏΠΎ-близък Π΄ΠΎ ΠΎΠ½ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΎΡ‡Π°ΠΊΠ²Π°ΠΌΠ΅ ΠΎΡ‚ Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΈΡ‚Π΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚-сСрвСрни Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ: ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΡŠΡ‚ ΠΏΠΎΠ·Π½Π°Π²Π° само удостовСрСния ΡΡŠΡ€Π²ΡŠΡ€Π°, Π° ΡΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Π·Π½Π°Π΅ всичко. ОсвСн Ρ‚ΠΎΠ²Π° Π΅ ΠΏΠΎ-лСсСн Π·Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ ΠΏΠΎΡ€Π°Π΄ΠΈ ΠΏΠΎ-малкия Π±Ρ€ΠΎΠΉ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅. Всичко, ΠΊΠΎΠ΅Ρ‚ΠΎ добавямС Π² ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°, Π΅ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π΅ Π½Π° част ΠΎΡ‚ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈ ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° A Π² ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π°Ρ‚Π° част Π½Π° послСдното ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅:

    β”Œβ”€β”€β”€β”€β”€β”                                                                        β”Œβ”€β”€β”€β”€β”€β”
    β”‚PeerAβ”‚                                                                        β”‚PeerBβ”‚
    β””β”€β”€β”¬β”€β”€β”˜                                                                        β””β”€β”€β”¬β”€β”€β”˜
       β”‚                                PubA, CookieA                                 β”‚ ╔═══════════════════════════╗
       │─────────────────────────────────────────────────────────────────────────────>β”‚ β•‘SignPrvA, SignPubA = load()β•‘
       β”‚                                                                              β”‚ β•‘PrvA, PubA = DHgen()       β•‘
       β”‚                                                                              β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
       β”‚PubB, CookieB, Enc((IdB, sign(SignPrvB, (CookieA, CookieB, PubB)), MAC(IdB))) β”‚ ╔═══════════════════════════╗
       β”‚<─────────────────────────────────────────────────────────────────────────────│ β•‘SignPrvB, SignPubB = load()β•‘
       β”‚                                                                              β”‚ β•‘PrvB, PubB = DHgen()       β•‘
       β”‚                                                                              β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
       β”‚                                                                              β”‚ ╔═════════════════════╗
       β”‚       Enc((IdA, sign(SignPrvA, (CookieB, CookieA, PubA)), MAC(IdA)))         β”‚ β•‘Key = DH(PrvA, PubB) β•‘
       │─────────────────────────────────────────────────────────────────────────────>β”‚ β•‘verify(Key, IdB)     β•‘
       β”‚                                                                              β”‚ β•‘verify(SignPubB, ...)β•‘
       β”‚                                                                              β”‚ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
       β”‚                                                                              β”‚
    
    • Π—Π° подписванС сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π“ΠžΠ‘Π’ Π  34.10-2012 Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ с 256-Π±ΠΈΡ‚ΠΎΠ²ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅.
    • Π—Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° общия ΠΊΠ»ΡŽΡ‡ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° 34.10-2012 VKO.
    • ΠšΠ°Ρ‚ΠΎ MAC сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° CMAC. ВСхничСски Ρ‚ΠΎΠ²Π° Π΅ спСцифичСн Ρ€Π΅ΠΆΠΈΠΌ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° Π½Π° Π±Π»ΠΎΡ‡Π΅Π½ ΡˆΠΈΡ„ΡŠΡ€, описан Π² Π“ΠžΠ‘Π’ Π  34.13-2015. ΠšΠ°Ρ‚ΠΎ функция Π·Π° ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π΅ Π·Π° Ρ‚ΠΎΠ·ΠΈ Ρ€Π΅ΠΆΠΈΠΌ β€” ΠšΡƒΠ·Π½Π΅Ρ‡ΠΈΠΊ (34.12-2015).
    • ΠšΠ°Ρ‚ΠΎ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π½Π° събСсСдника сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ…Π΅Ρˆ ΠΎΡ‚ нСговия ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ ΠΊΠ»ΡŽΡ‡. Π—Π° Ρ…Π΅Ρˆ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π‘Ρ‚Ρ€ΠΈΠ±ΠΎΠ³-256 (34.11-2012 256 Π±ΠΈΡ‚Π°).

    Π‘Π»Π΅Π΄ Ρ€ΡŠΠΊΡƒΠ²Π°Π½Π΅ Ρ‰Π΅ ΠΈΠΌΠ°ΠΌΠ΅ ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½ ΠΎΠ±Ρ‰ ΠΊΠ»ΡŽΡ‡. МоТСм Π΄Π° Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π·Π° удостовСрСно ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°Π½Π΅ Π½Π° транспортни ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ. Π’Π°Π·ΠΈ част Π΅ напълно проста ΠΈ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΡΠ±ΡŠΡ€ΠΊΠ°: ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ€Π°ΠΌΠ΅ брояча Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡΡ‚Π°, ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ, удостовСрявамС (MAC) брояча ΠΈ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ тСкст, ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°ΠΌΠ΅. ΠŸΡ€ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ°Π½Π΅ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ провСрявамС, Ρ‡Π΅ Π±Ρ€ΠΎΡΡ‡ΡŠΡ‚ ΠΈΠΌΠ° ΠΎΡ‡Π°ΠΊΠ²Π°Π½Π°Ρ‚Π° стойност, удостовСрявамС ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ тСкст с брояча, Π΄Π΅ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°ΠΌΠ΅. Π‘ ΠΊΠΎΠΉ ΠΊΠ»ΡŽΡ‡ Π΄Π° ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡΡ‚Π° Π·Π° Ρ€ΡŠΠΊΡƒΠ²Π°Π½Π΅, транспортнитС, с ΠΊΠΎΠΉ Π΄Π° удостовСрим? Π˜Π·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΅Π΄ΠΈΠ½ ΠΊΠ»ΡŽΡ‡ Π·Π° всички Ρ‚Π΅Π·ΠΈ Π·Π°Π΄Π°Ρ‡ΠΈ Π΅ опасно ΠΈ Π½Π΅Ρ€Π°Π·ΡƒΠΌΠ½ΠΎ. НСобходимо Π΅ Π΄Π° сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ‚ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° спСциализирани Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ KDF (функция Π·Π° ΠΈΠ·Π²Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΊΠ»ΡŽΡ‡). ΠžΡ‚Π½ΠΎΠ²ΠΎ, няма Π΄Π° измислямС Π½ΠΈΡ‰ΠΎ Π½ΠΎΠ²ΠΎ: HKDF ΠΎΡ‚Π΄Π°Π²Π½Π° Π΅ извСстна, Π΄ΠΎΠ±Ρ€Π΅ ΠΏΡ€ΠΎΡƒΡ‡Π΅Π½Π° ΠΈ няма извСстни ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ. Π—Π° съТалСниС, Π² Ρ€ΠΎΠ΄Π½Π°Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π½Π° Python няма Ρ‚Π°Π·ΠΈ функция, Π·Π°Ρ‚ΠΎΠ²Π° Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ hkdf ΠΏΠ°ΠΊΠ΅Ρ‚Π°. HKDF влагашС HMAC, ΠΊΠΎΠΉΡ‚ΠΎ ΠΎΡ‚ своя страна ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ…Π΅Ρˆ функция. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° рСализация Π½Π° Python Π½Π° страницата Wikipedia Π·Π°Π΅ΠΌΠ° съвсСм ΠΌΠ°Π»ΠΊΠΎ Ρ€Π΅Π΄ΠΎΠ²Π΅ ΠΊΠΎΠ΄. ΠšΠ°ΠΊΡ‚ΠΎ ΠΈ Π² случая с 34.10-2012, ΠΊΠ°Ρ‚ΠΎ Ρ…Π΅Ρˆ функция Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π‘Ρ‚Ρ€ΠΈΠ±ΠΎΠ³-256. Π˜Π·Ρ…ΠΎΠ΄ΡŠΡ‚ ΠΎΡ‚ Π½Π°ΡˆΠ°Ρ‚Π° функция Π·Π° ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½Π΅ Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ Ρ‰Π΅ бъдС Π½Π°Ρ€Π΅Ρ‡Π΅Π½ сСсионСн ΠΊΠ»ΡŽΡ‡, ΠΎΡ‚ ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ сС ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ симСтрични:

    kdf = Hkdf(None, key_session, hash=GOST34112012256)
    kdf.expand(b"handshake1-mac-identity")
    kdf.expand(b"handshake1-enc")
    kdf.expand(b"handshake1-mac")
    kdf.expand(b"handshake2-mac-identity")
    kdf.expand(b"handshake2-enc")
    kdf.expand(b"handshake2-mac")
    kdf.expand(b"transport-initiator-enc")
    kdf.expand(b"transport-initiator-mac")
    kdf.expand(b"transport-responder-enc")
    kdf.expand(b"transport-responder-mac")
    

    Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€ΠΈ/схСми

    НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊΠ²ΠΈ ASN.1 структури ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ Π·Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° всички Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ:

    class Msg(Choice):
        schema = ((
            ("text", MsgText()),
            ("handshake0", MsgHandshake0(expl=tag_ctxc(0))),
            ("handshake1", MsgHandshake1(expl=tag_ctxc(1))),
            ("handshake2", MsgHandshake2(expl=tag_ctxc(2))),
        ))
    
    class MsgText(Sequence):
        schema = ((
            ("payload", MsgTextPayload()),
            ("payloadMac", MAC()),
        ))
    
    class MsgTextPayload(Sequence):
        schema = ((
            ("nonce", Integer(bounds=(0, float("+inf")))),
            ("ciphertext", OctetString(bounds=(1, MaxTextLen))),
        ))
    
    class MsgHandshake0(Sequence):
        schema = ((
            ("cookieInitiator", Cookie()),
            ("pubKeyInitiator", PubKey()),
        ))
    
    class MsgHandshake1(Sequence):
        schema = ((
            ("cookieResponder", Cookie()),
            ("pubKeyResponder", PubKey()),
            ("ukm", OctetString(bounds=(8, 8))),
            ("ciphertext", OctetString()),
            ("ciphertextMac", MAC()),
        ))
    
    class MsgHandshake2(Sequence):
        schema = ((
            ("ciphertext", OctetString()),
            ("ciphertextMac", MAC()),
        ))
    
    class HandshakeTBE(Sequence):
        schema = ((
            ("identity", OctetString(bounds=(32, 32))),
            ("signature", OctetString(bounds=(64, 64))),
            ("identityMac", MAC()),
        ))
    
    class HandshakeTBS(Sequence):
        schema = ((
            ("cookieTheir", Cookie()),
            ("cookieOur", Cookie()),
            ("pubKeyOur", PubKey()),
        ))
    
    class Cookie(OctetString): bounds = (16, 16)
    class PubKey(OctetString): bounds = (64, 64)
    class MAC(OctetString): bounds = (16, 16)
    

    HandshakeTBS β€” Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ бъдС подписано (to be signed). HandshakeTBE β€” Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ бъдС ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°Π½ΠΎ (to be encrypted). ΠžΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΏΠΎΠ»Π΅Ρ‚ΠΎ ukm Π² MsgHandshake1. 34.10 VKO, Π·Π° Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½Π° рандомизация Π² Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅, Π²ΠΊΠ»ΡŽΡ‡Π²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€ UKM (user keying material) β€” просто Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½Π° Снтропия.

    ДобавянС Π½Π° криптография Π² ΠΊΠΎΠ΄Π°

    НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ само ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΡ‚Π΅ Π² оригиналния ΠΊΠΎΠ΄, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ структурата остава ΡΡŠΡ‰Π°Ρ‚Π° (Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚, ΠΏΡŠΡ€Π²ΠΎ бСшС написана ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»Π½Π°Ρ‚Π° вСрсия, Π° слСд Ρ‚ΠΎΠ²Π° ΠΎΡ‚ нСя сС ΠΈΠ·Ρ€ΡΠ·Π²Π°ΡˆΠ΅ цялата криптография).

    Въй ΠΊΠ°Ρ‚ΠΎ автСнтикацията ΠΈ идСнтификацията Π½Π° ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈΡ‚Π΅ Ρ‰Π΅ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Ρ‡Ρ€Π΅Π· ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅, Ρ‚Π΅ сСга трябва Π΄Π° сС ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚ някъдС Π΄ΡŠΠ»Π³ΠΎΡΡ€ΠΎΡ‡Π½ΠΎ. Π—Π° простота ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ JSON ΠΎΡ‚ Ρ‚Π°ΠΊΡŠΠ² Π²ΠΈΠ΄:

    {
        "our": {
            "prv": "21254cf66c15e0226ef2669ceee46c87b575f37f9000272f408d0c9283355f98",
            "pub": "938c87da5c55b27b7f332d91b202dbef2540979d6ceaa4c35f1b5bfca6df47df0bdae0d3d82beac83cec3e353939489d9981b7eb7a3c58b71df2212d556312a1"
        },
        "their": {
            "alice": "d361a59c25d2ca5a05d21f31168609deeec100570ac98f540416778c93b2c7402fd92640731a707ec67b5410a0feae5b78aeec93c4a455a17570a84f2bc21fce",
            "bob": "aade1207dd85ecd283272e7b69c078d5fae75b6e141f7649ad21962042d643512c28a2dbdc12c7ba40eb704af920919511180c18f4d17e07d7f5acd49787224a"
        }
    }
    

    our β€” Π½Π°ΡˆΠΈΡΡ‚ ΠΊΠ»ΡŽΡ‡ΠΎΠ²ΠΈ Π΄Π²ΠΎΠΉΠΊΠ°, ΡˆΠ΅ΡΡ‚Π½Π°Π΄Π΅ΡΠ΅Ρ‚ΠΈΡ‡Π½ΠΈ частСн ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π΅Π½ ΠΊΠ»ΡŽΡ‡. their β€” ΠΈΠΌΠ΅Π½Π° Π½Π° ΡΡŠΠ±Π΅ΡΠ΅Π΄Π½ΠΈΡ†ΠΈΡ‚Π΅ ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅. НСка ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π½Π° командния Ρ€Π΅Π΄ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ постобработка Π½Π° JSON Π΄Π°Π½Π½ΠΈΡ‚Π΅:

    ΠΎΡ‚ pygost import gost3410
    ΠΎΡ‚ pygost.gost34112012256 import GOST34112012256
    
    CURVE = gost3410.GOST3410Curve(
        *gost3410.CURVE_PARAMS["GostR3410_2001_CryptoPro_A_ParamSet"]
    )
    
    parser = argparse.ArgumentParser(description="GOSTIM")
    parser.add_argument(
        "--keys-gen",
        action="store_true",
        help="Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° JSON с Π½ΠΎΠ²Π° Π΄Π²ΠΎΠΉΠΊΠ° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅",
    )
    parser.add_argument(
        "--keys",
        default="keys.json",
        required=False,
        help="JSON с Π½Π°ΡˆΠΈΡ‚Π΅ ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅",
    )
    parser.add_argument(
        "--bind",
        default="::1",
        help="АдрСс Π·Π° ΡΠ»ΡƒΡˆΠ°Π½Π΅",
    )
    parser.add_argument(
        "--port",
        type=int,
        default=6666,
        help="ΠŸΠΎΡ€Ρ‚ Π·Π° ΡΠ»ΡƒΡˆΠ°Π½Π΅",
    )
    args = parser.parse_args()
    
    if args.keys_gen:
        prv_raw = urandom(32)
        pub = gost3410.public_key(CURVE, gost3410.prv_unmarshal(prv_raw))
        pub_raw = gost3410.pub_marshal(pub)
        print(json.dumps({
            "our": {"prv": hexenc(prv_raw), "pub": hexenc(pub_raw)},
            "their": {},
        }))
        exit(0)
    
    # ΠŸΠ°Ρ€ΡΠ²Π°Π½Π΅ ΠΈ Ρ€Π°Π·ΡƒΠΏΠ»ΡŠΡ‚Π½ΡΠ²Π°Π½Π΅ Π½Π° Π½Π°ΡˆΠΈΡ‚Π΅ ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ {{{
    with open(args.keys, "rb") as fd:
        _keys = json.loads(fd.read().decode("utf-8"))
    KEY_OUR_SIGN_PRV = gost3410.prv_unmarshal(hexdec(_keys["our"]["prv"]))
    _pub = hexdec(_keys["our"]["pub"])
    KEY_OUR_SIGN_PUB = gost3410.pub_unmarshal(_pub)
    KEY_OUR_SIGN_PUB_HASH = OctetString(GOST34112012256(_pub).digest())
    for peer_name, pub_raw in _keys["their"].items():
        _pub = hexdec(pub_raw)
        KEYS[GOST34112012256(_pub).digest()] = {
            "name": peer_name,
            "pub": gost3410.pub_unmarshal(_pub),
        }
    # }}}
    

    ΠŸΡ€ΠΈΠ²Π°Ρ‚Π½ΠΈΡΡ‚ ΠΊΠ»ΡŽΡ‡ Π½Π° Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΡ€Π° 34.10 Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΎ число. Π‘ Ρ€Π°Π·ΠΌΠ΅Ρ€ 256 Π±ΠΈΡ‚Π° Π·Π° 256-Π±ΠΈΡ‚ΠΎΠ²ΠΈ Π΅Π»ΠΈΠΏΡ‚ΠΈΡ‡Π½ΠΈ ΠΊΡ€ΠΈΠ²ΠΈ. PyGOST Ρ€Π°Π±ΠΎΡ‚ΠΈ Π½Π΅ с Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ Π±Π°ΠΉΡ‚ΠΎΠ²Π΅, Π° с Π³ΠΎΠ»Π΅ΠΌΠΈ числа, Π·Π°Ρ‚ΠΎΠ²Π° Π½Π°ΡˆΠΈΡΡ‚ ΠΏΡ€ΠΈΠ²Π°Ρ‚Π΅Π½ ΠΊΠ»ΡŽΡ‡ (urandom(32)) трябва Π΄Π° бъдС трансформиран Π² число, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ gost3410.prv_unmarshal(). ΠŸΡƒΠ±Π»ΠΈΡ‡Π½ΠΈΡΡ‚ ΠΊΠ»ΡŽΡ‡ сС изчислява Π΄Π΅Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΈΡ€Π°Π½ΠΎ ΠΎΡ‚ приватния, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ gost3410.public_key(). ΠŸΡƒΠ±Π»ΠΈΡ‡Π½ΠΈΡΡ‚ ΠΊΠ»ΡŽΡ‡ 34.10 сС ΡΡŠΡΡ‚ΠΎΠΈ ΠΎΡ‚ Π΄Π²Π΅ Π³ΠΎΠ»Π΅ΠΌΠΈ числа, ΠΊΠΎΠΈΡ‚ΠΎ ΡΡŠΡ‰ΠΎ трябва Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Π½ΠΈ Π² Π±Π°ΠΉΡ‚ΠΎΠ²Π° послСдоватСлност Π·Π° удобство ΠΏΡ€ΠΈ ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ gost3410.pub_marshal().

    Π‘Π»Π΅Π΄ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π½Π΅ Π½Π° JSON Ρ„Π°ΠΉΠ»Π°, ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ трябва Π΄Π° сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Ρ‚ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ gost3410.pub_unmarshal(). Въй ΠΊΠ°Ρ‚ΠΎ Ρ‰Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ Π½Π° събСсСдника ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° Ρ…Π΅Ρˆ ΠΎΡ‚ публичния ΠΊΠ»ΡŽΡ‡, Ρ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Π΄Π° сС изчислят ΠΈ поставят Π² Ρ€Π΅Ρ‡Π½ΠΈΠΊ Π·Π° Π±ΡŠΡ€Π·ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅. Π‘Ρ‚Ρ€ΠΈΠ±ΠΎΠ³-256 Ρ…Π΅ΡˆΡŠΡ‚ Π΅ gost34112012256.GOST34112012256(), изцяло удовлСтворяващ интСрфСйса Π½Π° hashlib Π·Π° Ρ…Π΅Ρˆ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.

    Как сС ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°Ρ‚Π° Π½Π° ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π°? Всичко Π΅ ΠΏΠΎ схСмата Π½Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅Ρ‚ΠΎ: Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ бисквитка (128 Π±ΠΈΡ‚Π° са напълно Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΈ), Π΅Ρ„ΠΈΠΌΠ΅Ρ€Π΅Π½ ΠΊΠ»ΡŽΡ‡ΠΎΠ² Π½Π°Π±ΠΎΡ€ 34.10, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° VKO функцията Π·Π° ΡΡŠΠ³Π»Π°ΡΡƒΠ²Π°Π½Π΅ Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅.

     395 async def initiator(host, port):
     396     _id = repr((host, port))
     397     logging.info("%s: dialing", _id)
     398     reader, writer = await asyncio.open_connection(host, port)
     399     # Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ Π½Π°ΡˆΠ΅Ρ‚ΠΎ Π΅ΠΏhemeral ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎ ΠΊΠ»ΡŽΡ‡ ΠΈ бисквитка, ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Handshake 0 {{{
     400     cookie_our = Cookie(urandom(16))
     401     prv = gost3410.prv_unmarshal(urandom(32))
     402     pub_our = gost3410.public_key(CURVE, prv)
     403     pub_our_raw = PubKey(gost3410.pub_marshal(pub_our))
     404     writer.write(Msg(("handshake0", MsgHandshake0((
     405         ("cookieInitiator", cookie_our),
     406         ("pubKeyInitiator", pub_our_raw),
     407     )))).encode())
     408     # }}}
     409     await writer.drain()
    

    • ΠΎΡ‡Π°ΠΊΠ²Π°ΠΌΠ΅ ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ ΠΈ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΡ‚ΠΎ Msg ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅;
    • ΡƒΠ±Π΅ΠΆΠ΄Π°Π²Π°ΠΌΠ΅ сС, Ρ‡Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ handshake1;
    • Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ Π΅ΠΏhemeral публичния ΠΊΠ»ΡŽΡ‡ Π½Π° ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΠΏΠΎΠ»ΠΎΠΆΠ½Π°Ρ‚Π° страна ΠΈ изчислявамС сСсионния ΠΊΠ»ΡŽΡ‡;
    • създавамС симСтрични ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π° TBE частта ΠΎΡ‚ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ.

     423     logging.info("%s: got %s message", _id, msg.choice)
     424     if msg.choice != "handshake1":
     425         logging.warning("%s: unexpected message, disconnecting", _id)
     426         writer.close()
     427         return
     428     # }}}
     429     msg_handshake1 = msg.value
     430     # Π’Π°Π»ΠΈΠ΄ΠΈΡ€Π°ΠΌΠ΅ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π·Π° Handshake {{{
     431     cookie_their = msg_handshake1["cookieResponder"]
     432     pub_their_raw = msg_handshake1["pubKeyResponder"]
     433     pub_their = gost3410.pub_unmarshal(bytes(pub_their_raw))
     434     ukm_raw = bytes(msg_handshake1["ukm"])
     435     ukm = ukm_unmarshal(ukm_raw)
     436     key_session = kek_34102012256(CURVE, prv, pub_their, ukm, mode=2001)
     437     kdf = Hkdf(None, key_session, hash=GOST34112012256)
     438     key_handshake1_mac_identity = kdf.expand(b"handshake1-mac-identity")
     439     key_handshake1_enc = kdf.expand(b"handshake1-enc")
     440     key_handshake1_mac = kdf.expand(b"handshake1-mac")
    

    UKM Π΅ 64-Π±ΠΈΡ‚ΠΎΠ² Π½ΠΎΠΌΠ΅Ρ€ (urandom(8)), ΠΊΠΎΠΉΡ‚ΠΎ ΡΡŠΡ‰ΠΎ изисква дСсСриализация ΠΎΡ‚ Π±Π°ΠΉΡ‚ΠΎΠ²ΠΎΡ‚ΠΎ прСдставянС, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ gost3410_vko.ukm_unmarshal(). VKO функцията Π·Π° 34.10-2012 256-Π±ΠΈΡ‚ΠΎΠ²Π° Π΅ gost3410_vko.kek_34102012256() (KEK β€” ΠΊΠ»ΡŽΡ‡ Π·Π° ΠΊΡ€ΠΈΠΏΡ‚ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΊΠ»ΡŽΡ‡).

    ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΡΡ‚ сСсионСн ΠΊΠ»ΡŽΡ‡ Π²Π΅Ρ‡Π΅ Π΅ 256-Π±ΠΈΡ‚ΠΎΠ²Π° Π±Π°ΠΉΡ‚ΠΎΠ²Π° псСвдослучайна послСдоватСлност. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, Ρ‚ΠΎΠΉ Π²Π΅Π΄Π½Π°Π³Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π² HKDF функцията. Въй ΠΊΠ°Ρ‚ΠΎ GOST34112012256 отговаря Π½Π° интСрфСйса Π½Π° hashlib, Ρ‚ΠΎΠΉ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π² класа Hkdf. Π‘ΠΎΠ»Ρ‚Π° (ΠΏΡŠΡ€Π²ΠΈΡΡ‚ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π½Π° Hkdf) Π½Π΅ я ΡƒΠΊΠ°Π·Π²Π°ΠΌΠ΅, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ ΠΏΠΎΡ€Π°Π΄ΠΈ Π΅ΠΏhemeralността Π½Π° участиС Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²ΠΈΡ‚Π΅ Π΄Π²ΠΎΠΉΠΊΠΈ Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π·Π° всяка сСсия ΠΈ Π² Π½Π΅Π³ΠΎ Π²Π΅Ρ‡Π΅ ΠΈΠΌΠ° Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Снтропия. kdf.expand() ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ Π²Π΅Ρ‡Π΅ Π²Ρ€ΡŠΡ‰Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ с дълТина 256 Π±ΠΈΡ‚Π°, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ Π·Π° ΠšΡƒΠ·Π½Π΅Ρ‡ΠΈΠΊΠ° Π² ΠΏΠΎ-късСн Π΅Ρ‚Π°ΠΏ.

    Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС провСряват TBE ΠΈ TBS частитС Π½Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΡ‚ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅:

    • изчислява сС ΠΈ провСрява MAC Π½Π°Π΄ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΡ‚ΠΎ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ тСкст;
    • Π΄Π΅ΡˆΠΈΡ„Ρ€ΠΈΡ€Π° сС ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ тСкст;
    • Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π° сС TBE структура;
    • ΠΎΡ‚ нСя сС Π²Π·ΠΈΠΌΠ° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ Π½Π° ΠΎΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ сС провСрява Π΄Π°Π»ΠΈ Π½ΠΈ Π΅ извСстСн;
    • изчислява сС ΠΈ сС провСрява MAC Π½Π°Π΄ Ρ‚ΠΎΠ·ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€;
    • провСрява сС ΠΏΠΎΠ΄ΠΏΠΈΡΡŠΡ‚ Π½Π°Π΄ TBS структурата, Π² която Π²Π»ΠΈΠ·Π°Ρ‚ бисквиткитС Π½Π° Π΄Π²Π΅Ρ‚Π΅ страни ΠΈ публичният Π΅Ρ„ΠΈΠΌΠ΅Ρ€Π΅Π½ ΠΊΠ»ΡŽΡ‡ Π½Π° ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΠΏΠΎΠ»ΠΎΠΆΠ½Π°Ρ‚Π° страна. ΠŸΠΎΠ΄ΠΏΠΈΡΡŠΡ‚ сС провСрява с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Π΄ΡŠΠ»Π³ΠΎΡΡ€ΠΎΡ‡Π½ΠΈΡ ΠΊΠ»ΡŽΡ‡ Π·Π° подпис Π½Π° събСсСдника.

     441     ΠΎΠΏΠΈΡ‚:
     442         peer_name = validate_tbe(
     443             msg_handshake1,
     444             key_handshake1_mac_identity,
     445             key_handshake1_enc,
     446             key_handshake1_mac,
     447             cookie_our,
     448             cookie_their,
     449             pub_their_raw,
     450         )
     451     освСн Π°ΠΊΠΎ ValueError ΠΊΠ°Ρ‚ΠΎ Π³Ρ€Π΅ΡˆΠΊΠ°:
     452         logging.warning("%s: %s, ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π°Π½Π΅ Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°", _id, err)
     453         writer.close()
     454         return
     455     # }}}
    
     128 def validate_tbe(
     129         msg_handshake: Union[MsgHandshake1, MsgHandshake2],
     130         key_mac_identity: bytes,
     131         key_enc: bytes,
     132         key_mac: bytes,
     133         cookie_their: Cookie,
     134         cookie_our: Cookie,
     135         pub_key_our: PubKey,
     136 ) -> str:
     137     ciphertext = bytes(msg_handshake["ciphertext"])
     138     mac_tag = mac(GOST3412Kuznechik(key_mac).encrypt, KUZNECHIK_BLOCKSIZE, ciphertext)
     139     if not compare_digest(mac_tag, bytes(msg_handshake["ciphertextMac"])):
     140         raise ValueError("Π½Π΅Π²Π°Π»ΠΈΠ΄Π΅Π½ MAC")
     141     plaintext = ctr(
     142         GOST3412Kuznechik(key_enc).encrypt,
     143         KUZNECHIK_BLOCKSIZE,
     144         ciphertext,
     145         8 * b"x00",
     146     )
     147     try:
     148         tbe, _ = HandshakeTBE().decode(plaintext)
     149     освСн ако ASN1Error:
     150         raise ValueError("Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π° TBE")
     151     key_sign_pub_hash = bytes(tbe["identity"])
     152     peer = KEYS.get(key_sign_pub_hash)
     153     if peer is None:
     154         raise ValueError("нСизвСстна идСнтичност")
     155     mac_tag = mac(
     156         GOST3412Kuznechik(key_mac_identity).encrypt,
     157         KUZNECHIK_BLOCKSIZE,
     158         key_sign_pub_hash,
     159     )
     160     if not compare_digest(mac_tag, bytes(tbe["identityMac"])):
     161         raise ValueError("Π½Π΅Π²Π°Π»ΠΈΠ΄Π΅Π½ идСнтичност MAC")
     162     tbs = HandshakeTBS((
     163         ("cookieTheir", cookie_their),
     164         ("cookieOur", cookie_our),
     165         ("pubKeyOur", pub_key_our),
     166     ))
     167     if not gost3410.verify(
     168         CURVE,
     169         peer["pub"],
     170         GOST34112012256(tbs.encode()).digest(),
     171         bytes(tbe["signature"]),
     172     ):
     173         raise ValueError("нСвалидСн подпис")
     174     return peer["name"]
    

    ΠšΠ°ΠΊΡ‚ΠΎ Π²Π΅Ρ‡Π΅ спомСнах, 34.13-2015 описва Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠΈ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° Π½Π° Π±Π»ΠΎΡ‡Π½ΠΈΡ‚Π΅ ΡˆΠΈΡ„Ρ€ΠΈ ΠΎΡ‚ 34.12-2015. Π‘Ρ€Π΅Π΄ тях ΠΈΠΌΠ° Ρ€Π΅ΠΆΠΈΠΌ Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° имитовставки, изчисляванС Π½Π° MAC. Π’ PyGOST Ρ‚ΠΎΠ²Π° Π΅ gost3413.mac(). Π’ΠΎΠ·ΠΈ Ρ€Π΅ΠΆΠΈΠΌ изисква ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° функция Π·Π° ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Π½Π΅ (ΠΏΡ€ΠΈΠ΅ΠΌΠ°Ρ‰Π° ΠΈ Π²Ρ€ΡŠΡ‰Π°Ρ‰Π° Π΅Π΄ΠΈΠ½ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½ΠΈ), Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π½Π° ΡˆΠΈΡ„Ρ€ΠΎΠ±Π»ΠΎΠΊΠ° ΠΈ самитС Π΄Π°Π½Π½ΠΈ. Π—Π°Ρ‰ΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π·Π°Π΄Π°Π΄Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€ΡŠΡ‚ Π½Π° ΡˆΠΈΡ„Ρ€ΠΎΠ±Π»ΠΎΠΊΠ° Π½Π° Ρ‚Π²ΡŠΡ€Π΄ΠΎ? 34.12-2015 описва Π½Π΅ само 128-битовия ΡˆΠΈΡ„ΡŠΡ€ ΠšΡƒΠ·Π½Π΅Ρ‡ΠΈΠΊ, Π½ΠΎ ΠΈ 64-битовия Магма β€” ΠΌΠ°Π»ΠΊΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ Π“ΠžΠ‘Π’ 28147-89, създадСн ΠΎΡ‰Π΅ Π² ΠšΠ“Π‘ ΠΈ всС ΠΎΡ‰Π΅ ΠΏΡ€ΠΈΡ‚Π΅ΠΆΠ°Π²Π°Ρ‰ Π΅Π΄ΠΈΠ½ ΠΎΡ‚ Π½Π°ΠΉ-високитС ΠΏΡ€Π°Π³ΠΎΠ²Π΅ Π½Π° сигурност.

    ΠšΡƒΠ·Π½Π΅Ρ‡ΠΈΠΊ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π° gost.3412.GOST3412Kuznechik(key) ΠΈΠ·Π²ΠΈΠΊΠ²Π° ΠΈ Π²Ρ€ΡŠΡ‰Π° ΠΎΠ±Π΅ΠΊΡ‚ с ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈΡ‚Π΅ .encrypt()/ .decrypt(), подходящи Π·Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π² 34.13 Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. MAC сС изчислява ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½: gost3413.mac(GOST3412Kuznechik(key).encrypt, KUZNECHIK_BLOCKSIZE, ciphertext). Π—Π° сравнСниС Π½Π° изчислСния ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ MAC Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ сравнСниС (==) Π½Π° Π±Π°ΠΉΡ‚ΠΎΠ²ΠΈ Π½ΠΈΠ·ΠΎΠ²Π΅, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‚Π°Π·ΠΈ опСрация Π΄Π°Π²Π° ΠΈΠ·Ρ‚ΠΈΡ‡Π°Π½Π΅ Π½Π° Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π·Π° сравнСниС, ΠΊΠΎΠ΅Ρ‚ΠΎ, Π² общия случай, ΠΌΠΎΠΆΠ΅ Π΄Π° Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ Ρ„Π°Ρ‚Π°Π»Π½ΠΈ уязвимости ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° BEAST Π°Ρ‚Π°ΠΊΠΈΡ‚Π΅ срСщу TLS. Π’ Python ΠΈΠΌΠ° спСциална функция hmac.compare_digest Π·Π° Ρ‚ΠΎΠ²Π°.

    Ѐункцията Π·Π° Π±Π»ΠΎΡ‡Π½ΠΎ ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡˆΠΈΡ„Ρ€ΠΎΠ²Π° само Π΅Π΄ΠΈΠ½ Π±Π»ΠΎΠΊ ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ. Π—Π° ΠΏΠΎ-голямо количСство, ΠΈ особСно с Π½Π΅ ΠΊΡ€Π°Ρ‚Π½Π° дълТина, Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ€Π΅ΠΆΠΈΠΌ Π½Π° ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Π½Π΅. Π’ 34.13-2015 са описани слСднитС: ECB, CTR, OFB, CBC, CFB. ВсСки ΠΈΠΌΠ° свои допустими сфСри Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈ характСристики. Π—Π° голямо съТалСниС, всС ΠΎΡ‰Π΅ нямамС стандартизирани Π°Π²Ρ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½ΠΈ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠΈ (ΠΊΠ°Ρ‚ΠΎ CCM, OCB, GCM ΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ) β€” ΠΏΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»Π½ΠΎ смС ΠΎΠ±Ρ€Π΅ΠΌΠ΅Π½Π΅Π½ΠΈ ΠΏΠΎΠ½Π΅ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ MAC. Π˜Π·Π±Ρ€Π°Ρ… Ρ€Π΅ΠΆΠΈΠΌ Π½Π° брояч (CTR): Ρ‚ΠΎΠΉ Π½Π΅ изисква допълнСния Π΄ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π½Π° Π±Π»ΠΎΠΊΠ°, ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΏΠ°Ρ€Π°Π»Π΅Π»ΠΈΠ·ΠΈΡ€Π°Π½, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° само функция Π·Π° ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Π½Π΅ ΠΈ ΠΌΠΎΠΆΠ΅ бСзопасно Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° голямо количСство ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ (Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ CBC, ΠΏΡ€ΠΈ ΠΊΠΎΠΉΡ‚ΠΎ сравнитСлно Π±ΡŠΡ€Π·ΠΎ Π·Π°ΠΏΠΎΡ‡Π²Π°Ρ‚ ΠΊΠΎΠ»ΠΈΠ·ΠΈΠΈΡ‚Π΅).

    ΠšΠ°ΠΊΡ‚ΠΎ .mac(), .ctr() ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Π΄Π°Π½Π½ΠΈ Π½Π° Π²Ρ…ΠΎΠ΄Π°: ciphertext = gost3413.ctr(GOST3412Kuznechik(key).encrypt, KUZNECHIK_BLOCKSIZE, plaintext, iv). НСобходимо Π΅ Π·Π°Π΄Π°Π²Π°Π½Π΅ Π½Π° Π²Π΅ΠΊΡ‚ΠΎΡ€ Π·Π° инициализация, с дълТина Ρ‚ΠΎΡ‡Π½ΠΎ Π² ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°Ρ‚Π° Π½Π° ΡˆΠΈΡ„Ρ€ΠΎΠ±Π»ΠΎΠΊΠ°. Ако Π½Π°ΡˆΠΈΡΡ‚ ΡˆΠΈΡ„Ρ€ΠΎΠ² ΠΊΠ»ΡŽΡ‡ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° само Π·Π° ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π΅ Π½Π° Π΅Π΄Π½ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ (Π΄ΠΎΡ€ΠΈ ΠΈ ΠΎΡ‚ няколко Π±Π»ΠΎΠΊΠ°), бСзопасно ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π·Π°Π΄Π°Π΄Π΅ Π½ΡƒΠ»Π΅Π² Π²Π΅ΠΊΡ‚ΠΎΡ€ Π·Π° инициализация. Π—Π° ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½Π΅ Π½Π° handshake ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° всСки ΠΏΡŠΡ‚ ΠΎΡ‚Π΄Π΅Π»Π΅Π½ ΠΊΠ»ΡŽΡ‡.

    ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°Ρ‚Π° Π½Π° подписа gost3410.verify() Π΅ Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»Π½Π°: ΠΏΡ€Π΅Π΄Π°Π²Π°ΠΌΠ΅ Π΅Π»ΠΈΠΏΡ‚ΠΈΡ‡Π½Π°Ρ‚Π° ΠΊΡ€ΠΈΠ²Π°, Π² ΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ Π½Π° която Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌ (която просто фиксирамС Π² нашия GOSTIM ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»), публичния ΠΊΠ»ΡŽΡ‡ Π½Π° подписващия (Π½Π΅ забравяйтС, Ρ‡Π΅ Ρ‚ΠΎΠ²Π° трябва Π΄Π° бъдС ΠΊΠΎΡ€Ρ‚Π΅ΠΆ ΠΎΡ‚ Π΄Π²Π΅ Π³ΠΎΠ»Π΅ΠΌΠΈ числа, Π° Π½Π΅ Π±Π°ΠΉΡ‚ΠΎΠ² Π½ΠΈΠ·), 34.11-2012 Ρ…Π΅Ρˆ ΠΈ самия ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ подпис.

    Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π°, Π² ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€Π° подготвямС ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°ΠΌΠ΅ handshake2 ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π·Π° Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅, ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°ΠΉΠΊΠΈ ΡΡŠΡ‰ΠΈΡ‚Π΅ дСйствия, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ…ΠΌΠ΅ ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°Ρ‚Π°, само симСтрично: подпис Π²ΡŠΡ€Ρ…Ρƒ собствСнитС си ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ вмСсто ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΈ Ρ‚.Π½...

     456     # ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΡŒΡ‚Π΅ ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΡŒΡ‚Π΅ сообщСниС Handshake 2 {{{
     457     tbs = HandshakeTBS((
     458         ("cookieTheir", cookie_their),
     459         ("cookieOur", cookie_our),
     460         ("pubKeyOur", pub_our_raw),
     461     ))
     462     signature = gost3410.sign(
     463         CURVE,
     464         KEY_OUR_SIGN_PRV,
     465         GOST34112012256(tbs.encode()).digest(),
     466     )
     467     key_handshake2_mac_identity = kdf.expand(b"handshake2-mac-identity")
     468     mac_tag = mac(
     469         GOST3412Kuznechik(key_handshake2_mac_identity).encrypt,
     470         KUZNECHIK_BLOCKSIZE,
     471         bytes(KEY_OUR_SIGN_PUB_HASH),
     472     )
     473     tbe = HandshakeTBE((
     474         ("identity", KEY_OUR_SIGN_PUB_HASH),
     475         ("signature", OctetString(signature)),
     476         ("identityMac", MAC(mac_tag)),
     477     ))
     478     tbe_raw = tbe.encode()
     479     key_handshake2_enc = kdf.expand(b"handshake2-enc")
     480     key_handshake2_mac = kdf.expand(b"handshake2-mac")
     481     ciphertext = ctr(
     482         GOST3412Kuznechik(key_handshake2_enc).encrypt,
     483         KUZNECHIK_BLOCKSIZE,
     484         tbe_raw,
     485         8 * b"x00",
     486     )
     487     mac_tag = mac(
     488         GOST3412Kuznechik(key_handshake2_mac).encrypt,
     489         KUZNECHIK_BLOCKSIZE,
     490         ciphertext,
     491     )
     492     writer.write(Msg(("handshake2", MsgHandshake2((
     493         ("ciphertext", OctetString(ciphertext)),
     494         ("ciphertextMac", MAC(mac_tag)),
     495     )))).encode())
     496     # }}}
     497     await writer.drain()
     498     logging.info("%s: сСссия установлСна: %s", _id, peer_name)
     

    Когда сСссия установлСна, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ транспортныС ΠΊΠ»ΡŽΡ‡ΠΈ (ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ»ΡŽΡ‡ для ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ, для Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ, для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· сторон), инициализируСтся ΠšΡƒΠ·Π½Π΅Ρ‡ΠΈΠΊ для Π΄Π΅ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ MAC:

     499     # ЗапуститС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ тСкстовых сообщСний, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ€ транспорта {{{
     500     key_initiator_enc = kdf.expand(b"transport-initiator-enc")
     501     key_initiator_mac = kdf.expand(b"transport-initiator-mac")
     502     key_responder_enc = kdf.expand(b"transport-responder-enc")
     503     key_responder_mac = kdf.expand(b"transport-responder-mac")
     ...
     509     asyncio.ensure_future(msg_sender(
     510         peer_name,
     511         key_initiator_enc,
     512         key_initiator_mac,
     513         writer,
     514     ))
     515     encrypter = GOST3412Kuznechik(key_responder_enc).encrypt
     516     macer = GOST3412Kuznechik(key_responder_mac).encrypt
     517     # }}}
     519     nonce_expected = 0
    
     520     # ОТиданиС тСстовых сообщСний {{{
     521     while True:
     522         data = await reader.read(MaxMsgLen)
     ...
     530             msg, tail = Msg().decode(buf)
     ...
     537         try:
     538             await msg_receiver(
     539                 msg.value,
     540                 nonce_expected,
     541                 macer,
     542                 encrypter,
     543                 peer_name,
     544             )
     545         except ValueError as err:
     546             logging.warning("%s: %s", err)
     547             break
     548         nonce_expected += 1
     549     # }}}
    

    msg_sender ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΡˆΠΈΡ„Ρ€ΡƒΠ΅Ρ‚ сообщСния ΠΏΠ΅Ρ€Π΅Π΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ Π² TCP-соСдинСниС. Π£ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сообщСния ΠΌΠΎΠ½ΠΎΡ‚ΠΎΠ½Π½ΠΎ Π²ΠΎΠ·Ρ€Π°ΡΡ‚Π°ΡŽΡ‰ΠΈΠΉ nonce, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ‚Π°ΠΊΠΆΠ΅ являСтся Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠΌ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΈ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΠΈ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ счётчика. Π£ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сообщСния ΠΈ Π±Π»ΠΎΠΊΠ° сообщСния Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‰ΠΈΠ΅ΡΡ значСния счётчика.

    асинхронная функция msg_sender(peer_name: str, key_enc: bytes, key_mac: bytes, writer) -> None:
        nonce = 0
        encrypter = GOST3412Kuznechik(key_enc).encrypt
        macer = GOST3412Kuznechik(key_mac).encrypt
        in_queue = IN_QUEUES[peer_name]
        while True:
            text = await in_queue.get()
            if text is None:
                break
            ciphertext = ctr(
                encrypter,
                KUZNECHIK_BLOCKSIZE,
                text.encode("utf-8"),
                long2bytes(nonce, 8),
            )
            payload = MsgTextPayload((
                ("nonce", Integer(nonce)),
                ("ciphertext", OctetString(ciphertext)),
            ))
            mac_tag = mac(macer, KUZNECHIK_BLOCKSIZE, payload.encode())
            writer.write(Msg(("text", MsgText((
                ("payload", payload),
                ("payloadMac", MAC(mac_tag)),
            )))).encode())
            nonce += 1
    

    ВходящиС сообщСния ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½ΠΎΠΉ msg_receiver, Π·Π°Π½ΠΈΠΌΠ°ΡŽΡ‰Π΅ΠΉΡΡ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ ΠΈ Π΄Π΅ΡˆΠΈΡ„Ρ€Π°Ρ†ΠΈΠ΅ΠΉ:

    асинхронная функция msg_receiver(
            msg_text: MsgText,
            nonce_expected: int,
            macer,
            encrypter,
            peer_name: str,
    ) -> None:
        payload = msg_text["payload"]
        if int(payload["nonce"]) != nonce_expected:
            raise ValueError("Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ nonce")
        mac_tag = mac(macer, KUZNECHIK_BLOCKSIZE, payload.encode())
        if not compare_digest(mac_tag, bytes(msg_text["payloadMac"])):
            raise ValueError("нСдопустимый MAC")
        plaintext = ctr(
            encrypter,
            KUZNECHIK_BLOCKSIZE,
            bytes(payload["ciphertext"]),
            long2bytes(nonce_expected, 8),
        )
        text = plaintext.decode("utf-8")
        await OUT_QUEUES[peer_name].put(text)
    

    Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

    GOSTIM прСдполагаСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π² ΡƒΡ‡Π΅Π±Π½Ρ‹Ρ… цСлях (Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π½Π΅ ΠΏΠΎΠΊΡ€Ρ‹Ρ‚ тСстами, ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ)! Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Ρ‡Π°Ρ‚ΡŒ Ρ‚ΡƒΠΊ (Π‘Ρ‚Ρ€ΠΈΠ±ΠΎΠ³-256 Ρ…ΡΡˆ: 995bbd368c04e50a481d138c5fa2e43ec7c89bc77743ba8dbabee1fde45de120). Как ΠΈ всС ΠΌΠΎΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹, Ρ‚ΠΈΠΏΠ° GoGOST, PyDERASN, NNCP, GoVPN, GOSTIM являСтся ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ свободСн софтуСр, разпространяван ΠΏΡ€ΠΈ условията Π½Π° GPLv3+.

    Π‘Π΅Ρ€Π³Π΅ΠΉ ΠœΠ°Ρ‚Π²Π΅Π΅Π², ΡˆΠΈΡ„Ρ€ΠΎΠΏΠ°Π½ΠΊ, Ρ‡Π»Π΅Π½ Π€ΠΎΠ½Π΄Π° БПО, Python/Go-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ, Π³Π»Π°Π²Π΅Π½ спСциалист Π€Π“Π£ΠŸ «НВЦ β€žΠΡ‚Π»Π°Ρβ€œ.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster