GOSTIM: GOST рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреАрдХреЛ рд╕рд╛рде рдПрдХ рд╕рд╛рдБрдЭрдорд╛ P2P F2F E2EE IM

рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛ рднрдПрд░ PyGOST рдкреБрд╕реНрддрдХрд╛рд▓рдпрд╣рд░реВ (рд╢реБрджреНрдз рдкрд╛рдЗрдердирдорд╛ GOST рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рдкреНрд░рд┐рдорд┐рдЯрд┐рд╡рд╣рд░реВ), рдо рдкреНрд░рд╛рдпрдГ рдШреБрдБрдбрд╛рдорд╛ рд╕рдмреИрднрдиреНрджрд╛ рд╕рд░рд▓ рд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдиреНрджреЗрд╢ рдХрд╕рд░реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрдиреЗ рднрдиреНрдиреЗ рдмрд╛рд░реЗ рдкреНрд░рд╢реНрдирд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдЫреБред рдзреЗрд░реИ рдорд╛рдирд┐рд╕рд╣рд░реВрд▓реЗ рд▓рд╛рдЧреВ рдЧрд░рд┐рдПрдХреЛ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреАрд▓рд╛рдИ рдПрдХрджрдо рд╕рд░рд▓ рдорд╛рдиреНрдЫрдиреН, рд░ рдмреНрд▓рдХ рд╕рд╛рдЗрдлрд░рдорд╛ .encrypt() рд▓рд╛рдИ рдХрд▓ рдЧрд░реНрджрд╛ рдпрд╕рд▓рд╛рдИ рд╕рдВрдЪрд╛рд░ рдЪреНрдпрд╛рдирд▓рдорд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдкрдорд╛ рдкрдард╛рдЙрди рдкрд░реНрдпрд╛рдкреНрдд рд╣реБрдиреЗрдЫред рдЕрд░реВрд╣рд░реВ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдЧрд░реНрдЫрдиреН рдХрд┐ рд▓рд╛рдЧреВ рдЧрд░рд┐рдПрдХреЛ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдереЛрд░реИрдХреЛ рднрд╛рдЧреНрдп рд╣реЛ, рд░ рдпреЛ рд╕реНрд╡реАрдХрд╛рд░реНрдп рдЫ рдХрд┐ рдУрд▓рдореНрдкрд┐рдпрд╛рдб-рдЧрдгрд┐рддрдЬреНрдЮрд╣рд░реВрд╕рдБрдЧ рдЯреЗрд▓рд┐рдЧреНрд░рд╛рдо рдЬрд╕реНрддрд╛ рдзрдиреА рдХрдореНрдкрдиреАрд╣рд░реВред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрди рд╕рдХреНрджреИрди рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░реЛрдЯреЛрдХрд▓ред

рдпреА рд╕рдмреИрд▓реЗ рдорд▓рд╛рдИ рдпреЛ рд▓реЗрдЦ рд▓реЗрдЦреНрди рдкреНрд░реЗрд░рд┐рдд рдЧрд░реНтАНрдпреЛ рдХрд┐ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ рд▓рд╛рдЧреВ рдЧрд░реНрди рд░ рд╕реБрд░рдХреНрд╖рд┐рдд IM рддреНрдпрд╕реНрддреЛ рдЧрд╛рд╣реНрд░реЛ рдХрд╛рдо рд╣реЛрдЗрдиред рдпрджреНрдпрдкрд┐, рдпреЛ рддрдкрд╛рдИрдВрдХреЛ рдЖрдлреНрдиреИ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд░ рдкреНрд░рдореБрдЦ рд╕рдореНрдЭреМрддрд╛ рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдЧрд░реНрди рд▓рд╛рдпрдХ рдЫреИрдиред

GOSTIM: GOST рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреАрдХреЛ рд╕рд╛рде рдПрдХ рд╕рд╛рдБрдЭрдорд╛ P2P F2F E2EE IM
рд▓реЗрдЦ рд▓реЗрдЦреНрдиреЗ рд╣реЛ рдкрд┐рдпрд░ рдЯреБ рдкрд┐рдпрд░, рд╕рд╛рдереА-рд╕рд╛рдереА, рдЕрдиреНрдд-рджреЗрдЦрд┐-рдЕрдиреНрдд рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб рддрддреНрдХрд╛рд▓ рджреВрдд рд╕рдВрдЧ SIGMA-I рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд░ рдкреНрд░рдореБрдЦ рд╕рдореНрдЭреМрддрд╛ рдкреНрд░реЛрдЯреЛрдХрд▓ (рдЬрд╕рдХреЛ рдЖрдзрд╛рд░рдорд╛ рдпреЛ рд▓рд╛рдЧреВ рдЧрд░рд┐рдПрдХреЛ рдЫ IPsec IKE), рд╡рд┐рд╢реЗрд╖ рд░реВрдкрдорд╛ GOST рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо PyGOST рдкреБрд╕реНрддрдХрд╛рд▓рдп рд░ ASN.1 рд╕рдиреНрджреЗрд╢ рдЗрдиреНрдХреЛрдбрд┐рдЩ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджреИ PyDERASN (рдЬрд╕рдХреЛ рдмрд╛рд░реЗрдорд╛ рдо рдкрд╣рд┐рд▓реЗ рдиреИ рдкрд╣рд┐рд▓реЗ рд▓реЗрдЦреЗ)ред рдПрдХ рд╢рд░реНрдд: рдпреЛ рдпрддрд┐ рд╕рд░рд▓ рд╣реБрдиреБрдкрд░реНрдЫ рдХрд┐ рдпрд╕рд▓рд╛рдИ рдПрдХ рд╕рд╛рдБрдЭ (рд╡рд╛ рдХрд╛рд░реНрдпрджрд┐рд╡рд╕) рдорд╛ рд╕реНрдХреНрд░реНрдпрд╛рдЪрдмрд╛рдЯ рд▓реЗрдЦреНрди рд╕рдХрд┐рдиреНрдЫ, рдЕрдиреНрдпрдерд╛ рдпреЛ рдЕрдм рд╕рд╛рдзрд╛рд░рдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдЫреИрдиред рдпрд╕рдорд╛ рддреНрд░реБрдЯрд┐рд╣рд░реВ, рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЬрдЯрд┐рд▓рддрд╛рд╣рд░реВ, рдХрдордЬреЛрд░реАрд╣рд░реВ рдЫрдиреН, рд╕рд╛рдереИ рдпреЛ asyncio рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдореЗрд░реЛ рдкрд╣рд┐рд▓реЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╣реЛред

IM рдбрд┐рдЬрд╛рдЗрди

рдкрд╣рд┐рд▓реЗ, рд╣рд╛рдореАрд▓реЗ рд╣рд╛рдореНрд░реЛ IM рдХрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ рднрдиреЗрд░ рдмреБрдЭреНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╕рд░рд▓рддрд╛рдХреЛ рд▓рд╛рдЧрд┐, рдпрд╕рд▓рд╛рдИ рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрдХреЛ рдХреБрдиреИ рдкрдирд┐ рдЦреЛрдЬ рдмрд┐рдирд╛, рдПрдХ рд╕рд╣рдХрд░реНрдореА-рджреЗрдЦрд┐-рд╕рд╣рдХрд░реНрдореА рдиреЗрдЯрд╡рд░реНрдХ рд╣реБрди рджрд┐рдиреБрд╣реЛрд╕реНред рд╣рд╛рдореА рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдкрдорд╛ рдХреБрди рдареЗрдЧрд╛рдирд╛ рд╕рдВрдХреЗрдд рдЧрд░реНрдиреЗрдЫреМрдВ: рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╕рдБрдЧ рдХреБрд░рд╛рдХрд╛рдиреА рдЧрд░реНрди рдкреЛрд░реНрдЯ рдЬрдбрд╛рди рдЧрд░реНрдиред

рдо рдмреБрдЭреНрдЫреБ рдХрд┐, рдпрд╕ рд╕рдордпрдорд╛, рджреБрдИ рд╕реНрд╡реЗрдЪреНрдЫрд╛рдЪрд╛рд░реА рдХрдореНрдкреНрдпреБрдЯрд░рд╣рд░реВ рдмреАрдЪ рдкреНрд░рддреНрдпрдХреНрд╖ рд╕рдВрдЪрд╛рд░ рдЙрдкрд▓рдмреНрдз рдЫ рднрдиреНрдиреЗ рдзрд╛рд░рдгрд╛ IM рдХреЛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХрддрд╛рдорд╛ рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рд╕реАрдорд┐рддрддрд╛ рд╣реЛред рддрд░ рдЬрддрд┐ рдзреЗрд░реИ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд╣рд░реВрд▓реЗ рд╕рдмреИ рдкреНрд░рдХрд╛рд░рдХрд╛ NAT-рдЯреНрд░рд╛рднрд░реНрд╕рд▓ рдХреНрд░рдЪрд╣рд░реВ рд▓рд╛рдЧреВ рдЧрд░реНрдЫрдиреН, рд╣рд╛рдореА рдЙрддрд┐ рд▓рд╛рдореЛ рд╕рдордпрд╕рдореНрдо IPv4 рдЗрдиреНрдЯрд░рдиреЗрдЯрдорд╛ рд░рд╣рдиреЗрдЫреМрдВ, рдЕрдирд┐рдпрдиреНрддреНрд░рд┐рдд рдХрдореНрдкреНрдпреБрдЯрд░рд╣рд░реВ рдмреАрдЪ рд╕рдЮреНрдЪрд╛рд░рдХреЛ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ рд╕рдореНрднрд╛рд╡рдирд╛рдХреЛ рд╕рд╛рдеред рддрдкрд╛рдИрдВ рдШрд░ рд░ рдХрд╛рдордорд╛ IPv6 рдХреЛ рдЕрднрд╛рд╡ рдХрд╣рд┐рд▓реЗрд╕рдореНрдо рд╕рд╣рди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ?

рд╣рд╛рдореАрд╕рдБрдЧ рдПрдХ рдорд┐рддреНрд░-рдмрд╛рдЯ-рдорд┐рддреНрд░ рдиреЗрдЯрд╡рд░реНрдХ рд╣реБрдиреЗрдЫ: рд╕рдмреИ рд╕рдореНрднрд╛рд╡рд┐рдд рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрд▓рд╛рдИ рдкрд╣рд┐рд▓реЗ рдиреИ рдерд╛рд╣рд╛ рд╣реБрдиреБрдкрд░реНрдЫред рд╕рдмреИрднрдиреНрджрд╛ рдкрд╣рд┐рд▓реЗ, рдпрд╕рд▓реЗ рд╕рдмреИ рдХреБрд░рд╛рд▓рд╛рдИ рдзреЗрд░реИ рд╕рд░рд▓ рдмрдирд╛рдЙрдБрдЫ: рд╣рд╛рдореАрд▓реЗ рдЖрдлреИрд▓рд╛рдИ рдкрд░рд┐рдЪрдп рджрд┐рдпреМрдВ, рдирд╛рдо/рдХреБрдЮреНрдЬреА рдлреЗрд▓рд╛ рдкрд╛рд░реЗрдиреМрдВ, рд╡рд┐рдЪреНрдЫреЗрдж рднрдпреЛ рд╡рд╛ рдХрд╛рдо рдЬрд╛рд░реА рд░рд╛рдЦреНрдЫреМрдВ, рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рд▓рд╛рдИ рдерд╛рд╣рд╛ рдЫред рджреЛрд╕реНрд░реЛ, рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛, рдпреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рдЫ рд░ рдзреЗрд░реИ рдЖрдХреНрд░рдордгрд╣рд░реВ рд╣рдЯрд╛рдЙрдБрдЫред

IM рдЗрдиреНрдЯрд░рдлреЗрд╕ рдХреНрд▓рд╛рд╕рд┐рдХ рд╕рдорд╛рдзрд╛рдирдХреЛ рдирдЬрд┐рдХ рд╣реБрдиреЗрдЫ рдмреЗрдХрд╛рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рд╣рд░реВ, рдЬреБрди рдорд▓рд╛рдИ рд╕рд╛рдБрдЪреНрдЪреИ рддрд┐рдиреАрд╣рд░реВрдХреЛ minimalism рд░ Unix-way рджрд░реНрд╢рдирдХреЛ рд▓рд╛рдЧрд┐ рдордирдкрд░реНрдЫред IM рдХрд╛рд░реНрдпрдХреНрд░рдорд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рдХреЛ рд▓рд╛рдЧрд┐ рддреАрди рдпреБрдирд┐рдХреНрд╕ рдбреЛрдореЗрди рд╕рдХреЗрдЯрд╣рд░реВрдХреЛ рд╕рд╛рде рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реА рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрджрдЫ:

  • рдЕрдиреНрддрд░рд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд▓рд╛рдИ рдкрдард╛рдЗрдПрдХрд╛ рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдпрд╕рдорд╛ рд░реЗрдХрд░реНрдб рдЧрд░рд┐рдПрдХрд╛ рдЫрдиреН;
  • рдмрд╛рд╣рд┐рд░ - рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдпрд╕рдмрд╛рдЯ рдкрдврд┐рдиреНрдЫрдиреН;
  • рд░рд╛рдЬреНрдп - рдпрд╕рдмрд╛рдЯ рдкрдвреЗрд░, рд╣рд╛рдореА рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрдБрдЫреМрдВ рдХрд┐ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛ рд╣рд╛рд▓ рдЬрдбрд╛рди рднрдПрдХреЛ рдЫ, рдЬрдбрд╛рди рдареЗрдЧрд╛рдирд╛/рдкреЛрд░реНрдЯред

рдердк рд░реВрдкрдорд╛, рдПрдХ рдХрдиреНрди рд╕рдХреЗрдЯ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдПрдХреЛ рдЫ, рд╣реЛрд╕реНрдЯ рдкреЛрд░реНрдЯ рд▓реЗрдЦреЗрд░ рдЬрд╕рдорд╛ рд╣рд╛рдореА рд░рд┐рдореЛрдЯ рдЗрдиреНрдЯрд░рд▓реЛрдХреНрдпреВрдЯрд░рдорд╛ рдЬрдбрд╛рди рд╕реБрд░реБ рдЧрд░реНрдЫреМрдВред

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

рдпреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдгрд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ IM рдпрд╛рддрд╛рдпрд╛рдд рд░ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдиреНрдЯрд░рдлреЗрд╕рдХреЛ рд╕реНрд╡рддрдиреНрддреНрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫ, рдХрд┐рдирдХрд┐ рддреНрдпрд╣рд╛рдБ рдХреБрдиреИ рд╕рд╛рдереА рдЫреИрди, рддрдкрд╛рдИрдВ рд╕рдмреИрд▓рд╛рдИ рдЦреБрд╕реА рдкрд╛рд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдиред рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджреИ tmux рд░ / рд╡рд╛ рдорд▓реНрдЯрд┐рдЯрд╛рдЗрд▓, рддрдкрд╛рдИрд▓реЗ рд╕рд┐рдиреНрдЯреНрдпрд╛рдХреНрд╕ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд┐рдЩрдХреЛ рд╕рд╛рде рдмрд╣реБ-рд╡рд┐рдиреНрдбреЛ рдЗрдиреНрдЯрд░рдлреЗрд╕ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред рд░ рд╕рд╣рдпреЛрдЧ рд╕рдВрдЧ rlwrap рддрдкрд╛рдИрдВрд▓реЗ GNU Readline-compatible рд╕рдиреНрджреЗрд╢ рдЗрдирдкреБрдЯ рд▓рд╛рдЗрди рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред

рд╡рд╛рд╕реНрддрд╡рдорд╛, suckless рдкрд░рд┐рдпреЛрдЬрдирд╛рд╣рд░реВрд▓реЗ FIFO рдлрд╛рдЗрд▓рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдЫрдиреНред рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдкрдорд╛, рдореИрд▓реЗ рд╕рдорд░реНрдкрд┐рдд рдереНрд░реЗрдбрд╣рд░реВрдмрд╛рдЯ рд╣рд╛рддрд▓реЗ рд▓реЗрдЦрд┐рдПрдХреЛ рдкреГрд╖реНрдарднреВрдорд┐ рдмрд┐рдирд╛ asyncio рдорд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛рддреНрдордХ рд░реВрдкрдорд╛ рдлрд╛рдЗрд▓рд╣рд░реВрд╕рдБрдЧ рдХрд╕рд░реА рдХрд╛рдо рдЧрд░реНрдиреЗ рднрдиреЗрд░ рдмреБрдЭреНрди рд╕рдХрд┐рди (рдореИрд▓реЗ рд▓рд╛рдореЛ рд╕рдордпрджреЗрдЦрд┐ рддреНрдпрд╕реНрддрд╛ рдЪреАрдЬрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рднрд╛рд╖рд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджреИ рдЖрдПрдХреЛ рдЫреБред Go)ред рддреНрдпрд╕рдХрд╛рд░рдг, рдореИрд▓реЗ рдпреБрдирд┐рдХреНрд╕ рдбреЛрдореЗрди рд╕рдХреЗрдЯрд╣рд░реВрд╕рдБрдЧ рдЧрд░реНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реЗрдВред рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, рдпрд╕рд▓реЗ echo 2001:470:dead::babe 6666 > conn рдЧрд░реНрди рдЕрд╕рдореНрднрд╡ рдмрдирд╛рдЙрдБрдЫред рдореИрд▓реЗ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдпреЛ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реЗрдВ socat: echo 2001:470:dead::bebe 6666 | socat - UNIX-CONNECT:conn, socat READLINE UNIX-Connect:alice/inред

рдореВрд▓ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░реЛрдЯреЛрдХрд▓

TCP рдпрд╛рддрд╛рдпрд╛рддрдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ: рдпрд╕рд▓реЗ рдбреЗрд▓рд┐рднрд░реА рд░ рдпрд╕рдХреЛ рдЕрд░реНрдбрд░рдХреЛ рдЧреНрдпрд╛рд░реЗрдиреНрдЯреА рдЧрд░реНрджрдЫред UDP рд▓реЗ рдЧреНрдпрд╛рд░реЗрдиреНрдЯреА рджрд┐рджреИрди (рдЬреБрди рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛ рдЙрдкрдпреЛрдЧреА рд╣реБрдиреЗрдЫ), рддрд░ рд╕рдорд░реНрдерди SCTP рдкрд╛рдЗрдерди рдмрдХреНрд╕рдмрд╛рдЯ рдмрд╛рд╣рд┐рд░ рдЖрдЙрдБрджреИрдиред

рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, TCP рдорд╛ рд╕рдиреНрджреЗрд╢рдХреЛ рдХреБрдиреИ рдЕрд╡рдзрд╛рд░рдгрд╛ рдЫреИрди, рдХреЗрд╡рд▓ рдмрд╛рдЗрдЯрд╣рд░реВрдХреЛ рд╕реНрдЯреНрд░рд┐рдоред рддрд╕рд░реНрде, рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдврд╛рдБрдЪрд╛рдХреЛ рд╕рд╛рде рдЖрдЙрди рдЖрд╡рд╢реНрдпрдХ рдЫ рддрд╛рдХрд┐ рддрд┐рдиреАрд╣рд░реВ рдпрд╕ рдереНрд░реЗрдбрдорд╛ рдЖрдкрд╕рдорд╛ рд╕рд╛рдЭрд╛ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рд╣рд╛рдореА рд▓рд╛рдЗрди рдлрд┐рдб рдХреНрдпрд╛рд░реЗрдХреНрдЯрд░ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рд╣рдордд рд╣реБрди рд╕рдХреНрдЫреМрдВред рдпреЛ рд╢реБрд░реБрд╡рд╛рддрдХрд╛ рд▓рд╛рдЧрд┐ рд░рд╛рдореНрд░реЛ рдЫ, рддрд░ рд╣рд╛рдореАрд▓реЗ рд╣рд╛рдореНрд░рд╛ рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдЧреБрдкреНрддрд┐рдХрд░рдг рдЧрд░реНрди рд╕реБрд░реБ рдЧрд░реЗрдкрдЫрд┐, рдпреЛ рдХреНрдпрд╛рд░реЗрдХреНрдЯрд░ рд╕рд┐рдлрд░рдЯреЗрдХреНрд╕реНрдЯрдорд╛ рдЬрд╣рд╛рдБ рдкрдирд┐ рджреЗрдЦрд╛ рдкрд░реНрди рд╕рдХреНрдЫред рд╕рдЮреНрдЬрд╛рд▓рд╣рд░реВрдорд╛, рддреНрдпрд╕рдХрд╛рд░рдг, рд▓реЛрдХрдкреНрд░рд┐рдп рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ рддреА рд╣реБрдиреН рдЬрд╕рд▓реЗ рдкрд╣рд┐рд▓реЗ рд╕рдиреНрджреЗрд╢рдХреЛ рд▓рдореНрдмрд╛рдЗ рдмрд╛рдЗрдЯрд╣рд░реВрдорд╛ рдкрдард╛рдЙрдБрдЫрдиреНред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдкрд╛рдЗрдердирдорд╛ xdrlib рдЫ, рдЬрд╕рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ рд╕рдорд╛рди рдврд╛рдБрдЪрд╛рдорд╛ рдХрд╛рдо рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред XDR.

рд╣рд╛рдореАрд▓реЗ TCP рдкрдврд╛рдЗрд╕рдБрдЧ рд╕рд╣реА рд░ рдкреНрд░рднрд╛рд╡рдХрд╛рд░реА рд░реВрдкрдорд╛ рдХрд╛рдо рдЧрд░реНрдиреЗ рдЫреИрдиреМрдВ - рд╣рд╛рдореА рдХреЛрдбрд▓рд╛рдИ рд╕рд░рд▓ рдмрдирд╛рдЙрдиреЗрдЫреМрдВред рд╣рд╛рдореАрд▓реЗ рдкреВрд░рд╛ рд╕рдиреНрджреЗрд╢ рдбрд┐рдХреЛрдб рдирдЧрд░реЗрд╕рдореНрдо рд╣рд╛рдореА рд╕рдХреЗрдЯрдмрд╛рдЯ рдбрд╛рдЯрд╛ рдЕрдирдиреНрдд рд▓реБрдкрдорд╛ рдкрдвреНрдЫреМрдВред XML рд╕рдБрдЧ JSON рдкрдирд┐ рдпрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдгрдХреЛ рд▓рд╛рдЧрд┐ рдврд╛рдБрдЪрд╛рдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рддрд░ рдЬрдм рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдердкрд┐рдиреНрдЫ, рдбрд╛рдЯрд╛рдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрдиреБрдкрд░реНрдиреЗрдЫ - рд░ рдпрд╕рдХрд╛ рд▓рд╛рдЧрд┐ рд╡рд╕реНрддреБрд╣рд░реВрдХреЛ рдмрд╛рдЗрдЯ-рдлрд░-рдмрд╛рдЗрдЯ рд╕рдорд╛рди рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдЖрд╡рд╢реНрдпрдХ рдкрд░реНрджрдЫ, рдЬреБрди JSON/XML рд▓реЗ рдкреНрд░рджрд╛рди рдЧрд░реНрджреИрди (рдбрдореНрдк рдкрд░рд┐рдгрд╛рдорд╣рд░реВ рднрд┐рдиреНрди рд╣реБрди рд╕рдХреНрдЫрдиреН)ред

XDR рдпрд╕ рдХрд╛рд░реНрдпрдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рдЫ, рдпрджреНрдпрдкрд┐ рдо DER рдПрдиреНрдХреЛрдбрд┐рдЩ рд░ ASN.1 рдЫрдиреМрдЯ рдЧрд░реНрдЫреБ PyDERASN рдкреБрд╕реНрддрдХрд╛рд▓рдп, рдХрд┐рдирдХрд┐ рд╣рд╛рдореАрд╕рдБрдЧ рд╣рд╛рддрдорд╛ рдЙрдЪреНрдЪ-рд╕реНрддрд░рдХрд╛ рд╡рд╕реНрддреБрд╣рд░реВ рд╣реБрдиреЗрдЫрдиреН рдЬрд╕рдХреЛ рд╕рд╛рде рдпреЛ рдХрд╛рдо рдЧрд░реНрди рдзреЗрд░реИ рд░рдорд╛рдЗрд▓реЛ рд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реБрдиреНрдЫред рдпреЛрдЬрдирд╛рд╡рд┐рд╣реАрди рд╡рд┐рдкрд░реАрдд рдмреЗрдирдХреЛрдб, 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тФВ тФФтФАтФАтФмтФШтФАтФАтФШ тФАтФАтФА IdA) тФВ тФВтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФА>тФВ тФВ тФВ тФВMsgHandshake(IdB) тФВ тФВ<тФАтФАтФАтФАтФАтФВтФАтФАтФАтФАтФВ тФВ тФВ MsgText() тФВ тФВтФАтФАтФАтФА MsgText() тФВ тФВ тФВ

рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдмрд┐рдирд╛ IM

рдореИрд▓реЗ рдкрд╣рд┐рд▓реЗ рдиреИ рднрдиреЗрдЭреИрдВ, asyncio рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕рдмреИ рд╕рдХреЗрдЯ рдЕрдкрд░реЗрд╢рдирд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреЗрдЫред рд╣рд╛рдореА рдкреНрд░рдХреНрд╖реЗрдкрдгрдорд╛ рдХреЗ рдЖрд╢рд╛ рдЧрд░реНрдЫреМрдВ рднрдиреЗрд░ рдШреЛрд╖рдгрд╛ рдЧрд░реМрдВ:

parser = argparse.ArgumentParser(description="GOSTIM")
parser.add_argument(
    "--our-name",
    required=True,
    help="Our peer name",
)
parser.add_argument(
    "--their-names",
    required=True,
    help="Their peer names, comma-separated",
)
parser.add_argument(
    "--bind",
    default="::1",
    help="Address to listen on",
)
parser.add_argument(
    "--port",
    type=int,
    default=6666,
    help="Port to listen on",
)
args = parser.parse_args()
OUR_NAME = UTF8String(args.our_name)
THEIR_NAMES = set(args.their_names.split(","))

рдЖрдлреНрдиреЛ рдирд╛рдо рд╕реЗрдЯ рдЧрд░реНрдиреБрд╣реЛрд╕реН (--рд╣рд╛рдореНрд░реЛ-рдирд╛рдо рдПрд▓рд┐рд╕)ред рд╕рдмреИ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд╛рд░рд╣рд░реВрд▓рд╛рдИ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо (тАФрддрд┐рдиреАрд╣рд░реВрдХреЛ рдирд╛рдо рдмрдм, рдЗрдн) рджреНрд╡рд╛рд░рд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдЧрд░рд┐рдПрдХреЛ рдЫред рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐, рдпреБрдирд┐рдХреНрд╕ рд╕рдХреЗрдЯрд╣рд░реВ рд╕рд╣рд┐рддрдХреЛ рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реА рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдПрдХреЛ рдЫ, рд╕рд╛рдереИ рдкреНрд░рддреНрдпреЗрдХ рднрд┐рддреНрд░, рдмрд╛рд╣рд┐рд░, рд░рд╛рдЬреНрдпрдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдХреЛрд░реБрдЯрд┐рди:

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_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 рд▓рд╛рдЗрдирд╣рд░реВрдорд╛ рдкрдард╛рдЗрдиреНрдЫ, рдЬрд╕рдмрд╛рдЯ рдбрд╛рдЯрд╛ рдЖрдЙрдЯ рд╕рдХреЗрдЯрдорд╛ рд▓реЗрдЦрд┐рдиреНрдЫ:

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()

рд░рд╛рдЬреНрдп рд╕рдХреЗрдЯрдмрд╛рдЯ рдкрдвреНрджрд╛, рдХрд╛рд░реНрдпрдХреНрд░рдорд▓реЗ 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()

рдХрдиреНрди рд╕рдХреЗрдЯрдорд╛ рдареЗрдЧрд╛рдирд╛ рд▓реЗрдЦреНрджрд╛, рдЬрдбрд╛рди "рдкреНрд░рд╛рд░рдореНрднрд┐рдХ" рдкреНрд░рдХрд╛рд░реНрдп рд╕реБрд░реБ рд╣реБрдиреНрдЫ:

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()

рддреНрдпрд╕рдкрдЫрд┐, рдпреЛ рдЯрд╛рдврд╛рдХреЛ рдкрд╛рд░реНрдЯреАрдмрд╛рдЯ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдкрд░реНрдЦрдиреНрдЫред рд╕рдиреНрджреЗрд╢ ASN.1 рдпреЛрдЬрдирд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдЖрдЧрдорди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдбрд┐рдХреЛрдб рдЧрд░реНрди рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрджрдЫред рд╣рд╛рдореА рдорд╛рдиреНрджрдЫреМрдВ рдХрд┐ рд╕рдореНрдкреВрд░реНрдг рд╕рдиреНрджреЗрд╢ рдПрдХ TCP рдЦрдгреНрдбрдорд╛ рдкрдард╛рдЗрдиреЗрдЫ рд░ .read() рд▓рд╛рдИ рдХрд▓ рдЧрд░реНрджрд╛ рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рдкрд░рдорд╛рдгреБ рд░реВрдкрдорд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗрдЫреМрдВред рд╣рд╛рдореАрд▓реЗ рд╣рд╛рдд рдорд┐рд▓рд╛рдЙрдиреЗ рд╕рдиреНрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНтАНрдпреМрдБ рднрдиреА рдЬрд╛рдБрдЪ рдЧрд░реНрдЫреМрдБред

 141     # Wait for Handshake message {{{
 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 рд▓рд╛рдорд▓реЗ рд╕рдиреНрджреЗрд╢рдХреЛ рдкрд╛рдард╕рдБрдЧ рдкрд╛рдЗрдерди рд╕реНрдЯреНрд░рд┐рдЩрд╣рд░реВ рд╕рдорд╛рддреНрдЫ, рддрд░ None рдХреЛ рд╡рд┐рд╢реЗрд╖ рдорд╛рди рдЫ рдЬрд╕рд▓реЗ msg_sender coroutine рд▓рд╛рдИ рдХрд╛рдо рдЧрд░реНрди рд░реЛрдХреНрдирдХреЛ рд▓рд╛рдЧрд┐ рд╕рдВрдХреЗрдд рдЧрд░реНрдЫ рддрд╛рдХрд┐ рдпрд╕рд▓реЗ рд▓рд┐рдЧреЗрд╕реА 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     # Run text message sender, initialize transport decoder {{{
 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 coroutine рд░реЛрдХреНрдЫреМрдВ (OUT_QUEUES рд▓рд╛рдордорд╛ None рдкрдард╛рдПрд░)ред

 174     buf = b""
 175     # Wait for test messages {{{
 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: max buffer size exceeded", _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: unexpected %s message", _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: disconnecting: %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: received %d characters message", peer_name, len(text))
  69     await OUT_QUEUES[peer_name].put(text)

рдореБрдЦреНрдп рдХреЛрдбрдорд╛ рдлрд░реНрдХреМрдВред рдХрд╛рд░реНрдпрдХреНрд░рдо рд╕реБрд░реБ рд╣реБрдиреЗ рд╕рдордпрдорд╛ рд╕рдмреИ рдХреЛрд░реБрдЯрд┐рдирд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реЗрдкрдЫрд┐, рд╣рд╛рдореА TCP рд╕рд░реНрднрд░ рд╕реБрд░реБ рдЧрд░реНрдЫреМрдВред рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд╛рдкрд┐рдд рдЬрдбрд╛рдирдХреЛ рд▓рд╛рдЧрд┐, рдпрд╕рд▓реЗ рдЬрд╡рд╛рдл рджрд┐рдиреЗ рдХреЛрд░реБрдЯрд┐рди рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрджрдЫред

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("Listening on: %s", server.sockets[0].getsockname())
loop.run_forever()

рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХрд░реНрддрд╛ рдкреНрд░рд╛рд░рдореНрднрдХрд░реНрддрд╛ рдЬрд╕реНрддреИ рдЫ рд░ рд╕рдмреИ рд╕рдорд╛рди рдХрд╛рд░реНрдпрд╣рд░реВ рджрд░реНрдкрдг рдЧрд░реНрджрдЫ, рддрд░ рдкрдарди рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рдЕрд╕реАрдо рдкрд╛рд╢ рддреБрд░реБрдиреНрддреИ рд╕реБрд░реБ рд╣реБрдиреНрдЫ, рд╕рд░рд▓рддрд╛рдХреЛ рд▓рд╛рдЧрд┐ред рд╣рд╛рд▓, рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рдкреНрд░реЛрдЯреЛрдХрд▓рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдкрдХреНрд╖рдмрд╛рдЯ рдПрдХ рд╕рдиреНрджреЗрд╢ рдкрдард╛рдЙрдБрдЫ, рддрд░ рднрд╡рд┐рд╖реНрдпрдорд╛ рдЬрдбрд╛рди рдкреНрд░рд╛рд░рдореНрднрдХрд░реНрддрд╛рдмрд╛рдЯ рджреБрдИрд╡рдЯрд╛ рд╣реБрдиреЗрдЫрдиреН, рдЬрд╕ рдкрдЫрд┐ рдкрд╛рда рд╕рдиреНрджреЗрд╢рд╣рд░реВ рддреБрд░реБрдиреНрддреИ рдкрдард╛рдЙрди рд╕рдХрд┐рдиреНрдЫред

  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()

рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░реЛрдЯреЛрдХрд▓

рдпреЛ рд╣рд╛рдореНрд░реЛ рд╕рдВрдЪрд╛рд░ рд╕реБрд░рдХреНрд╖рд┐рдд рдЧрд░реНрдиреЗ рд╕рдордп рд╣реЛред рд╣рд╛рдореАрд▓реЗ рд╕реБрд░рдХреНрд╖рд╛ рднрдиреЗрдХреЛ рдХреЗ рд╣реЛ рд░ рд╣рд╛рдореА рдХреЗ рдЪрд╛рд╣рдиреНрдЫреМрдВ:

  • рдкреНрд░рд╕рд╛рд░рд┐рдд рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рдЧреЛрдкрдиреАрдпрддрд╛;
  • рдкреНрд░рд╕рд╛рд░рд┐рдд рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рдкреНрд░рд╛рдорд╛рдгрд┐рдХрддрд╛ рд░ рдЕрдЦрдгреНрдбрддрд╛ - рддрд┐рдиреАрд╣рд░реВрдХрд╛ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВ рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрдиреБ рдкрд░реНрдЫ;
  • рд░рд┐рдкреНрд▓реЗ рдЖрдХреНрд░рдордгрд╣рд░реВ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд╛ - рд╣рд░рд╛рдПрдХреЛ рд╡рд╛ рджреЛрд╣реЛрд░реНрдпрд╛рдЗрдПрдХреЛ рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рддрдереНрдп рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрдиреБ рдкрд░реНрдЫ (рд░ рд╣рд╛рдореА рдЬрдбрд╛рди рд╕рдорд╛рдкреНрдд рдЧрд░реНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНрдЫреМрдВ);
  • рдкреВрд░реНрд╡-рдкреНрд░рд╡рд┐рд╖реНрдЯ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рдкрд╣рд┐рдЪрд╛рди рд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг - рд╣рд╛рдореАрд▓реЗ рдкрд╣рд┐рд▓реЗ рдиреИ рдирд┐рд░реНрдгрдп рдЧрд░реНрдпреМрдВ рдХрд┐ рд╣рд╛рдореА рдорд┐рддреНрд░-рдмрд╛рдЯ-рдорд┐рддреНрд░ рдиреЗрдЯрд╡рд░реНрдХ рдмрдирд╛рдЗрд░рд╣реЗрдХрд╛ рдЫреМрдВред рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдкрдЫрд┐ рдорд╛рддреНрд░ рд╣рд╛рдореАрд▓реЗ рдмреБрдЭреНрди рд╕рдХреНрдиреЗрдЫреМрдВ рдХрд┐ рд╣рд╛рдореА рдХреЛрд╕рдБрдЧ рдХреБрд░рд╛рдХрд╛рдиреА рдЧрд░реНрджреИрдЫреМрдВ;
  • рдЙрдкрд▓рдмреНрдзрддрд╛ рдкреВрд░реНрдг рдЕрдЧрд╛рдбрд┐ рдЧреЛрдкрдиреАрдпрддрд╛ рдЧреБрдгрд╣рд░реВ (PFS) - рд╣рд╛рдореНрд░реЛ рд▓рд╛рдореЛ рд╕рдордпрд╕рдореНрдо рдЪрд▓реЗрдХреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреБрдЮреНрдЬреАрдорд╛ рд╕рдореНрдЭреМрддрд╛ рдЧрд░реНрджрд╛ рд╕рдмреИ рдЕрдШрд┐рд▓реНрд▓реЛ рдкрддреНрд░рд╛рдЪрд╛рд░ рдкрдвреНрди рд╕рдХреНрдиреЗ рдХреНрд╖рдорддрд╛рдорд╛ рд▓реИрдЬрд╛рдиреБ рд╣реБрдБрджреИрдиред рдЕрд╡рд░реЛрдзрд┐рдд рдЯреНрд░рд╛рдлрд┐рдХ рд░реЗрдХрд░реНрдбрд┐рдЩ рдмреЗрдХрд╛рд░ рд╣реБрдиреНрдЫ;
  • рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рд╡реИрдзрддрд╛/рд╡реИрдзрддрд╛ (рдЯреНрд░рд╛рдиреНрд╕рдкреЛрд░реНрдЯ рд░ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ) рдХреЗрд╡рд▓ рдПрдХ TCP рд╕рддреНрд░ рднрд┐рддреНрд░ред рдЕрд░реНрдХреЛ рд╕рддреНрд░рдмрд╛рдЯ рд╕рд╣реА рд░реВрдкрдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд/рдкреНрд░рдорд╛рдгрд┐рдд рд╕рдиреНрджреЗрд╢рд╣рд░реВ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реНрди рд╕рдореНрднрд╡ рд╣реБрдиреБ рд╣реБрдБрджреИрди (рдПрдЙрдЯреИ рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рдХреЛ рд╕рд╛рде рдкрдирд┐);
  • рдПрдХ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХрд▓реЗ рдпрд╛ рдд рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛рд╣рд░реВ, рдкреНрд░рд╕рд╛рд░рдг рдЧрд░рд┐рдПрдХреЛ рд▓рд╛рдореЛ рд╕рдордпрд╕рдореНрдо рдЪрд▓реНрдиреЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ, рд╡рд╛ рддрд┐рдиреАрд╣рд░реВрдмрд╛рдЯ рд╣реНрдпрд╛рд╕рд╣рд░реВ рджреЗрдЦреНрдиреБ рд╣реБрдБрджреИрдиред рдирд┐рд╖реНрдХреНрд░рд┐рдп рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХрдмрд╛рдЯ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЕрдЬреНрдЮрд╛рддрддрд╛ред

рдЕрдЪрдореНрдордХреЛ рдХреБрд░рд╛, рд▓рдЧрднрдЧ рд╕рдмреИрдЬрдирд╛ рдХреБрдиреИ рдкрдирд┐ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рдкреНрд░реЛрдЯреЛрдХрд▓рдорд╛ рдпреЛ рдиреНрдпреВрдирддрдо рд╣реБрди рдЪрд╛рд╣рдиреНрдЫрдиреН, рд░ рдорд╛рдерд┐рдХреЛ рдзреЗрд░реИ рдереЛрд░реИ рдЕрдиреНрддрддрдГ "рд╣реЛрдордЧреНрд░рд╛рдЙрди" рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рднреЗрдЯрд┐рдиреНрдЫред рдЕрдм рд╣рд╛рдореА рдХреБрдиреИ рдирдпрд╛рдБ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдЧрд░реНрджреИрдиреМрдВред рдо рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рд┐рдлрд╛рд░рд┐рд╕ рдЧрд░реНрджрдЫреБ рд╢реЛрд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ рдирд┐рд░реНрдорд╛рдг рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐, рддрд░ рдХреЗрд╣реА рд╕рд░рд▓ рдЫрдиреМрдЯ рдЧрд░реМрдВред

рджреБрдИ рд╕рдмреИрднрдиреНрджрд╛ рд▓реЛрдХрдкреНрд░рд┐рдп рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ рд╣реБрдиреН:

  • TLS - рдмрдЧрд╣рд░реВ, рдЬрд╛рдорд╣рд░реВ, рдХрдордЬреЛрд░реАрд╣рд░реВ, рдЦрд░рд╛рдм рд╡рд┐рдЪрд╛рд░, рдЬрдЯрд┐рд▓рддрд╛ рд░ рдХрдордЬреЛрд░реАрд╣рд░реВрдХреЛ рд▓рд╛рдореЛ рдЗрддрд┐рд╣рд╛рд╕ рднрдПрдХреЛ рдПрдХ рдзреЗрд░реИ рдЬрдЯрд┐рд▓ рдкреНрд░реЛрдЯреЛрдХрд▓ (рдпрджреНрдпрдкрд┐, рдпрд╕рдХреЛ TLS 1.3 рд╕рдБрдЧ рдереЛрд░реИ рд╕рдореНрдмрдиреНрдз рдЫ)ред рддрд░ рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рд╡рд┐рдЪрд╛рд░ рдЧрд░реНрджреИрдиреМрдВ рдХрд┐рдирднрдиреЗ рдпреЛ рдзреЗрд░реИ рдЬрдЯрд┐рд▓ рдЫред
  • IPsec ╤Б ike - рдЧрдореНрднреАрд░ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рд╕рдорд╕реНрдпрд╛рд╣рд░реВ рдЫреИрдирдиреН, рдпрджреНрдпрдкрд┐ рддрд┐рдиреАрд╣рд░реВ рдкрдирд┐ рд╕рд░рд▓ рдЫреИрдирдиреНред рдпрджрд┐ рддрдкрд╛рдИрдВрд▓реЗ IKEv1 рд░ IKEv2 рдмрд╛рд░реЗ рдкрдвреНрдиреБрднрдпреЛ рднрдиреЗ, рддрд┐рдиреАрд╣рд░реВрдХреЛ рд╕реНрд░реЛрдд рд╣реЛ рдПрд╕рдЯреАрдПрд╕, ISO/IEC IS 9798-3 рд░ SIGMA (SIGn-and-MAc) рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВ - рдПрдХ рд╕рд╛рдБрдЭ рд▓рд╛рдЧреВ рдЧрд░реНрди рдкрд░реНрдпрд╛рдкреНрдд рд╕рд░рд▓ред

STS/ISO рдкреНрд░реЛрдЯреЛрдХрд▓рд╣рд░реВрдХреЛ рд╡рд┐рдХрд╛рд╕рдорд╛ рдирд╡реАрдирддрдо рд▓рд┐рдЩреНрдХрдХреЛ рд░реВрдкрдорд╛ SIGMA рдХреЛ рдмрд╛рд░реЗрдорд╛ рдХреЗ рд░рд╛рдореНрд░реЛ рдЫ? рдпрд╕рд▓реЗ рд╣рд╛рдореНрд░рд╛ рд╕рдмреИ рдЖрд╡рд╢реНрдпрдХрддрд╛рд╣рд░реВ рдкреВрд░рд╛ рдЧрд░реНрджрдЫ ("рд▓реБрдХрд╛рдЙрдиреЗ" рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛рд╣рд░реВ рд╕рд╣рд┐рдд) рд░ рдХреБрдиреИ рдЬреНрдЮрд╛рдд рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рд╕рдорд╕реНрдпрд╛рд╣рд░реВ рдЫреИрдирдиреНред рдпреЛ рдиреНрдпреВрдирддрдо рдЫ - рдкреНрд░реЛрдЯреЛрдХрд▓ рд╕рдиреНрджреЗрд╢рдмрд╛рдЯ рдХрдореНрддрд┐рдорд╛ рдПрдЙрдЯрд╛ рддрддреНрд╡ рд╣рдЯрд╛рдЙрдирд╛рд▓реЗ рдпрд╕рдХреЛ рдЕрд╕реБрд░рдХреНрд╖рд╛ рдирд┐рдореНрддреНрдпрд╛рдЙрдБрдЫред

рд╕рд┐рдЧреНрдорд╛рдорд╛ рд╕рдмреИрднрдиреНрджрд╛ рд╕рд░рд▓ рдШрд░реЗрд▓реБ рдкреНрд░реЛрдЯреЛрдХрд▓рдмрд╛рдЯ рдЬрд╛рдФрдВред рд╣рд╛рдореАрд▓реЗ рдЪрд╛рд╕реЛ рд░рд╛рдЦреЗрдХреЛ рд╕рдмреИрднрдиреНрджрд╛ рдЖрдзрд╛рд░рднреВрдд рдЕрдкрд░реЗрд╢рди рд╣реЛ рдкреНрд░рдореБрдЦ рд╕рдореНрдЭреМрддрд╛: рдПрдХ рдкреНрд░рдХрд╛рд░реНрдп рдЬрд╕рд▓реЗ рджреБрдмреИ рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрд▓рд╛рдИ рд╕рдорд╛рди рдорд╛рди рдЖрдЙрдЯрдкреБрдЯ рдЧрд░реНрджрдЫ, рдЬреБрди рд╕рд┐рдореЗрдЯреНрд░рд┐рдХ рдХреБрдЮреНрдЬреАрдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рд╡рд┐рд╡рд░рдгрд╣рд░реВрдорд╛ рдирдЧрдИрдХрди: рдкреНрд░рддреНрдпреЗрдХ рдкрдХреНрд╖рд▓реЗ рдХреНрд╖рдгрд┐рдХ (рдПрдЙрдЯрд╛ рд╕рддреНрд░рдорд╛ рдорд╛рддреНрд░ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ) рдХреБрдЮреНрдЬреА рдЬреЛрдбреА (рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░ рдирд┐рдЬреА рдХреБрдЮреНрдЬреАрд╣рд░реВ) рдЙрддреНрдкрдиреНрди рдЧрд░реНрджрдЫ, рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рд╕рд╛рдЯрд╛рд╕рд╛рдЯ рдЧрд░реНрджрдЫ, рд╕рдореНрдЭреМрддрд╛ рдкреНрд░рдХрд╛рд░реНрдпрд▓рд╛рдИ рдХрд▓ рдЧрд░реНрджрдЫ, рдЬрд╕рдХреЛ рдЗрдирдкреБрдЯрдорд╛ рдЙрдиреАрд╣рд░реВрд▓реЗ рдЖрдлреНрдиреЛ рдирд┐рдЬреА рдХреБрдЮреНрдЬреА рд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдкрд╛рд░реНрдЫрдиреНред рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рдХреЛ рдХреБрдЮреНрдЬреАред

тФМтФАтФАтФАтФАтФАтФР тФМтФАтФАтФАтФАтФАтФР тФВPeerAтФВ тФВPeerBтФВ тФФтФАтФАтФмтФАтФАтФШ тФАтФАтФВ Aub тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА>тФВ тХСPrvA, тХР тХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЭ тФВ IdB, PubB тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФВ<тФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФВ тХСPrvB, PubB = DHgen()тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФАтФАтФАтФР тХФтХРтХРтХРтХР тХРтХРтХРтХзтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВ тХСKey = DH(PrvA, PubB)тХС <тФАтФАтФАтФШтХС <тФАтФАтФАтФШтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХЭ тФВ тФВ тФВ тФВ

рдЬреЛ рдХреЛрд╣реАрд▓реЗ рдмреАрдЪрдорд╛ рд╣рд╛рдо рдлрд╛рд▓реНрди рд╕рдХреНрдЫрдиреН рд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдЖрдлреНрдиреИрд╕рдБрдЧ рдмрджрд▓реНрди рд╕рдХреНрдЫрдиреН - рдпрд╕ рдкреНрд░реЛрдЯреЛрдХрд▓рдорд╛ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рдХреБрдиреИ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЫреИрдиред рджрд┐рд░реНрдШрдХрд╛рд▓рд┐рди рдХреБрдЮреНрдЬреАрд╣рд░реВрд╕рдБрдЧ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдердкреМрдВред

тФМтФАтФАтФАтФАтФАтФР тФМтФАтФАтФАтФАтФАтФР тФВPeerAтФВ тФВPeerBтФВ тФФтФАтФАтФмтФАтФАтФШ тФАтФАтФВ, P рдЪрд┐рдиреНрд╣ (SignPrvA, (PubA)) тФВ тХФтХР тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФСтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА ubA = рд▓реЛрдб()тХС тФВ тФВ тХСPrvA, PubA = DHgen() тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР , рдЪрд┐рдиреНрд╣ (SignPrvB, (PubB)) тФВ тХФтХРтХРтХРтФФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФВ тХСSignPrvB, SignPubB = load( )тХС тФВ тФВ тХСPrvB, PubB = DH тХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХЭ тФАтФАтФАтФАтФР тХФ тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХЧ тФВ тФВ тХСрдкреНрд░рдорд╛рдгрд┐рдд( SignPubB, ...)тХС тФВ <тФАтФАтФАтФШ тХСKey = DH(Pr vA, PubB) тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХЭ тФВ тФВ тФВ

рдпрд╕реНрддреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд▓реЗ рдХрд╛рдо рдЧрд░реНрджреИрди, рдХрд┐рдирдХрд┐ рдпреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рддреНрд░рдорд╛ рдмрд╛рдБрдзрд┐рдПрдХреЛ рдЫреИрдиред рддреНрдпрд╕реНрддрд╛ рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдЕрдиреНрдп рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрд╕рдБрдЧ рд╕рддреНрд░рд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдкрдирд┐ "рдЙрдкрдпреБрдХреНрдд" рдЫрдиреНред рд╕рдореНрдкреВрд░реНрдг рд╕рдиреНрджрд░реНрдн рд╕рджрд╕реНрдпрддрд╛ рд▓рд┐рдиреБ рдкрд░реНрдЫред рдпрд╕рд▓реЗ рд╣рд╛рдореАрд▓рд╛рдИ A рдмрд╛рдЯ рдЕрд░реНрдХреЛ рд╕рдиреНрджреЗрд╢ рдердкреНрди рдмрд╛рдзреНрдп рдкрд╛рд░реНрдЫред

рдердк рд░реВрдкрдорд╛, рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЕрдиреНрддрд░реНрдЧрдд рддрдкрд╛рдИрдВрдХреЛ рдЖрдлреНрдиреИ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛ рдердкреНрди рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рдЫ, рдХрд┐рдирдХрд┐ рдЕрдиреНрдпрдерд╛ рд╣рд╛рдореА IdXXX рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЧрд░реНрди рд╕рдХреНрдЫреМрдВ рд░ рдЕрд░реНрдХреЛ рдЬреНрдЮрд╛рдд рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рдХреЛ рдХреБрдЮреНрдЬреАрд▓реЗ рд╕рдиреНрджреЗрд╢рд▓рд╛рдИ рдкреБрди: рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВред рд░реЛрдХрдерд╛рдо рдЧрд░реНрди рдкреНрд░рддрд┐рдмрд┐рдореНрдм рдЖрдХреНрд░рдордгрд╣рд░реВ, рдпреЛ рдЖрд╡рд╢реНрдпрдХ рдЫ рдХрд┐ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЕрдиреНрддрд░реНрдЧрдд рддрддреНрд╡рд╣рд░реВ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдЕрд░реНрде рдЕрдиреБрд╕рд╛рд░ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╕реНрдерд╛рдирд╣рд░реВрдорд╛ рдЫрдиреН: рдпрджрд┐ A рдЪрд┐рдиреНрд╣рд╣рд░реВ (PubA, PubB), рддреНрдпрд╕рдкрдЫрд┐ B рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░реНрдиреБрдкрд░реНрдЫ (PubB, PubA)ред рдпрд╕рд▓реЗ рдХреНрд░рдордмрджреНрдз рдбреЗрдЯрд╛рдХреЛ рд╕рдВрд░рдЪрдирд╛ рд░ рдврд╛рдБрдЪрд╛ рдЫрдиреМрдЯ рдЧрд░реНрдиреЗ рдорд╣рддреНрддреНрд╡рд▓рд╛рдИ рдкрдирд┐ рдмреЛрд▓реНрдЫред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, ASN.1 DER рдПрдиреНрдХреЛрдбрд┐рдЩрдорд╛ рд╕реЗрдЯрд╣рд░реВ рдХреНрд░рдордмрджреНрдз рдЫрдиреН: SET OF(PubA, PubB) SET OF(PubB, PubA) рд╕рдБрдЧ рд╕рдорд╛рди рд╣реБрдиреЗрдЫред

тФМтФАтФАтФАтФАтФАтФР тФМтФАтФАтФАтФАтФАтФР тФВPeerAтФВ тФВPeerBтФВ тФФтФАтФАтФмтФАтФАтФШ тФАтФАтФВ Aub тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА>тФВ тХСSignPrvA, SignPubA = load()тХС тФВ тФВ тХСPrvA, PubA = DHgen тХФ тХР тХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЭ тФВIdB, PubB, рдЪрд┐рдиреНрд╣(SignPrvB, (IdB, PubA, PubB)) тФВ тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВ<тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФВ тХСSignPrvB, SignPubB = load()тХС тФВ тФВ тХСPrvB, PubB = DHgen() тХС тФВ тФВ тФАтХР тХР тХР тХР тХР тХР тХР тХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЭ тФВ рдЪрд┐рдиреНрд╣(SignPrvA, (IdA, PubB, PubA)) тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХЧ тФВтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФА>тФВ тХСрдкреНрд░рдорд╛рдгрд┐рдд (SignPubB, ...) тХС тФВ тФВ тХСkey = dh (prva, PUBB) тХС тФВ тФВ тФВ

рдпрджреНрдпрдкрд┐, рд╣рд╛рдореАрд▓реЗ рдЕрдЭреИ рдкрдирд┐ "рдкреНрд░рдорд╛рдг" рдЧрд░реЗрдХрд╛ рдЫреИрдиреМрдВ рдХрд┐ рд╣рд╛рдореАрд▓реЗ рдпреЛ рд╕рддреНрд░рдХреЛ рд▓рд╛рдЧрд┐ рд╕рдорд╛рди рд╕рд╛рдЭрд╛ рдХреБрдЮреНрдЬреА рдЙрддреНрдкрдиреНрди рдЧрд░реЗрдХрд╛ рдЫреМрдВред рд╕рд┐рджреНрдзрд╛рдиреНрддрдорд╛, рд╣рд╛рдореА рдпреЛ рдЪрд░рдг рдмрд┐рдирд╛ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВ - рдкрд╣рд┐рд▓реЛ рдпрд╛рддрд╛рдпрд╛рдд рдЬрдбрд╛рди рдЕрдорд╛рдиреНрдп рд╣реБрдиреЗрдЫ, рддрд░ рд╣рд╛рдореА рдЪрд╛рд╣рдиреНрдЫреМрдВ рдХрд┐ рдЬрдм рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рдкреВрд░рд╛ рд╣реБрдиреНрдЫ, рд╣рд╛рдореА рдирд┐рд╢реНрдЪрд┐рдд рд╣реБрдиреЗрдЫреМрдВ рдХрд┐ рд╕рдмреИ рдХреБрд░рд╛ рд╡рд╛рд╕реНрддрд╡рдореИ рд╕рд╣рдордд рдЫрдиреНред рдЕрд╣рд┐рд▓реЗ рд╣рд╛рдореАрд╕рдБрдЧ ISO/IEC IS 9798-3 рдкреНрд░реЛрдЯреЛрдХрд▓ рд╣рд╛рддрдорд╛ рдЫред

рд╣рд╛рдореАрд▓реЗ рдЙрддреНрдкрдиреНрди рдЧрд░рд┐рдПрдХреЛ рдХреБрдЮреНрдЬреАрдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВред рдпреЛ рдЦрддрд░рдирд╛рдХ рдЫ, рдХрд┐рдирдХрд┐ рдпреЛ рд╕рдореНрднрд╡ рдЫ рдХрд┐ рддреНрдпрд╣рд╛рдБ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдПрд▓реНрдЧреЛрд░рд┐рджрдордорд╛ рдЪреБрд╣рд╛рд╡рдЯ рд╣реБрди рд╕рдХреНрдЫ (рдмрд┐рдЯреНрд╕-рдкреНрд░рддрд┐-рд╣рд╕реНрддрд╛рдХреНрд╖рд░, рддрд░ рдЕрдЭреИ рдкрдирд┐ рд▓реАрдХ)ред рдпреЛ рд╡реНрдпреБрддреНрдкрдиреНрди рдХреБрдЮреНрдЬреАрдХреЛ рд╣реНрдпрд╛рд╕рдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░реНрди рд╕рдореНрднрд╡ рдЫ, рддрд░ рд╡реНрдпреБрддреНрдкрдиреНрди рдХреБрдЮреНрдЬреАрдХреЛ рд╣реНрдпрд╛рд╕ рдкрдирд┐ рд▓реАрдХ рдЧрд░реНрджрд╛ рд╡реНрдпреБрддреНрдкрдиреНрди рдкреНрд░рдХрд╛рд░реНрдпрдорд╛ рдмреНрд░реВрдЯ-рдлреЛрд░реНрд╕ рдЖрдХреНрд░рдордгрдорд╛ рдореВрд▓реНрдпрд╡рд╛рди рд╣реБрди рд╕рдХреНрдЫред SIGMA рд▓реЗ рдкреНрд░реЗрд╖рдХ ID рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрдиреЗ MAC рдкреНрд░рдХрд╛рд░реНрдп рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫред

тФМтФАтФАтФАтФАтФАтФР тФМтФАтФАтФАтФАтФАтФР тФВPeerAтФВ тФВPeerBтФВ тФФтФАтФАтФмтФАтФАтФШ тФАтФАтФВ Aub тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА>тФВ тХСSignPrvA, SignPubA = load()тХС тФВ тФВ тХСPrv()тХС тФВ тФВ тХСPrv() тХЪ тХРтХРтХРтХРтХРтХРтХР тХР- тХРтХРтХР тФВ<тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФВ тХСSignPrvB, SignPubB = load()тХС тФВ тФВ тХСPrvB, PubB = DHgen() тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХЭ тФВ тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР Pv рдЪрд┐рдиреНрд╣ тФВ тХС рдХреБрдЮреНрдЬреА = DH( PrvA, PubB) тХС тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФА>тФВ тХСрдкреНрд░рдорд╛рдгрд┐рдд (рдХреБрдЮреНрдЬреА, IdB) тХС тФВ тФВ тХСрдкреНрд░рдорд╛рдгрд┐рдд(рд╕рд╛рдЗрди рдкрдмрдмреА, ...)тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХР тХРтХЭ тФВ тФВ

рдПрдХ рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рдирдХреЛ рд░реВрдкрдорд╛, рдХреЛрд╣реА-рдХреЛрд╣реАрд▓реЗ рдЖрдлреНрдиреЛ рдЕрд▓реНрдкрдХрд╛рд▓рд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдкреБрди: рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдЫрдиреН (рдЬреБрди рдкрдХреНрдХреИ рдкрдирд┐ рдкреАрдПрдлрдПрд╕рдХреЛ рд▓рд╛рдЧрд┐ рджреБрд░реНрднрд╛рдЧреНрдпрдкреВрд░реНрдг рдЫ)ред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореАрд▓реЗ рдПрдЙрдЯрд╛ рдХреБрдЮреНрдЬреА рдЬреЛрдбрд╛ рдЙрддреНрдкрдиреНрди рдЧрд░реНрдпреМрдВ, рдЬрдбрд╛рди рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реНтАНрдпреМрдВ, рддрд░ TCP рдЙрдкрд▓рдмреНрдз рдерд┐рдПрди рд╡рд╛ рдкреНрд░реЛрдЯреЛрдХрд▓рдХреЛ рдмреАрдЪрдорд╛ рдХрддреИ рдЕрд╡рд░реЛрдз рднрдпреЛред рдпреЛ рдирдпрд╛рдБ рдЬреЛрдбреАрдорд╛ рдмрд░реНрдмрд╛рдж рдПрдиреНрдЯреНрд░реЛрдкреА рд░ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕реНрд░реЛрддрд╣рд░реВ рдмрд░реНрдмрд╛рдж рдЧрд░реНрди рд▓рд╛рдЬрдорд░реНрджреЛ рдХреБрд░рд╛ рд╣реЛред рддрд╕рд░реНрде, рд╣рд╛рдореА рддрдерд╛рдХрдерд┐рдд рдХреБрдХреА рдкреНрд░рд╕реНрддреБрдд рдЧрд░реНрдиреЗрдЫреМрдВ - рдПрдХ рдЫрджреНрдо-рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдорд╛рди рдЬрд╕рд▓реЗ рдХреНрд╖рдгрд┐рдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдкреБрди: рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛ рд╕рдореНрднрд╛рд╡рд┐рдд рдЕрдирд┐рдпрдорд┐рдд рдкреБрди: рдкреНрд▓реЗ рдЖрдХреНрд░рдордгрд╣рд░реВ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд╛ рдЧрд░реНрдиреЗрдЫред рдХреБрдХреА рд░ рдЕрд▓реНрдкрдХрд╛рд▓рд┐рдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреА рдмреАрдЪрдХреЛ рдмрдиреНрдзрдирдХрд╛ рдХрд╛рд░рдг, рд╡рд┐рдкрд░рд┐рдд рдкрдХреНрд╖рдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд▓рд╛рдИ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдкрдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рдмрд╛рдЯ рд╣рдЯрд╛рдЙрди рд╕рдХрд┐рдиреНрдЫред

тФМтФАтФАтФАтФАтФАтФР тФМтФАтФАтФАтФАтФАтФР тФВPeerAтФВ тФВPeerBтФВ тФФтФАтФАтФмтФАтФАтФШ тФАтФАтФВ, P рдХреБрдХреАрдП тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЧ тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФА>тФВ тХСSignPrvA, SignPubA = рд▓реЛрдб( )тХС тФВ тФВ тХСPrvA, PubA = DHgen() тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХЭ тФВIdB, PubB, рдХреБрдХреАрдмреА рдЪрд┐рдиреНрд╣ тХР тХЧ тФВ< тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА * тФВ тХЪтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЭ тФВ тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХЧ тФВ рдЪрд┐рдиреНрд╣ ( SignPrvA, (CookieB, CookieA, PubA)), MAC(IdA) тФВ тХСKey = DH(PrvA, PubB) тХС тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФА тФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФА>тФВ тХС verify(Key, IdB) тХС тФВ тФВ тХСрдкреНрд░рдорд╛рдгрд┐рдд (SignPubB, ...)тХС тФВ тФВ тХЪтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФВ тФВ

рдЕрдиреНрддрдорд╛, рд╣рд╛рдореА рдирд┐рд╖реНрдХреНрд░рд┐рдп рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХрдмрд╛рдЯ рд╣рд╛рдореНрд░рд╛ рдХреБрд░рд╛рдХрд╛рдиреА рд╕рд╛рдЭреЗрджрд╛рд░рд╣рд░реВрдХреЛ рдЧреЛрдкрдиреАрдпрддрд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдЫреМрдВред рдпрд╕реЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, SIGMA рд▓реЗ рдкрд╣рд┐рд▓реЛ рдкрдЯрдХ рдЕрд▓реНрдкрдХрд╛рд▓рд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдЖрджрд╛рдирдкреНрд░рджрд╛рди рдЧрд░реНрдиреЗ рд░ рд╕рдиреНрджреЗрд╢рд╣рд░реВрд▓рд╛рдИ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд░ рдкрд╣рд┐рдЪрд╛рди рдЧрд░реНрдиреЗ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрдиреЗ рд╕рд╛рдЭрд╛ рдХреБрдЮреНрдЬреА рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрдиреЗ рдкреНрд░рд╕реНрддрд╛рд╡ рдЧрд░реНрджрдЫред SIGMA рд▓реЗ рджреБрдИ рд╡рд┐рдХрд▓реНрдкрд╣рд░реВ рд╡рд░реНрдгрди рдЧрд░реНрджрдЫ:

  • SIGMA-I - рд╕рдХреНрд░рд┐рдп рдЖрдХреНрд░рдордгрд╣рд░реВрдмрд╛рдЯ рд╢реБрд░реБрд╡рд╛рддрдХрд░реНрддрд╛рд▓рд╛рдИ рдмрдЪрд╛рдЙрдБрдЫ, рдирд┐рд╖реНрдХреНрд░рд┐рдпрд╣рд░реВрдмрд╛рдЯ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХрд░реНрддрд╛: рдкреНрд░рд╛рд░рдореНрднрдХрд░реНрддрд╛рд▓реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХрд░реНрддрд╛рд▓рд╛рдИ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрджрдЫ рд░ рдпрджрд┐ рдХреЗрд╣рд┐ рдореЗрд▓ рдЦрд╛рдБрджреИрди рднрдиреЗ, рддреНрдпрд╕рд▓реЗ рдЖрдлреНрдиреЛ рдкрд╣рд┐рдЪрд╛рди рджрд┐рдБрджреИрдиред рдкреНрд░рддрд┐рд╡рд╛рджреАрд▓реЗ рдЖрдлреНрдиреЛ рдкрд░рд┐рдЪрдп рджрд┐рдиреНрдЫ рдпрджрд┐ рдЙрдиреАрд╕рдБрдЧ рд╕рдХреНрд░рд┐рдп рдкреНрд░реЛрдЯреЛрдХрд▓ рд╕реБрд░реБ рд╣реБрдиреНрдЫред рдирд┐рд╖реНрдХреНрд░рд┐рдп рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХрд▓реЗ рдХреЗрд╣реА рд╕рд┐рдХреНрджреИрди;
    SIGMA-R - рд╕рдХреНрд░рд┐рдп рдЖрдХреНрд░рдордгрд╣рд░реВрдмрд╛рдЯ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХрд░реНрддрд╛рд▓рд╛рдИ рдмрдЪрд╛рдЙрдБрдЫ, рдирд┐рд╖реНрдХреНрд░рд┐рдпрд╣рд░реВрдмрд╛рдЯ рд╢реБрд░реБрд╡рд╛рддрдХрд░реНрддрд╛ред рд╕рдмреИ рдареАрдХ рдЙрд▓реНрдЯреЛ рдЫ, рддрд░ рдпрд╕ рдкреНрд░реЛрдЯреЛрдХрд▓рдорд╛ рдЪрд╛рд░ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдкрд╣рд┐рд▓реЗ рдиреИ рдкреНрд░рд╕рд╛рд░рд┐рдд рдЫрдиреНред

    рд╣рд╛рдореА SIGMA-I рдЫрдиреМрдЯ рдЧрд░реНрдЫреМрдВ рдХрд┐рдирдХрд┐ рдпреЛ рдХреНрд▓рд╛рдЗрдиреНрдЯ-рд╕рд░реНрднрд░ рдкрд░рд┐рдЪрд┐рдд рдЪреАрдЬрд╣рд░реВрдмрд╛рдЯ рд╣рд╛рдореАрд▓реЗ рдЕрдкреЗрдХреНрд╖рд╛ рдЧрд░реЗрдХреЛ рдХреБрд░рд╛рд╕рдБрдЧ рдорд┐рд▓реНрджреЛрдЬреБрд▓реНрджреЛ рдЫ: рдХреНрд▓рд╛рдЗрдиреНрдЯрд▓рд╛рдИ рдкреНрд░рдорд╛рдгреАрдХреГрдд рд╕рд░реНрднрд░рд▓реЗ рдорд╛рддреНрд░ рдорд╛рдиреНрдпрддрд╛ рджрд┐рдиреНрдЫ, рд░ рд╕рдмреИрд▓рд╛рдИ рдкрд╣рд┐рд▓реЗ рдиреИ рд╕рд░реНрднрд░ рдерд╛рд╣рд╛ рдЫред рд╕рд╛рдереИ рдХрдо рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рдХрд╛рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрди рд╕рдЬрд┐рд▓реЛ рдЫред рд╣рд╛рдореАрд▓реЗ рдкреНрд░реЛрдЯреЛрдХрд▓рдорд╛ рдердкреНрдиреЗ рднрдиреЗрдХреЛ рд╕рдиреНрджреЗрд╢рдХреЛ рдЕрдВрд╢ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрдиреБ рд░ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛ A рд▓рд╛рдИ рдЕрдиреНрддрд┐рдо рд╕рдиреНрджреЗрд╢рдХреЛ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб рднрд╛рдЧрдорд╛ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдЧрд░реНрдиреБ рд╣реЛ:

    PubA, CookieA тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФА>тФВ тХСSignPrvA , SignPubA = load()тХС тФВ тФВ тХСPrvA, PubA = DHgen() тХС тФХ тХР DHgen тХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тФВ тФВ тФВ тФВ тФВ тФВ тФВ тФВтФВb, usiB ((IDB, рдЪрд┐рдиреНрд╣ (spabvb), рдореНрдпрд╛рдХ (рдЖрдИрдбреАрдмреА)) тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХЧ тФВ<тФАтФФтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тХСSignP rvB, SignPubB = load()тХС тФВ тФВ тФАтФАтФА тФАтФАтФАтФА тХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХЭ тФВ тФВ тХФтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХРтХР тХРтХРтХЧ тФВ Enc((IdA, рдЪрд┐рдиреНрд╣( SignPrvA, (CookieB, CookieA, PubA)), MAC(IdA))) тФВ тХСKey = DH(PrvA, PubB) тХС тФВтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА тФАтФАтФАтФАтФАтФАтФАтФАтФАтФАтФА + тХРтХРтХРтХРтХР тХРтХРтХЭ тФВ тФВ
    
    • GOST R рд╣рд╕реНрддрд╛рдХреНрд╖рд░рдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ 34.10-2012 256-рдмрд┐рдЯ рдХреБрдЮреНрдЬреАрд╣рд░реВрд╕рдБрдЧ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдоред
    • рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреА рдЙрддреНрдкрдиреНрди рдЧрд░реНрди, 34.10-2012 VKO рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫред
    • CMAC MAC рдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫред рдкреНрд░рд╛рд╡рд┐рдзрд┐рдХ рд░реВрдкрдорд╛, рдпреЛ GOST R 34.13-2015 рдорд╛ рд╡рд░реНрдгрди рдЧрд░рд┐рдПрдХреЛ рдмреНрд▓рдХ рд╕рд┐рдлрд░рдХреЛ рд╕рдЮреНрдЪрд╛рд▓рдирдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдореЛрдб рд╣реЛред рдпрд╕ рдореЛрдбрдХреЛ рд▓рд╛рдЧрд┐ рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдкреНрд░рдХрд╛рд░реНрдпрдХреЛ рд░реВрдкрдорд╛ - рдЯрд┐рднреА (34.12-2015)ред
    • рдЙрд╕рдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрдХреЛ рд╣реНрдпрд╛рд╕ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рдХреЛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛рдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫред рд╣реНрдпрд╛рд╕рдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ Stribog-256 (34.11/2012/256 XNUMX рдмрд┐рдЯ)ред

    рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рдкрдЫрд┐, рд╣рд╛рдореА рд╕рд╛рдЭрд╛ рдХреБрдЮреНрдЬреАрдорд╛ рд╕рд╣рдордд рд╣реБрдиреЗрдЫреМрдВред рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рдпрд╛рддрд╛рдпрд╛рдд рд╕рдиреНрджреЗрд╢рд╣рд░реВрдХреЛ рдкреНрд░рдорд╛рдгреАрдХреГрдд рдЗрдиреНрдХреНрд░рд┐рдкреНрд╢рдирдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВред рдпреЛ рднрд╛рдЧ рдзреЗрд░реИ рд╕рд░рд▓ рд░ рдЧрд▓реНрддреА рдЧрд░реНрди рдЧрд╛рд╣реНрд░реЛ рдЫ: рд╣рд╛рдореА рд╕рдиреНрджреЗрд╢ рдХрд╛рдЙрдиреНрдЯрд░ рдмрдврд╛рдЙрдБрдЫреМрдВ, рд╕рдиреНрджреЗрд╢ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрдЫреМрдВ, рдХрд╛рдЙрдиреНрдЯрд░рд▓рд╛рдИ рдкреНрд░рдорд╛рдгреАрдХрд░рдг (MAC) рд░ рд╕рд┐рдлрд░рдЯреЗрдХреНрд╕реНрдЯ рдкрдард╛рдЙрдБрдЫреМрдВред рд╕рдиреНрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрджрд╛, рд╣рд╛рдореА рдХрд╛рдЙрдиреНрдЯрд░рдорд╛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдорд╛рди рдЫ рднрдиреЗрд░ рдЬрд╛рдБрдЪ рдЧрд░реНрдЫреМрдВ, рдХрд╛рдЙрдиреНрдЯрд░рд╕рдБрдЧ рд╕рд┐рдлрд░рдЯреЗрдХреНрд╕реНрдЯ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрдиреБрд╣реЛрд╕реН, рд░ рдпрд╕рд▓рд╛рдИ рдбрд┐рдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрдиреБрд╣реЛрд╕реНред рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рд╕рдиреНрджреЗрд╢рд╣рд░реВ, рдЯреНрд░рд╛рдиреНрд╕рдкреЛрд░реНрдЯ рд╕рдиреНрджреЗрд╢рд╣рд░реВ, рд░ рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдХрд╕рд░реА рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрдиреЗ рднрдиреЗрд░ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрди рдореИрд▓реЗ рдХреБрди рдХреБрдЮреНрдЬреА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреБрдкрд░реНрдЫ? рдпреА рд╕рдмреИ рдХрд╛рд░реНрдпрд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐ рдПрдЙрдЯреИ рдХреБрдЮреНрдЬреА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреБ рдЦрддрд░рдирд╛рдХ рд░ рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рдЫред рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░реНрдпрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдЙрддреНрдкрдиреНрди рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ KDF (рдХреБрдЮреНрдЬреА рд╡реНрдпреБрддреНрдкрдиреНрди рдкреНрд░рдХрд╛рд░реНрдп)ред рдлреЗрд░рд┐, рдХрдкрд╛рд▓ рд╡рд┐рднрд╛рдЬрд┐рдд рдирдЧрд░реМрдВ рд░ рдХреЗрд╣рд┐ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдЧрд░реМрдВ: HKDF рд▓рд╛рдореЛ рд╕рдордпрджреЗрдЦрд┐ рдЬреНрдЮрд╛рдд рдЫ, рд░рд╛рдореНрд░реЛрд╕рдБрдЧ рдЕрдиреБрд╕рдиреНрдзрд╛рди рдЧрд░рд┐рдПрдХреЛ рдЫ рд░ рдХреБрдиреИ рдЬреНрдЮрд╛рдд рд╕рдорд╕реНрдпрд╛рд╣рд░реВ рдЫреИрдирдиреНред рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, рдиреЗрдЯрд┐рдн рдкрд╛рдЗрдерди рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдорд╛ рдпреЛ рдкреНрд░рдХрд╛рд░реНрдп рдЫреИрди, рддреНрдпрд╕реИрд▓реЗ рд╣рд╛рдореА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдЫреМрдВ hkdf рдкреНрд▓рд╛рд╕реНрдЯрд┐рдХ рдЭреЛрд▓рд╛ред HKDF рдЖрдиреНрддрд░рд┐рдХ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫ HMAC, рдЬрд╕рд▓реЗ рдмрд╛рд░реАрдорд╛ рд╣реНрдпрд╛рд╕ рдкреНрд░рдХрд╛рд░реНрдп рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫред рд╡рд┐рдХрд┐рдкрд┐рдбрд┐рдпрд╛ рдкреГрд╖реНрдардорд╛ рдкрд╛рдЗрдердирдорд╛ рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдирд▓реЗ рдХреЛрдбрдХреЛ рдХреЗрд╣реА рд▓рд╛рдЗрдирд╣рд░реВ рдорд╛рддреНрд░ рд▓рд┐рдиреНрдЫред 34.10/2012/256 рдХреЛ рдорд╛рдорд▓рд╛ рдорд╛, рд╣рд╛рдореА рд╣реНрдпрд╛рд╕ рдкреНрд░рдХрд╛рд░реНрдп рдХреЛ рд░реВрдк рдорд╛ Stribog-XNUMX рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВред рд╣рд╛рдореНрд░реЛ рдкреНрд░рдореБрдЦ рд╕рдореНрдЭреМрддрд╛ рдкреНрд░рдХрд╛рд░реНрдпрдХреЛ рдЖрдЙрдЯрдкреБрдЯрд▓рд╛рдИ рд╕рддреНрд░ рдХреБрдЮреНрдЬреА рднрдирд┐рдиреЗрдЫ, рдЬрд╕рдмрд╛рдЯ рдЫреБрдЯреЗрдХрд╛ рд╕рд┐рдореЗрдЯреНрд░рд┐рдХрд╣рд░реВ рдЙрддреНрдкрдиреНрди рд╣реБрдиреЗрдЫрдиреН:

    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 рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реБрдиреЗрдЫред HandshakeTBE - рдХреЗ рдИрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб рд╣реБрдиреЗрдЫред рдо рддрдкрд╛рдИрдХреЛ рдзреНрдпрд╛рди MsgHandshake1 рдорд╛ ukm рдлрд┐рд▓реНрдбрдорд╛ рдЦрд┐рдЪреНрджрдЫреБред 34.10 VKO, рдЙрддреНрдкрдиреНрди рдЧрд░рд┐рдПрдХрд╛ рдХреБрдЮреНрдЬреАрд╣рд░реВрдХреЛ рдЕрдЭ рдареВрд▓реЛ рдЕрдирд┐рдпрдорд┐рддрддрд╛рдХреЛ рд▓рд╛рдЧрд┐, UKM (рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдХреБрдЮреНрдЬреА рд╕рд╛рдордЧреНрд░реА) рдкреНрдпрд╛рд░рд╛рдорд┐рдЯрд░ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ - рдХреЗрд╡рд▓ рдЕрддрд┐рд░рд┐рдХреНрдд рдПрдиреНрдЯреНрд░реЛрдкреАред

    рдХреЛрдбрдорд╛ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдердкреНрджреИ

    рдореВрд▓ рдХреЛрдбрдорд╛ рдЧрд░рд┐рдПрдХрд╛ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВрд▓рд╛рдИ рдорд╛рддреНрд░ рд╡рд┐рдЪрд╛рд░ рдЧрд░реМрдВ, рдХрд┐рдирдХрд┐ рдврд╛рдБрдЪрд╛ рдЙрд╕реНрддреИ рд░рд╣реНрдпреЛ (рд╡рд╛рд╕реНрддрд╡рдорд╛, рдЕрдиреНрддрд┐рдо рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд╣рд┐рд▓реЗ рд▓реЗрдЦрд┐рдПрдХреЛ рдерд┐рдпреЛ, рд░ рддреНрдпрд╕рдкрдЫрд┐ рд╕рдмреИ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдХрд╛рдЯрд┐рдПрдХреЛ рдерд┐рдпреЛ)ред

    рдкреНрд░рдорд╛рдгрд┐рдХрд░рдг рд░ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рдкрд╣рд┐рдЪрд╛рди рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реА рдЧрд░рд┐рдиреЗ рднрдПрдХреЛрд▓реЗ, рддрд┐рдиреАрд╣рд░реВ рдЕрдм рд▓рд╛рдореЛ рд╕рдордпрдХреЛ рд▓рд╛рдЧрд┐ рдХрддреИ рднрдгреНрдбрд╛рд░рдг рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╕рд░рд▓рддрд╛рдХреЛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореА JSON рдпрд╕рд░реА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдЫреМрдВ:

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

    рд╣рд╛рдореНрд░реЛ - рд╣рд╛рдореНрд░реЛ рдХреБрдЮреНрдЬреА рдЬреЛрдбреА, рд╣реЗрдХреНрд╕рд╛рдбреЗрд╕рд┐рдорд▓ рдирд┐рдЬреА рд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВред рддрд┐рдиреАрд╣рд░реВрдХреЛ тАФ рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рд╣рд░реВрдХреЛ рдирд╛рдо рд░ рддрд┐рдиреАрд╣рд░реВрдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВред рдЖрджреЗрд╢ рд░реЗрдЦрд╛ рддрд░реНрдХрд╣рд░реВ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реМрдВ рд░ JSON рдбрд╛рдЯрд╛рдХреЛ рдкреЛрд╕реНрдЯ-рдкреНрд░реЛрд╕реЗрд╕рд┐рдЩ рдердкреМрдВ:

    from pygost import gost3410
    from 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="Generate JSON with our new keypair",
    )
    parser.add_argument(
        "--keys",
        default="keys.json",
        required=False,
        help="JSON with our and their keys",
    )
    parser.add_argument(
        "--bind",
        default="::1",
        help="Address to listen on",
    )
    parser.add_argument(
        "--port",
        type=int,
        default=6666,
        help="Port to listen on",
    )
    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)
    
    # Parse and unmarshal our and their keys {{{
    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() рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдлрд┐рд░реНрддрд╛ рд░реВрдкрд╛рдиреНрддрд░рдг рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╣рд╛рдореАрд▓реЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреАрдмрд╛рдЯ рд╣реНрдпрд╛рд╕рдХреЛ рд░реВрдкрдорд╛ рдЕрдиреНрддрд░реНрд╡рд╛рд░реНрддрд╛рдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛рд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рднрдПрдХреЛрд▓реЗ, рддрд┐рдиреАрд╣рд░реВ рддреБрд░реБрдиреНрддреИ рдЕрдЧреНрд░рд┐рдо рдЧрдгрдирд╛ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ рд░ рджреНрд░реБрдд рдЦреЛрдЬрдХреЛ рд▓рд╛рдЧрд┐ рд╢рдмреНрджрдХреЛрд╢рдорд╛ рд░рд╛рдЦреНрди рд╕рдХрд┐рдиреНрдЫред Stribog-256 hash gost34112012256.GOST34112012256(), рдЬрд╕рд▓реЗ рд╣реНрдпрд╛рд╕ рдкреНрд░рдХрд╛рд░реНрдпрд╣рд░реВрдХреЛ hashlib рдЗрдиреНрдЯрд░рдлреЗрд╕рд▓рд╛рдИ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рд╕рдиреНрддреБрд╖реНрдЯ рдЧрд░реНрджрдЫред

    рд╕реБрд░реБрд╡рд╛рддрдХрд░реНрддрд╛ рдХреЛрд░реБрдЯрд┐рди рдХрд╕рд░реА рдкрд░рд┐рд╡рд░реНрддрди рднрдПрдХреЛ рдЫ? рд╕рдмреИ рдХреБрд░рд╛ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рдпреЛрдЬрдирд╛ рдЕрдиреБрд╕рд╛рд░ рдЫ: рд╣рд╛рдореАрд▓реЗ рдПрдЙрдЯрд╛ рдХреБрдХреА (резреирео-рдмрд┐рдЯ рдкреНрд░рд╢рд╕реНрдд рдЫ), рдПрдЙрдЯрд╛ рдЕрд▓реНрдкрдХрд╛рд▓рд┐рдХ рдХреБрдЮреНрдЬреА рдЬреЛрдбреА рейрек.резреж, рдЬреБрди 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     # Generate our ephemeral public key and cookie, send Handshake 0 message {{{
     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()
    

    • рд╣рд╛рдореА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдкрд░реНрдЦрдиреНрдЫреМрдВ рд░ рдЖрдЧрдорди рд╕рдиреНрджреЗрд╢ рдбрд┐рдХреЛрдб рдЧрд░реНрдЫреМрдВ;
    • рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдЧрд░реНрдиреБрд╣реЛрд╕реН рдХрд┐ рддрдкрд╛рдЗрдБ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ 1 рдкрд╛рдЙрдиреБрд╣реБрдиреНрдЫ;
    • рд╡рд┐рдкрд░рд┐рдд рдкрд╛рд░реНрдЯреАрдХреЛ рдХреНрд╖рдгрд┐рдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреА рдбрд┐рдХреЛрдб рдЧрд░реНрдиреБрд╣реЛрд╕реН рд░ рд╕рддреНрд░ рдХреБрдЮреНрдЬреА рдЧрдгрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реН;
    • рд╣рд╛рдореАрд▓реЗ рд╕рдиреНрджреЗрд╢рдХреЛ 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     # Validate Handshake message {{{
     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() рдХреЛ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдпрд╕рдХреЛ рдмрд╛рдЗрдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡рдмрд╛рдЯ deserialization рдЖрд╡рд╢реНрдпрдХ рдЫред 34.10/2012/256 рдХреЛ рд▓рд╛рдЧрд┐ VKO рдкреНрд░рдХрд╛рд░реНрдп 3410-bit рд╣реЛ gost34102012256_vko.kek_XNUMX() (KEK - рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдХреБрдЮреНрдЬреА)ред

    рдЙрддреНрдкрдиреНрди рд╕рддреНрд░ рдХреБрдЮреНрдЬреА рдкрд╣рд┐рд▓реЗ рдиреИ 256-рдмрд┐рдЯ рд╕реНрдпреВрдбреЛ-рдЕрдирд┐рдпрдорд┐рдд рдмрд╛рдЗрдЯ рдЕрдиреБрдХреНрд░рдо рд╣реЛред рддреНрдпрд╕реИрд▓реЗ, рдпреЛ рддреБрд░реБрдиреНрддреИ HKDF рдкреНрд░рдХрд╛рд░реНрдпрд╣рд░реВрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред GOST34112012256 рд▓реЗ hashlib рдЗрдиреНрдЯрд░рдлреЗрд╕рд▓рд╛рдИ рд╕рдиреНрддреБрд╖реНрдЯ рдкрд╛рд░реЗрдХреЛ рд╣реБрдирд╛рд▓реЗ, рдпрд╕рд▓рд╛рдИ Hkdf рдХрдХреНрд╖рд╛рдорд╛ рддреБрд░реБрдиреНрддреИ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рд╣рд╛рдореА рдиреБрди (Hkdf рдХреЛ рдкрд╣рд┐рд▓реЛ рддрд░реНрдХ) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реНрджреИрдиреМрдВ, рдХрд┐рдирдХрд┐ рдЙрддреНрдкрдиреНрди рдХреБрдЮреНрдЬреА, рд╕рд╣рднрд╛рдЧреА рдХреБрдЮреНрдЬреА рдЬреЛрдбреАрд╣рд░реВрдХреЛ рдЕрд▓реНрдкрдХрд╛рд▓реАрдирддрд╛рдХрд╛ рдХрд╛рд░рдг, рдкреНрд░рддреНрдпреЗрдХ рд╕рддреНрд░рдХреЛ рд▓рд╛рдЧрд┐ рдлрд░рдХ рд╣реБрдиреЗрдЫ рд░ рдкрд╣рд┐рд▓реЗ рдиреИ рдкрд░реНрдпрд╛рдкреНрдд рдПрдиреНрдЯреНрд░реЛрдкреА рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд░реВрдкрдорд╛ kdf.expand() рд▓реЗ рдкрд╣рд┐рд▓реЗ рдиреИ рдкрдЫрд┐ рдЧреНрд░рд╛рд╕рдкрд░рдХрд╛ рд▓рд╛рдЧрд┐ рдЖрд╡рд╢реНрдпрдХ 256-рдмрд┐рдЯ рдХреБрдЮреНрдЬреАрд╣рд░реВ рдЙрддреНрдкрд╛рджрди рдЧрд░реНрджрдЫред

    рдЕрд░реНрдХреЛ, рдЖрдЧрдорди рд╕рдиреНрджреЗрд╢рдХреЛ TBE рд░ TBS рднрд╛рдЧрд╣рд░реВ рдЬрд╛рдБрдЪ рдЧрд░рд┐рдиреНрдЫ:

    • рдЖрдЧрдорди рд╕рд╛рдЗрдлрд░рдЯреЗрдХреНрд╕реНрдЯ рдорд╛ MAC рдЧрдгрдирд╛ рд░ рдЬрд╛рдБрдЪ рдЧрд░рд┐рдПрдХреЛ рдЫ;
    • рд╕рд┐рдлрд░рдЯреЗрдХреНрд╕реНрдЯ рдбрд┐рдХреНрд░рд┐рдкреНрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫ;
    • TBE рд╕рдВрд░рдЪрдирд╛ рдбрд┐рдХреЛрдб рдЧрд░рд┐рдПрдХреЛ рдЫ;
    • рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рдХреЛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛ рдпрд╕рдмрд╛рдЯ рд▓рд┐рдЗрдиреНрдЫ рд░ рдпреЛ рдЬрд╛рдБрдЪ рдЧрд░рд┐рдиреНрдЫ рдХрд┐ рдЙрдиреА рд╣рд╛рдореАрд▓рд╛рдИ рдЪрд┐рдиреНрдЫрдиреН рдХрд┐ рдЫреИрдирдиреН;
    • рдпреЛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛ рдорд╛ MAC рдЧрдгрдирд╛ рд░ рдЬрд╛рдБрдЪ рдЧрд░рд┐рдПрдХреЛ рдЫ;
    • TBS рд╕рдВрд░рдЪрдирд╛рдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкреНрд░рдорд╛рдгрд┐рдд рд╣реБрдиреНрдЫ, рдЬрд╕рдорд╛ рджреБрд╡реИ рдкрдХреНрд╖рдХреЛ рдХреБрдХреА рд░ рд╡рд┐рдкрд░рд┐рдд рдкрдХреНрд╖рдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЕрд▓реНрдкрдХрд╛рд▓рд┐рдХ рдХреБрдЮреНрдЬреА рд╕рдорд╛рд╡реЗрд╢ рд╣реБрдиреНрдЫред рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╡рд╛рд░реНрддрд╛рдХрд╛рд░рдХреЛ рд▓рд╛рдореЛ рд╕рдордпрд╕рдореНрдо рд░рд╣рдиреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреБрдЮреНрдЬреА рджреНрд╡рд╛рд░рд╛ рдкреНрд░рдорд╛рдгрд┐рдд рд╣реБрдиреНрдЫред

     441     try:
     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     except ValueError as err:
     452         logging.warning("%s: %s, disconnecting", _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("invalid 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     except ASN1Error:
     150         raise ValueError("can not decode 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("unknown identity")
     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("invalid identity 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("invalid signature")
     174     return peer["name"]
    

    рдореИрд▓реЗ рдорд╛рдерд┐ рд▓реЗрдЦреЗ рдЕрдиреБрд╕рд╛рд░, 34.13/2015/XNUMX рд▓реЗ рд╡рд┐рднрд┐рдиреНрди рд╡рд░реНрдгрди рдЧрд░реНрджрдЫ рдмреНрд▓рдХ рд╕рд╛рдЗрдлрд░ рдЕрдкрд░реЗрдЯрд┐рдЩ рдореЛрдбрд╣рд░реВ 34.12/2015/3413 рдмрд╛рдЯред рддрд┐рдиреАрд╣рд░реВрдордзреНрдпреЗ рдирдХреНрдХрд▓ рдЗрдиреНрд╕рд░реНрдЯрд╣рд░реВ рд░ MAC рдЧрдгрдирд╛рд╣рд░реВ рдЙрддреНрдкрдиреНрди рдЧрд░реНрдиреЗ рдореЛрдб рдЫред PyGOST рдорд╛ рдпреЛ gost34.12.mac() рд╣реЛред рдпреЛ рдореЛрдбрд▓рд╛рдИ рдЗрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдкреНрд░рдХрд╛рд░реНрдп (рдбреЗрдЯрд╛рдХреЛ рдПрдХ рдмреНрд▓рдХ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рд░ рдлрд┐рд░реНрддрд╛ рдЧрд░реНрдиреЗ), рдЗрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдмреНрд▓рдХрдХреЛ рд╕рд╛рдЗрдЬ рд░ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдбрд╛рдЯрд╛ рдЖрдлреИрдВ рдкрд╛рд╕ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рддрдкрд╛рдЗрдБ рдХрд┐рди рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдмреНрд▓рдХрдХреЛ рдЖрдХрд╛рд░ рд╣рд╛рд░реНрдбрдХреЛрдб рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрди? 2015/128/64 рд▓реЗ XNUMX-рдмрд┐рдЯ рдЧреНрд░рд╛рд╕реЛрдкрд░ рд╕рд╛рдЗрдлрд░ рдорд╛рддреНрд░ рд╣реЛрдЗрди, рддрд░ XNUMX-рдмрд┐рдЯ рдкрдирд┐ рд╡рд░реНрдгрди рдЧрд░реНрджрдЫред рдореНрдпрд╛рдЧреНрдорд╛ - рдереЛрд░реИ рдкрд░рд┐рдорд╛рд░реНрдЬрд┐рдд GOST 28147-89, KGB рдорд╛ рдлреЗрд░рд┐ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдПрдХреЛ рд░ рдЕрдЭреИ рдкрдирд┐ рдЙрдЪреНрдЪрддрдо рд╕реБрд░рдХреНрд╖рд╛ рдереНрд░реЗрд╕рд╣реЛрд▓реНрдбрд╣рд░реВ рдордзреНрдпреЗ рдПрдХ рдЫред

    Kuznechik рд▓рд╛рдИ gost.3412.GOST3412Kuznechik(key) рдорд╛ рдХрд▓ рдЧрд░реЗрд░ рдкреНрд░рд╛рд░рдореНрдн рдЧрд░рд┐рдПрдХреЛ рдЫ рд░ .encrypt()/.decrypt() рд╡рд┐рдзрд┐рд╣рд░реВ 34.13 рдкреНрд░рдХрд╛рд░реНрдпрд╣рд░реВрдорд╛ рдкрд╛рд╕ рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рднрдПрдХреЛ рд╡рд╕реНрддреБ рдлрд┐рд░реНрддрд╛ рдЧрд░реНрдЫред MAC рд▓рд╛рдИ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЧрдгрдирд╛ рдЧрд░рд┐рдиреНрдЫ: gost3413.mac(GOST3412Kuznechik(key)ред encrypt, KUZNECHIK_BLOCKSIZE, ciphertext)ред рдЧрдгрдирд╛ рдЧрд░рд┐рдПрдХреЛ рд░ рдкреНрд░рд╛рдкреНрдд рднрдПрдХреЛ MAC рддреБрд▓рдирд╛ рдЧрд░реНрди, рддрдкрд╛рдИрд▓реЗ рдмрд╛рдЗрдЯ рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддреБрд▓рдирд╛ (==) рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрди, рдХрд┐рдирдХрд┐ рдпреЛ рдЕрдкрд░реЗрд╢рдирд▓реЗ рддреБрд▓рдирд╛рддреНрдордХ рд╕рдордп рдЪреБрд╣рд╛рд╡рдЯ рдЧрд░реНрдЫ, рдЬреБрди рд╕рд╛рдорд╛рдиреНрдп рдЕрд╡рд╕реНрдерд╛рдорд╛, рдШрд╛рддрдХ рдХрдордЬреЛрд░реАрд╣рд░реВ рдирд┐рдореНрддреНрдпрд╛рдЙрди рд╕рдХреНрдЫред BEAST TLS рдорд╛ рдЖрдХреНрд░рдордгред рдкрд╛рдЗрдердирдХреЛ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░реНрдп рдЫ, 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)ред рдЗрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдмреНрд▓рдХрдХреЛ рдареНрдпрд╛рдХреНрдХреИ рдЖрдзрд╛ рд▓рдореНрдмрд╛рдЗ рднрдПрдХреЛ рдкреНрд░рд╛рд░рдореНрднрд┐рдХ рднреЗрдХреНрдЯрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рдпрджрд┐ рд╣рд╛рдореНрд░реЛ рдЗрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдХреБрдЮреНрдЬреА рдХреЗрд╡рд▓ рдПрдЙрдЯрд╛ рд╕рдиреНрджреЗрд╢ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрди рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ (рдзреЗрд░реИ рдмреНрд▓рдХрд╣рд░реВрдмрд╛рдЯ рднрдП рдкрдирд┐), рддреНрдпрд╕рдкрдЫрд┐ рдпреЛ рд╢реВрдиреНрдп рдкреНрд░рд╛рд░рдореНрднрд┐рдХ рднреЗрдХреНрдЯрд░ рд╕реЗрдЯ рдЧрд░реНрди рд╕реБрд░рдХреНрд╖рд┐рдд рдЫред рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рд╕рдиреНрджреЗрд╢рд╣рд░реВ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрди, рд╣рд╛рдореА рдкреНрд░рддреНрдпреЗрдХ рдкрдЯрдХ рдЫреБрдЯреНрдЯреИ рдХреБрдЮреНрдЬреА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдЫреМрдВред

    рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг gost3410.verify() рдорд╛рдореВрд▓реА рдЫ: рд╣рд╛рдореА рдЕрдгреНрдбрд╛рдХрд╛рд░ рд╡рдХреНрд░ рдкрд╛рд░ рдЧрд░реНрдЫреМрдВ рдЬреБрди рднрд┐рддреНрд░ рд╣рд╛рдореАрд▓реЗ рдХрд╛рдо рдЧрд░рд┐рд░рд╣реЗрдХрд╛ рдЫреМрдВ (рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рд╣рд╛рдореНрд░реЛ GOSTIM рдкреНрд░реЛрдЯреЛрдХрд▓рдорд╛ рд░реЗрдХрд░реНрдб рдЧрд░реНрдЫреМрдВ), рд╣рд╕реНрддрд╛рдХреНрд╖рд░рдХрд░реНрддрд╛рдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдЮреНрдЬреА (рдпреЛ рджреБрдИрдХреЛ рдЯреБрдкрд▓ рд╣реБрдиреБрдкрд░реНрдЫ рднрдиреЗрд░ рдирдмрд┐рд░реНрд╕рдиреБрд╣реЛрд╕реНред рдареВрд▓реЛ рд╕рдВрдЦреНрдпрд╛, рд░ рдмрд╛рдЗрдЯ рд╕реНрдЯреНрд░рд┐рдЩ рд╣реЛрдЗрди), 34.11/2012/XNUMX рд╣реНрдпрд╛рд╕ рд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЖрдлреИред

    рдЕрд░реНрдХреЛ, рдЗрдирд┐рд╕рд┐рдПрдЯрд░рдорд╛ рд╣рд╛рдореА рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ реи рдорд╛ рд╣реНрдпрд╛рдиреНрдбрд╢реЗрдХ рд╕рдиреНрджреЗрд╢ рддрдпрд╛рд░ рдЧрд░реНрдЫреМрдВ рд░ рдкрдард╛рдЙрдБрдЫреМрдВ, рдкреНрд░рдорд╛рдгреАрдХрд░рдгрдХреЛ рдХреНрд░рдордорд╛ рд╣рд╛рдореАрд▓реЗ рдЧрд░реЗрдХреЛ рд╕рдорд╛рди рдХрд╛рд░реНрдпрд╣рд░реВ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрджреИ, рдХреЗрд╡рд▓ рд╕рдордорд┐рдд рд░реВрдкрдорд╛: рдЬрд╛рдБрдЪ рдЧрд░реНрдиреБрдХреЛ рд╕рдЯреНрдЯрд╛ рд╣рд╛рдореНрд░реЛ рдХреБрдЮреНрдЬреАрд╣рд░реВрдорд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░реНрдиреЗ, рдЗрддреНрдпрд╛рджрд┐...

     456     # Prepare and send Handshake 2 message {{{
     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: session established: %s", _id, peer_name)
     

    рдЬрдм рд╕рддреНрд░ рд╕реНрдерд╛рдкрдирд╛ рд╣реБрдиреНрдЫ, рдпрд╛рддрд╛рдпрд╛рдд рдХреБрдЮреНрдЬреАрд╣рд░реВ рдЙрддреНрдкрдиреНрди рд╣реБрдиреНрдЫрдиреН (рдЗрдиреНрдХреНрд░рд┐рдкреНрд╕рдирдХреЛ рд▓рд╛рдЧрд┐ рдЫреБрдЯреНрдЯреИ рдХреБрдЮреНрдЬреА, рдкреНрд░рдорд╛рдгреАрдХрд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдкреНрд░рддреНрдпреЗрдХ рдкрдХреНрд╖рдХрд╛ рд▓рд╛рдЧрд┐), рд░ рдЧреНрд░рд╛рд╕рдкрд░рд▓рд╛рдИ MAC рдбрд┐рдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрди рд░ рдЬрд╛рдБрдЪ рдЧрд░реНрди рдкреНрд░рд╛рд░рдореНрдн рдЧрд░рд┐рдПрдХреЛ рдЫ:

     499     # Run text message sender, initialize transport decoder {{{
     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     # Wait for test messages {{{
     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 coroutine рд▓реЗ рдЕрдм рд╕рдиреНрджреЗрд╢рд╣рд░реВрд▓рд╛рдИ TCP рдЬрдбрд╛рдирдорд╛ рдкрдард╛рдЙрдиреБ рдЕрдШрд┐ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрдЫред рдкреНрд░рддреНрдпреЗрдХ рд╕рдиреНрджреЗрд╢рдорд╛ рдореЛрдиреЛрдЯреЛрдирд┐рдХ рд░реВрдкрдорд╛ рдмрдвреНрджреЛ рдиреЛрдиреНрд╕ рд╣реБрдиреНрдЫ, рдЬреБрди рдХрд╛рдЙрдиреНрдЯрд░ рдореЛрдбрдорд╛ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрджрд╛ рдкреНрд░рд╛рд░рдореНрднрд┐рдХ рднреЗрдХреНрдЯрд░ рдкрдирд┐ рд╣реБрдиреНрдЫред рдкреНрд░рддреНрдпреЗрдХ рд╕рдиреНрджреЗрд╢ рд░ рд╕рдиреНрджреЗрд╢ рдмреНрд▓рдХ рдлрд░рдХ рдХрд╛рдЙрдиреНрдЯрд░ рдореВрд▓реНрдп рдЫ рдЧреНрдпрд╛рд░реЗрдиреНрдЯреА рдЫред

    async def 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 coroutine рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╢реЛрдзрди рдЧрд░рд┐рдиреНрдЫ, рдЬрд╕рд▓реЗ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд░ рдбрд┐рдХреНрд░рд┐рдкреНрд╢рди рд╣реНрдпрд╛рдиреНрдбрд▓ рдЧрд░реНрджрдЫ:

    async def 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("unexpected nonce value")
        mac_tag = mac(macer, KUZNECHIK_BLOCKSIZE, payload.encode())
        if not compare_digest(mac_tag, bytes(msg_text["payloadMac"])):
            raise ValueError("invalid 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, NCCP, GoVPN, GOSTIM рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдЫ рдирд┐: рд╢реБрд▓реНрдХ рд╕рдлреНрдЯрд╡реЗрдпрд░, рд╕рд░реНрддрд╣рд░реВ рдЕрдиреНрддрд░реНрдЧрдд рд╡рд┐рддрд░рд┐рдд GPLv3 +.

    рд╕рд░реНрдЧреЗрдИ Matveev, рд╕рд╛рдЗрдлрд░рдкрдВрдХ, рд╕рджрд╕реНрдп SPO рдлрд╛рдЙрдиреНрдбреЗрд╕рди, рдкрд╛рдЗрдерди/рдЧреЛ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛, рдкреНрд░рдореБрдЦ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ FSUE "STC "рдПрдЯрд▓рд╕".

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди