рд╡реЗрдм рдХреНрд░рд┐рдкреНрдЯреЛ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЬреЗрдПрд╕ рдореЗрдВ 2FA рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ рдкрд╛рд╕рд╡рд░реНрдб рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ

рдкрд░рд┐рдЪрдп


рджреЛ-рдХрд╛рд░рдХ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЖрдЬ рд╣рд░ рдЬрдЧрд╣ рд╣реИред рдЙрд╕рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдПрдХ рдЦрд╛рддрд╛ рдЪреЛрд░реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдПрдХ рдкрд╛рд╕рд╡рд░реНрдб рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред рдФрд░ рдпрджреНрдпрдкрд┐ рдЗрд╕рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдпрд╣ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддреА рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдЦрд╛рддреЗ рдХреЛ рдЗрд╕рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдЯрд╛рдпрд╛ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛, рдПрдХ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдФрд░ рдмрд╣реБ-рд╕реНрддрд░реАрдп рд╣рдорд▓реЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдХреБрдЫ рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рдЙрддрдиреА рд╣реА рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред


рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рд╣рд░ рдХреЛрдИ рдЬреЛ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмрд╛рд░ рдЕрдкрдиреЗ рдЬреАрд╡рди рдореЗрдВ рджреЛ-рдХрд╛рд░рдХ рдкреНрд░рдорд╛рдгреАрдХрд░рдг (рдЗрд╕рдХреЗ рдмрд╛рдж 2FA рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд, рдПрдХ рджрд░реНрджрдирд╛рдХ рд▓рдВрдмреА рд╡рд╛рдХреНрдпрд╛рдВрд╢) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЖрдЬ рдореИрдВ рдЖрдкрдХреЛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рддрдХрдиреАрдХ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ, рдЬреЛ рдкреНрд░рддрд┐рджрд┐рди рдЕрдирдЧрд┐рдирдд рдЦрд╛рддреЛрдВ рдХреА рд╕реБрд░рдХреНрд╖рд╛ рдХрд░рддреА рд╣реИред


рд▓реЗрдХрд┐рди рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рдЖрдк рдЖрдЬ рд╣рдо рдЬреЛ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдЙрд╕рдХреЗ рдбреЗрдореЛ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред


рдореВрд▓ рдмрд╛рддреЗрдВ


рдПрдХ рдмрд╛рд░ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд╡реЗ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реЛрддреЗ рд╣реИрдВ: HOTP рдФрд░ TOTP ред рдЕрд░реНрдерд╛рддреН, рдПрдЪрдПрдордПрд╕реА-рдЖрдзрд╛рд░рд┐рдд рд╡рди рдЯрд╛рдЗрдо рдкрд╛рд╕рд╡рд░реНрдб рдФрд░ рд╕рдордп-рдЖрдзрд╛рд░рд┐рдд рдУрдЯреАрдкреА ред TOTP HOTP рдХреЗ рд▓рд┐рдП рдПрдХ рдРрдб-рдСрди рд╣реИ, рддреЛ рдЪрд▓рд┐рдП рдкрд╣рд▓реЗ рдПрдХ рд╕рд░рд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред


HOTP рдХреЛ RFC4226 рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рдЫреЛрдЯрд╛ рд╣реИ, рдХреЗрд╡рд▓ 35 рдкреГрд╖реНрда, рдФрд░ рдЗрд╕рдореЗрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдП: рдПрдХ рдФрдкрдЪрд╛рд░рд┐рдХ рд╡рд┐рд╡рд░рдг, рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ред рдЖрдЗрдП рдмреБрдирд┐рдпрд╛рджреА рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рджреЗрдЦреЗрдВред


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


рдореИрдХ рдЯреИрдЧ


рдПрдХ рд╣реИрд╢ рдХреНрдпрд╛ рд╣реИ? рдПрдХ рд╣реИрд╢ рдПрдХ рд╕рдВрджреЗрд╢ рдХреЛ рд╣реИрд╢ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИред рд╣реИрд╢ рдлрд╝рдВрдХреНрд╢рди рдЖрдкрдХреЗ рдбреЗрдЯрд╛ рдХреЛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдирд┐рд╢реНрдЪрд┐рдд рд▓рдВрдмрд╛рдИ рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдирд╛рддреЗ рд╣реИрдВред рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╕рд┐рджреНрдз рдПрдордбреА 5 рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдлрд╝рд╛рдЗрд▓ рдЕрдЦрдВрдбрддрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред


рдореИрдХ рд╕реНрд╡рдпрдВ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╢рдмреНрдж рд╣реИред рдПрдЪрдПрдордПрд╕реА, рдмрджрд▓реЗ рдореЗрдВ, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдареЛрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдПрдЪрдПрдордПрд╕реА- рдПрдХреНрд╕ , рдЬрд╣рд╛рдВ рдПрдХреНрд╕ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рд╣реИрд╢ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред рдПрдЪрдПрдордПрд╕реА рджреЛ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ: рдПрдХ рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдФрд░ рдПрдХ рд╕рдВрджреЗрд╢, рдЙрдиреНрд╣реЗрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рддрд░реАрдХреЗ рд╕реЗ рдорд┐рд▓рд╛рддрд╛ рд╣реИ, рдЪрдпрдирд┐рдд рд╣реИрд╢ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреЛ рдмрд╛рд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдореИрдХ рдЯреИрдЧ рджреЗрддрд╛ рд╣реИред


рдпрджрд┐ рдЖрдк рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рд╕реЛрдЪ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╕рдм рдПрдХ рдмрд╛рд░ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ - рдЪрд┐рдВрддрд╛ рдордд рдХрд░реЛ, рд╣рдо рд▓рдЧрднрдЧ рдореБрдЦреНрдп рдмрд┐рдВрджреБ рдкрд░ рдкрд╣реБрдВрдЪ рдЧрдП рд╣реИрдВред


рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдХреЗ рдЕрдиреБрд╕рд╛рд░, HOTP рдХреА рдЧрдгрдирд╛ рджреЛ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреА рдЬрд╛рддреА рд╣реИ:


  • K рд╡рд╣ рдЧреБрдкреНрдд рдХреБрдВрдЬреА рд╣реИ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдЬрд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рдХрдо рд╕реЗ рдХрдо 128 рдмрд┐рдЯ рд▓рдВрдмрд╛, рдФрд░ рдЕрдзрд┐рдорд╛рдирддрдГ 160 рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЬрдм рдЖрдк 2FA рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
  • C рдХрд╛рдЙрдВрдЯрд░ рд╣реИ ред

рдПрдХ рдХрд╛рдЙрдВрдЯрд░ рдЧреНрд░рд╛рд╣рдХ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рдмреАрдЪ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдПрдХ 8-рдмрд╛рдЗрдЯ рдорд╛рди рд╣реИред рдЬреИрд╕реЗ рд╣реА рдЖрдк рдирдП рдкрд╛рд╕рд╡рд░реНрдб рдЬрдирд░реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рдЕрдкрдбреЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред HOTP рдпреЛрдЬрдирд╛ рдореЗрдВ, рдЬрдм рднреА рдЖрдк рдПрдХ рдирдпрд╛ рдкрд╛рд╕рд╡рд░реНрдб рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдХрд╛рдЙрдВрдЯрд░ рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рдХреА рдУрд░, рд╣рд░ рдмрд╛рд░ рдкрд╛рд╕рд╡рд░реНрдб рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕рддреНрдпрд╛рдкрди рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдкрд╛рд╕рд╡рд░реНрдб рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛, рд╕рд░реНрд╡рд░ рдХрд╛рдЙрдВрдЯрд░ рдорд╛рди рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рд╡рд┐рдВрдбреЛ рдХреЗ рдЕрдВрджрд░ рдереЛрдбрд╝рд╛ рдЖрдЧреЗ рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рдЖрдк HOTP рд╕реНрдХреАрдо рдореЗрдВ рдкрд╛рд╕рд╡рд░реНрдб рдЬрдирд░реЗрдЯрд░ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЦреЗрд▓рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд╕рд┐рдВрдХ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


So. рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рд╢рд╛рдпрдж рджреЗрдЦрд╛ рд╣реИ, HMAC рднреА рджреЛ рддрд░реНрдХ рджреЗрддрд╛ рд╣реИред RFC4226 HOTP рдкреАрдврд╝реА рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ:


HOTP(K,C) = Truncate(HMAC-SHA-1(K,C)) 

рдЕрдкреЗрдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ, K рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХрд╛рдЙрдВрдЯрд░, рдмрджрд▓реЗ рдореЗрдВ, рдПрдХ рд╕рдВрджреЗрд╢ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред HMAC рдлрд╝рдВрдХреНрд╢рди рдореИрдХ рдЯреИрдЧ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд░рд╣рд╕реНрдпрдордп Truncate рдлрд╝рдВрдХреНрд╢рди рдЙрд╕ рд╡рди-рдЯрд╛рдЗрдо рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдорд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдк рдЕрдкрдиреЗ рдЬрдирд░реЗрдЯрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдпрд╛ рдЯреЛрдХрди рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВред


рдЖрдЗрдП рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ рдФрд░ рд╣рдо рдЬрд╛рддреЗ рд╣реА рдмрд╛рдХреА рдЪреАрдЬреЛрдВ рд╕реЗ рдирд┐рдкрдЯреЗрдВред


рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдпреЛрдЬрдирд╛


рд╡рди-рдЯрд╛рдЗрдо рдкрд╛рд╕рд╡рд░реНрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрди рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


  • K рдФрд░ C рдорд╛рдкрджрдВрдбреЛрдВ рд╕реЗ рдПрдХ HMAC-SHA1 рд╣реИрд╢ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВред рдпрд╣ рдПрдХ 20 рдмрд╛рдЗрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛрдЧрд╛ред
  • рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рдЗрд╕ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ 4 рдмрд╛рдЗрдЯреНрд╕ рдЦреАрдВрдЪреЗрдВред
  • рдЦреАрдВрдЪреЗ рдЧрдП рдорд╛рди рдХреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ 10 ^ n рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ, рдЬрд╣рд╛рдВ n = рдПрдХ рдмрд╛рд░ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдореЗрдВ рдЕрдВрдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ (рдЖрдорддреМрд░ рдкрд░ n = 6)ред рдФрд░ рдЕрдВрдд рдореЗрдВ, рдЗрд╕ рд╡рд┐рднрд╛рдЬрди рдХреЗ рд╢реЗрд╖ рднрд╛рдЧ рдХреЛ рд▓реЗрдВред рдпрд╣ рд╣рдорд╛рд░рд╛ рдкрд╛рд╕рд╡рд░реНрдб рд╣реЛрдЧрд╛ред

рдпрд╣ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рдзреНрд╡рдирд┐ рдирд╣реАрдВ рд╣реИ, рд╣реИ рдирд╛? рд╢реБрд░реБрдЖрдд рдХрд░рддреЗ рд╣реИрдВ рд╣реИрд╢ рдЬрдирд░реЗрд╢рди рд╕реЗред


HMAC-SHA1 рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ


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


рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдлрд╝рд╛рдпрд░рдлрд╝реЙрдХреНрд╕ рдореЗрдВ рдЖрдк рдПрдХ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдВрджрд░реНрдн рдореЗрдВ рд╡реЗрдм рдХреНрд░рд┐рдкреНрдЯреЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЖрдкрдХреЛ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдореЗрдВ рдкрд╣рд┐рдпрд╛ рдХреЛ рд╕реБрджреГрдврд╝ рдХрд░рдирд╛ рдпрд╛ рдЦреАрдВрдЪрдирд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдПрдХ рдбреЗрдореЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпреЛрдЬрдиреЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдПрдлрдПрдл рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВред


рдХреНрд░рд┐рдкреНрдЯреЛ рдПрдкреАрдЖрдИ рдХреЛ window.crypto.subtle рдореЗрдВ рд╣реА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдХреНрд░рд┐рдкреНрдЯреЛрдХрд░рдВрд╕реАред рдпрджрд┐ рдЖрдк рдирд╛рдо рд╕реЗ рд╣реИрд░рд╛рди рд╣реИрдВ, рддреЛ рдореИрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╕реЗ рдЙрджреНрдзреГрдд рдХрд░рддрд╛ рд╣реВрдВ:


рдПрдкреАрдЖрдИ рдХреЛ SubtleCrypto рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдЗрд╕ рддрдереНрдп рдХреЗ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐ рдХрдИ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рд╣реИрдВред рдХреЗрд╡рд▓ рдЬрдм рдпреЗ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдкреВрд░реА рд╣реЛрддреА рд╣реИрдВ, рддреЛ рд╡реЗ рдЕрдкрдиреЗ рд╕реНрдерд╛рдпрд┐рддреНрд╡ рдХреЛ рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реИрдВред

рдЖрдЗрдП рд╣рдо рдЙрди рддрд░реАрдХреЛрдВ рдкрд░ рдЬрд╛рдПрдВ рдЬрд┐рдирдХреА рд╣рдореЗрдВ рдЬрд╝рд░реВрд░рдд рд╣реИред рдиреЛрдЯ: рдпрд╣рд╛рдБ рдмрддрд╛рдИ рдЧрдИ рд╕рднреА рд╡рд┐рдзрд┐рдпрд╛рдБ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╣реИрдВ рдФрд░ Promise ред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ importKey рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЕрдкрдиреА рдирд┐рдЬреА рдХреБрдВрдЬреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЗрд╕реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред importKey 5 рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ:


 importKey( format, keyData, algorithm, extractable, usages ); 

рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ:


  • format 'raw' , рдЕрд░реНрдерд╛рдд рд╣рдо рдПрдХ ArrayBuffer рдмрд╛рдЗрдЯ рд╕рд░рдгреА рдХреЗ рд░реВрдк рдореЗрдВ рдХреБрдВрдЬреА рдкреНрд░рджрд╛рди рдХрд░реЗрдВрдЧреЗред
  • keyData рдПрдХ рд╣реА ArrayBuffer рд╣реИред рдмрд╣реБрдд рдЬрд▓реНрдж рд╣рдо рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдЙрддреНрдкрдиреНрди рдХрд┐рдпрд╛ рдЬрд╛рдПред
  • рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░ algorithm , HMAC-SHA1 ред рдпрд╣ рддрд░реНрдХ HmacImportParams рдХреЗ рдкреНрд░рд╛рд░реВрдк рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
  • рдЕрд╕рддреНрдп рдХреЗ рд▓рд┐рдП extractable , рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рд╣реИ
  • рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╕рднреА usages рд╣рдореЗрдВ рдХреЗрд╡рд▓ 'sign' ред

рд╣рдорд╛рд░реА рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдПрдХ рд▓рдВрдмреА рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛрдЧреАред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ, рдпрд╣ рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╣рдо рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдЗрд╕реЗ ArrayBuffer рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо TextEncoder рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЗрд╕рдХреЗ рд╕рд╛рде, рдХреБрдВрдЬреА рдХреЛрдб рдХреА рджреЛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рддреИрдпрд╛рд░ рдХреА рдЬрд╛рддреА рд╣реИ:


 const encoder = new TextEncoder('utf-8'); const secretBytes = encoder.encode(secret); 

рдЕрдм рдЗрд╕реЗ рд╕рдм рдПрдХ рд╕рд╛рде рд░рдЦреЗрдВ:


  const Crypto = window.crypto.subtle; const encoder = new TextEncoder('utf-8'); const secretBytes = encoder.encode(secret); const key = await Crypto.importKey( 'raw', secretBytes, { name: 'HMAC', hash: { name: 'SHA-1' } }, false, ['sign'] ); 

рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рддреИрдпрд╛рд░ рдХреА рдЧрдИ рдереАред рдЕрдм рд╣рдо рдХрд╛рдЙрдВрдЯрд░ рд╕реЗ рдирд┐рдкрдЯреЗрдВрдЧреЗ рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕рдВрджреЗрд╢ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░реЗрдВрдЧреЗред


рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╣рдорд╛рд░рд╛ рдХрд╛рдЙрдВрдЯрд░ 8 рдмрд╛рдЗрдЯ рд▓рдВрдмрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдВрдЧреЗ, рдЬреИрд╕реЗ рдХрд┐ ArrayBuffer рд╕рд╛рдеред рдЗрд╕ рд░реВрдк рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрд╕ рдЯреНрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдЖрдорддреМрд░ рдкрд░ рдЬреЗрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдКрдкрд░реА рдЕрдВрдХреЛрдВ рдореЗрдВ рд╢реВрдиреНрдп рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдЗрдЯ рдПрдХ ArrayBuffer рдореЗрдВ DataView рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ ArrayBuffer ред рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рд╕рднреА рдмрд╛рдЗрдирд░реА рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рд╕реЗ рдкреНрд░рд╛рд░реВрдк рдмрдбрд╝рд╛ рдПрдВрдбрд┐рдпрди рд╣реИ ред


 function padCounter(counter) { const buffer = new ArrayBuffer(8); const bView = new DataView(buffer); const byteString = '0'.repeat(64); // 8 bytes const bCounter = (byteString + counter.toString(2)).slice(-64); for (let byte = 0; byte < 64; byte += 8) { const byteValue = parseInt(bCounter.slice(byte, byte + 8), 2); bView.setUint8(byte / 8, byteValue); } return buffer; } 

рдкреИрдб рдХрд╛рдЙрдВрдЯрд░


рдЕрдВрдд рдореЗрдВ, рдХреБрдВрдЬреА рдФрд░ рдХрд╛рдЙрдВрдЯрд░ рддреИрдпрд╛рд░ рдХрд░рдХреЗ, рдЖрдк рд╣реИрд╢ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо SubtleCrypto рдХреЗ sign рдлрдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред


 const counterArray = padCounter(counter); const HS = await Crypto.sign('HMAC', key, counterArray); 

рдФрд░ рдЗрд╕ рдкрд░ рд╣рдордиреЗ рдкрд╣рд▓рд╛ рдХрджрдо рдкреВрд░рд╛ рдХрд░ рд▓рд┐рдпрд╛ рд╣реИред рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ, рд╣рдореЗрдВ рдПрдЪрдПрд╕ рдирд╛рдордХ рдереЛрдбрд╝рд╛ рд░рд╣рд╕реНрдпрдордп рдореВрд▓реНрдп рдорд┐рд▓рддрд╛ рд╣реИред рдФрд░ рдпрджреНрдпрдкрд┐ рдпрд╣ рдПрдХ рдЪрд░ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдирд╛рдо рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ (рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рд╕реЗ рдХреБрдЫ) рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рдЗрди рдирд╛рдореЛрдВ рдХреЛ рдЙрд╕рдХреЗ рд╕рд╛рде рдХреЛрдб рдХреА рддреБрд▓рдирд╛ рдХрд░рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗред рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реИ?


рдЪрд░рдг 2: 4-рдмрд╛рдЗрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдбрд╛рдпрдирд╛рдорд┐рдХ рдЯреНрд░рдВрдХреЗрд╢рди) рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ
рдЖрдЗрдП Sbits = DT (HS) // DT, рдиреАрдЪреЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд,
// рдПрдХ 31-рдмрд┐рдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реМрдЯрд╛рддрд╛ рд╣реИ

рдбреАрдЯреА рдбрд╛рдпрдиреЗрдорд┐рдХ рдЯреНрд░рдВрдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рд╣реИред рдФрд░ рдпрд╣рд╛рдБ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:


 function DT(HS) { // First we take the last byte of our generated HS and extract last 4 bits out of it. // This will be our _offset_, a number between 0 and 15. const offset = HS[19] & 0b1111; // Next we take 4 bytes out of the HS, starting at the offset const P = ((HS[offset] & 0x7f) << 24) | (HS[offset + 1] << 16) | (HS[offset + 2] << 8) | HS[offset + 3] // Finally, convert it into a binary string representation const pString = P.toString(2); return pString; } 

рдЯреНрд░рдВрдХреЗрд╢рди


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдордиреЗ рдмрд┐рдЯрд╡рд╛рдЗрдЬрд╝ рдФрд░ HS рдХреЗ рдкрд╣рд▓реЗ рдмрд╛рдЗрдЯ рдкрд░ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рдмрд╛рдЗрдирд░реА рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ 0b01111111 , рдЗрд╕рд▓рд┐рдП рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд╣рдо рдкрд╣рд▓реЗ рдмрд┐рдЯ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред рдЬреЗрдПрд╕ рдореЗрдВ, рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рдЗрд╕ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдЕрд░реНрде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдпрд╣ рд╕рдХрд╛рд░рд╛рддреНрдордХ / рдирдХрд╛рд░рд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдмреАрдЪ рднреНрд░рдо рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдмрд┐рдЯ рдХреЛ рдХрд╛рдЯрдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕ рдирдВрдмрд░ рдХреЛ рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдЧрд╛ред


рд▓рдЧрднрдЧ рдХрд┐рдпрд╛! рдпрд╣ рдХреЗрд╡рд▓ рдбреАрдЯреА рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп рдХреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмрджрд▓рдиреЗ рдФрд░ рддреАрд╕рд░реЗ рдЪрд░рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рд░рд╣рддрд╛ рд╣реИред


 function truncate(uKey) { const Sbits = DT(uKey); const Snum = parseInt(Sbits, 2); return Snum; } 

рддреАрд╕рд░рд╛ рдЪрд░рдг рднреА рдХрд╛рдлреА рдЫреЛрдЯрд╛ рд╣реИред рдмрд╕ рдЗрддрдирд╛ рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдкрд░рд┐рдгрд╛рдореА рд╕рдВрдЦреНрдпрд╛ рдХреЛ 10 ** ( ) рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рд╡рд┐рднрд╛рдЬрди рдХреЗ рд╢реЗрд╖ рднрд╛рдЧ рдХреЛ рд▓реЗрдирд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдордиреЗ рдЗрд╕ рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдЕрдВрддрд┐рдо рдПрди рдЕрдВрдХреЛрдВ рдХреЛ рдХрд╛рдЯ рджрд┐рдпрд╛ред рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╣рдорд╛рд░рд╛ рдХреЛрдб рдХрдо рд╕реЗ рдХрдо рдЫрд╣ рдЕрдВрдХреЛрдВ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдФрд░ рд╕рдВрднрд╛рд╡рд┐рдд 7 рдФрд░ 8 рдЕрдВрдХреЛрдВ рд╡рд╛рд▓реЗ рд▓реЛрдЧреЛрдВ рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, рдЪреВрдВрдХрд┐ рдпрд╣ 31-рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо 9 рд╡рд░реНрдгреЛрдВ рдХреЛ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рдереЗ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореИрдВрдиреЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдХрднреА рднреА 6 рд╕реЗ рдЕрдзрд┐рдХ рд╡рд░реНрдг рдирд╣реАрдВ рджреЗрдЦреЗ рд╣реИрдВред рдЖрдкрдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?


рдЕрдВрддрд┐рдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдХреЛрдб, рдЬреЛ рд╕рднреА рдкрд┐рдЫрд▓реЗ рд╡рд╛рд▓реЗ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:


 async function generateHOTP(secret, counter) { const key = await generateKey(secret, counter); const uKey = new Uint8Array(key); const Snum = truncate(uKey); // Make sure we keep leading zeroes const padded = ('000000' + (Snum % (10 ** 6))).slice(-6); return padded; } 

рд╣реБрд░реНрд░реЗ! рд▓реЗрдХрд┐рди рдЕрдм рдХреИрд╕реЗ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдХреЛрдб рд╕рд╣реА рд╣реИ?


рдкрд░реАрдХреНрд╖рдг


рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо RFC рд╕реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдкрд░рд┐рд╢рд┐рд╖реНрдЯ рдбреА рдореЗрдВ рдЧреБрдкреНрдд рдХреБрдВрдЬреА "12345678901234567890" рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдорд╛рди рдФрд░ 0 рд╕реЗ 9 рддрдХ рдХрд╛рдЙрдВрдЯрд░ рдорд╛рди рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЯреНрд░рдВрдХрдХреЗрдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЧрд┐рдирд╛рдП рдЧрдП HMAC рд╣реИрд╢ рдФрд░ рдордзреНрдпрд╡рд░реНрддреА рдкрд░рд┐рдгрд╛рдо рднреА рд╣реИрдВред рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХреЗ рд╕рднреА рдЪрд░рдгреЛрдВ рдХреЛ рдбреАрдмрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реИред рдпрд╣рд╛рдБ рдЗрд╕ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ (рдХреЗрд╡рд▓ рдХрд╛рдЙрдВрдЯрд░ рдФрд░ HOTP рдмрд╛рдХреА рд╣реИрдВ):


  Count HOTP 0 755224 1 287082 2 359152 3 969429 ... 

рдпрджрд┐ рдЖрдкрдиреЗ рдбреЗрдореЛ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИ, рддреЛ рдЕрдм рд╕рдордп рд╣реИред рдЖрдк рдЗрд╕рдореЗрдВ RFC рд╕реЗ рдорд╛рди рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдУ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо TOTP рд╢реБрд░реВ рдХрд░ рд░рд╣реЗ рд╣реИрдВред


TOTP


рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрдВрдд рдореЗрдВ 2FA рдХреЗ рдЕрдзрд┐рдХ рдЖрдзреБрдирд┐рдХ рд╣рд┐рд╕реНрд╕реЗ рдореЗрдВ рдкрд╣реБрдВрдЪ рдЧрдПред рдЬрдм рдЖрдк рдЕрдкрдирд╛ рд╡рди-рдЯрд╛рдЗрдо рдкрд╛рд╕рд╡рд░реНрдб рдЬрдирд░реЗрдЯрд░ рдЦреЛрд▓рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЫреЛрдЯреЗ рдЯрд╛рдЗрдорд░ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рддрдирд╛ рдЕрдзрд┐рдХ рдХреЛрдб рдорд╛рдиреНрдп рд╣реЛрдЧрд╛, рддреЛ рдпрд╣ рдЯреАрдЯреАрдкреА рд╣реИред рдЕрдВрддрд░ рдХреНрдпрд╛ рд╣реИ?


рд╕рдордп-рдЖрдзрд╛рд░рд┐рдд рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдПрдХ рд╕реНрдерд┐рд░ рдореВрд▓реНрдп рдХреЗ рдмрдЬрд╛рдп, рд╡рд░реНрддрдорд╛рди рд╕рдордп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╛, рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ, "рдЕрдВрддрд░рд╛рд▓" (рд╕рдордп рдХрджрдо)ред рдпрд╛ рд╡рд░реНрддрдорд╛рди рдЕрдВрддрд░рд╛рд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рднреАред рдЗрд╕рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдпреВрдирд┐рдХреНрд╕ рд╕рдордп (1 рдЬрдирд╡рд░реА, 1970 рдпреВрдЯреАрд╕реА рдкрд░ рдЖрдзреА рд░рд╛рдд рдХреЗ рдмрд╛рдж рд╕реЗ рдорд┐рд▓реАрд╕реЗрдХрдВрдб рдХреА рд╕рдВрдЦреНрдпрд╛) рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рд╡рд┐рдВрдбреЛ рджреНрд╡рд╛рд░рд╛ рдкрд╛рд╕рд╡рд░реНрдб рдХреА рд╡реИрдзрддрд╛ (рдЖрдорддреМрд░ рдкрд░ 30 рд╕реЗрдХрдВрдб) рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╕рд░реНрд╡рд░ рдЖрдорддреМрд░ рдкрд░ рдЕрдкреВрд░реНрдг рдШрдбрд╝реА рддреБрд▓реНрдпрдХрд╛рд▓рди рдХреЗ рдХрд╛рд░рдг рдорд╛рдореВрд▓реА рд╡рд┐рдЪрд▓рди рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░ 1 рдЕрдВрддрд░рд╛рд▓ рдЖрдЧреЗ рдФрд░ рдкреАрдЫреЗ рд╡рд┐рдиреНрдпрд╛рд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред


рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпрд╣ HOTP рдпреЛрдЬрдирд╛ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред рд╕рдордпрдмрджреНрдз рдпреЛрдЬрдирд╛ рдореЗрдВ, рд╡реИрдз рдХреЛрдб рд╣рд░ 30 рд╕реЗрдХрдВрдб рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред рдореВрд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдореЗрдВ, рдПрдХ рд╡реИрдз рдкрд╛рд╕рд╡рд░реНрдб рд╕рд░реНрд╡рд░ + рд╕рд╣рд┐рд╖реНрдгреБрддрд╛ рд╡рд┐рдВрдбреЛ рдкрд░ рд╡рд░реНрддрдорд╛рди рдХрд╛рдЙрдВрдЯрд░ рдореВрд▓реНрдп рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдкреНрд░рдорд╛рдгрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкрд╛рд╕рд╡рд░реНрдб рдЕрдирд┐рд╢реНрдЪрд┐рдд рдХрд╛рд▓ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдмрджрд▓рд╛ рдЬрд╛рдПрдЧрд╛ред рдЖрдк TOFC рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ RFC6238 рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред


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


 let stepWindow = 30 * 1000; // 30 seconds in ms let lastTimeStep = 0; const updateTOTPCounter = () => { const timeSinceStep = Date.now() - lastTimeStep * stepWindow; const timeLeft = Math.ceil(stepWindow - timeSinceStep); if (timeLeft > 0) { return requestAnimationFrame(updateTOTPCounter); } timeStep = getTOTPCounter(); lastTimeStep = timeStep; <...update counter and regenerate...> requestAnimationFrame(updateTOTPCounter); } 

рдлрд┐рдирд┐рд╢рд┐рдВрдЧ рдЯрдЪ - рдХреНрдпреВрдЖрд░ рдХреЛрдб рд╕рдкреЛрд░реНрдЯ


рдЖрдорддреМрд░ рдкрд░, рдЬрдм рд╣рдо 2FA рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рдХреНрдпреВрдЖрд░ рдХреЛрдб рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрдХреИрди рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ: рдЪрдпрдирд┐рдд рдпреЛрдЬрдирд╛, рдЧреБрдкреНрдд рдХреБрдВрдЬреА, рдЦрд╛рддрд╛ рдирд╛рдо, рдкреНрд░рджрд╛рддрд╛ рдХрд╛ рдирд╛рдо, рдкрд╛рд╕рд╡рд░реНрдб рдореЗрдВ рдЕрдВрдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ред


рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдХрд┐ рдЖрдк getDisplayMedia API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ QR рдХреЛрдб рдХреЛ рд╕реАрдзреЗ рд╕реНрдХреНрд░реАрди рд╕реЗ рдХреИрд╕реЗ рд╕реНрдХреИрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯрд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдмрдирд╛рдпрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдЕрднреА рдХрд░реЗрдВрдЧреЗред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд╕реНрдЯреНрд░реАрдо-рдбрд┐рд╕реНрдкреНрд▓реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рд╣рдо рдЕрджреНрднреБрдд jsQR рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред


QR- рдПрдиреНрдХреЛрдбреЗрдб рд▓рд┐рдВрдХ рдореЗрдВ рдирд┐рдореНрди рдкреНрд░рд╛рд░реВрдк рд╣реИ:


 otpauth://TYPE/LABEL?PARAMETERS 

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 otpauth://totp/label?secret=oyu55d4q5kllrwhy4euqh3ouw7hebnhm5qsflfcqggczoafxu75lsagt&algorithm=SHA1&digits=6&period=30 

рдореИрдВ рдЙрд╕ рдХреЛрдб рдХреЛ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ рдЬреЛ рд╕реНрдХреНрд░реАрди рдХреИрдкреНрдЪрд░ рдФрд░ рдорд╛рдиреНрдпрддрд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдм рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдпрд╣рд╛рдВ рдЗрд╕ рд▓рд┐рдВрдХ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:


 const setupFromQR = data => { const url = new URL(data); // drop the "//" and get TYPE and LABEL const [scheme, label] = url.pathname.slice(2).split('/'); const params = new URLSearchParams(url.search); const secret = params.get('secret'); let counter; if (scheme === 'hotp') { counter = params.get('counter'); } else { stepWindow = parseInt(params.get('period'), 10) * 1000; counter = getTOTPCounter(); } } 

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ, рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдПрдХ рдЖрдзрд╛рд░ рд╣реЛрдЧреА- 32 (!) рдПрдиреНрдХреЛрдбреЗрдб рд╕реНрдЯреНрд░рд┐рдВрдЧ, рдЬреИрд╕рд╛ рдХрд┐ рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдЕрдкреНрд░рд╛рдкреНрдп рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдкреНрд░рджрд░реНрд╢рди рдХреА рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рдмрд┐рдВрджреБ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рдорд┐рд▓реА рдХрд┐ рдЖрдзрд╛рд░ -32 рдпрд╛ рд╕рд┐рд░реНрдл рдРрд╕рд╛ рдкреНрд░рд╛рд░реВрдк рдХреНрдпреЛрдВ рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдЗрд╕ URL рдкреНрд░рд╛рд░реВрдк рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ, рдФрд░ рдпрд╣ рдкреНрд░рд╛рд░реВрдк рд╕реНрд╡рдпрдВ Google рджреНрд╡рд╛рд░рд╛ рдЧрдврд╝рд╛ рдЧрдпрд╛ рдерд╛ред рдЖрдк рдпрд╣рд╛рдБ рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ ред


рдкрд░реАрдХреНрд╖рдг QR рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ FreeOTP рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ ред


рдирд┐рд╖реНрдХрд░реНрд╖


рдФрд░ рд╡рд╣ рд╕рдм рд╣реИ! рдПрдХ рдмрд╛рд░ рдлрд┐рд░, рдбреЗрдореЛ рджреЗрдЦрдирд╛ рди рднреВрд▓реЗрдВред рдХреЛрдб рдХреЗ рд╕рд╛рде рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХрд╛ рдПрдХ рд▓рд┐рдВрдХ рднреА рд╣реИ рдЬреЛ рдЗрд╕рдХреЗ рдкреАрдЫреЗ рд╣реИред


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


рдЬрд▓реНрдж рдорд┐рд▓рддреЗ рд╣реИрдВ!

Source: https://habr.com/ru/post/hi462945/


All Articles