| |||
![]()
|
![]() ![]() |
![]()
Для скучных программистов: немного о шифровании на фронтендах Некоторые вещи мне удобно записывать для себя в дневник как в блокнот. Но вдруг кому-то тоже будет интересно? Современные криптографические методы (из легкодоступных в браузерных приложениях) — это эллиптические кривые семейства 25519 и хороший AES с длинными ключами. Обычно по надежности (а иногда и скорости) они уделывают все эти старинные RSA, который используется до сих пор, например, в PGP. А если завтра квантовый компьютер, а мы невыспавшиеся и не одеты? AES позволяет надежно шифровать данные и расшифровывать обратно симметрично (одним тем же паролем, плюс еще придется к шифрованным данным запомнить пару коротких констант). AES давно уже встроен аппаратно в любой браузер, и доступен для JS-разработчика как метод crypto. Ниже я накидал две простые функции, как его использовать: [ ТЕКСТ ПОД КАТОМ: Доступен только в оригинальной заметке на сайте ] Но с AES всё понятно давно. А что касается математики эллиптических кривых 25519, она пришла на смену старым методам сравнительно недавно и очень хорошо себя показала. Во-первых, она крайне надежна среди всего зоопарка. Во-вторых, очень быстра. В-третьих, компактна и красива. Например, старые ключи RSA занимали текстовые файл на несколько строк, а публичный ключ 25519 всего одну строчку, и этого скромного размера более чем достаточно. Вот например мой: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF8ZJDFjcdno13Re Для JS-разработки существует библиотека noble: https://github.com/paulmillr/noble-ed255 Что умеет библиотека 25519? Вот например: 1. Сгенерировать новый приватный ключ. А к нему — публичный. Приватный вы храните в тайне, публичный показываете всем. 2. Цифровая подпись. Своим приватным ключом вы можете подписать любые данные. Получатель, зная лишь ваш публичный ключ, всегда сможет проверить, что данные подписали именно вы. 3. Асимметричное шифрование данных для конкретного получателя, зная его публичный ключ (чтобы расшифровать эти данные смог лишь человек, обладающий приватной частью этого ключа). Тут интересный принцип. Старый алгоритм RSA позволял просто взять и зашифровать данные чужим публичным ключом. Алгоритмы 25519 работают чуть сложнее — они используют принцип «общего секрета». Это некий «общий» пароль для А и Б, который нигде не хранится, потому что в любой момент его можно вычислить, причем двумя способами: либо зная публичный ключ А и приватный Б, либо, наоборот, приватный А и публичный Б. Хитрая математика все равно вычислит «общий пароль» одинаково. Поэтому как работает шифрование данных для абонента для его публичного ключа? Первым делом генерируется временный ключ. Он позже будет забыт. С его помощью (используя приватную часть ключа и публичный ключ получателя) вычисляется общий пароль. Остаётся этим паролем тупо и симметрично зашифровать данные (при помощи того же мощного AES), а в комплект к шифровке добавить публичную часть временного ключа. Данные отправляются, все временные ключи и пароль отправитель уничтожает. Теперь никто, кроме получателя, не сможет это расшифровать обратно. А он сможет — добавит к публичному ключу свой приватный и легко вычислит, каким был общий пароль, которым шифрованы данные. И столь же симметрично их расшифрует. 4. Возникает интересная проблема: ну хорошо, а как зашифровать таким способом данные для нескольких получателей, не дублируя сами данные? PGP на старом RSA в этом смысле работал проще: если можно шифровать что-то, зная лишь публичник адресата, то данные шифруются единым паролем, а сам пароль шифруется много раз для каждого из адресатов и прикладываются к данным по числу получателей. Данные не дублируются, а шифрованных паролей можно напихать для каждого, они же относительно короткие (спойлер: в RSA не очень). С x25519 это явно не сработает, поэтому схема усложняется. Мы генерируем единый пароль для шифровки данных (пароль любого типа, не обязательно ключ 25519). А далее — как в предыдущем пункте, с той лишь разницей, что шифруем не данные, а сам пароль. То есть — генерируем временные ключи: столько временных ключей 25519, сколько у нас получателей, и для каждого шифруем пароль. К общей посылке у нас добавляется по числу получателей: 32 байта публичного временного ключа + 48 байт шифрованный пароль + 32 байта сам публичник получателя, чтоб он разобрался, какой из паролей шифрован для него, и ему не пришлось раскрывать данные подряд всеми чужими паролями, пока не увидит, что информация теперь расшифровалась чуть более осмысленно. Итого — чуть больше 100 байт на получателя. Кажется, снова лучше, чем у PGP. 5. Да, еще есть неочевидный нюанс, что генерится пара ключей обычно в формате Edwards (ed25519), а использовать для поиска общего секрета можно только ключи формата Montgomery (x25519), но это уже сущие мелочи, это делается легкой конвертацией ключа в одну строчку.
[ ТЕКСТ ПОД КАТОМ: Доступен только в оригинальной заметке на сайте ] Файлик: cryptotest.js |
|||||||||||||||
![]() |
![]() |