Шифрование SingleSPA customProps
Как мы можем зашифровать токен аутентификации, переданный приложению из одного SPA
singleSpa.registerApplication({name: 'app1',activeWhen,app,customProps: { authToken:"d83jD63UdZ6RS6f70D0" }});
2 ответа
Шифрование на веб-странице очень просто, например, вы можете использовать алгоритм симметричного шифрования, такой как AES (AES-JS). Но на самом деле вопрос в том, какова ваша цель?
- Вы хотите предотвратить атаки MITM? используйте TLS.
- Вы хотите запретить клиенту доступ к токену? Невозможно, потому что он может видеть запрос напрямую.
- Хотите защититься от XSS-атак? Вам нужно где-то хранить ключ шифрования! Если он находится в памяти, то в течение нескольких минут вы можете быть в безопасности, если сохраните ключ в памяти, но что происходит, когда вкладка закрывается?
Будет гораздо больше проблем с безопасностью вашего использования (судя по фрагменту кода), но вам понадобится больше деталей в вашем вопросе.
Предполагая, что OP действительно хочет сгенерировать токен аутентификации на клиенте и отправить его на сервер, вот рекомендация:
- Используйте HTTPS. Нам понадобится шифрование трафика между клиентом и сервером.
- Мы собираемся использовать протокол обмена ключами Диффи-Хеллмана для безопасного обмена ключами без постороннего подслушивания. Для этого нам понадобится несколько примитивов:
- GetServicePublicKey - этот вызов API службы может выполняться через HTTP и не обязательно должен быть конечной точкой HTTPS.
- GenerateKeyPair (библиотечная функция, общая для сервера и клиента) - генерирует пару открытый ключ + закрытый ключ для алгоритма Диффи-Хеллмана с эллиптической кривой. Выберите надежную эллиптическую кривую. См. https://safecurves.cr.yp.to/.
- Клиент генерирует новую пару ключей. Это временная пара ключей, действующая только для одного запроса.
- Клиент создает веб-запрос (используйте axios, fetch или ajax/xhr) и добавляет специальный заголовок протокола приложения (например, x-key-exchange-client-publickey) и устанавливает его на открытый ключ пары эфемерных ключей, созданной в шаг 3.
- Клиент вызывает вызов API GetServicePublicKey, используя веб-запрос, созданный на шаге 4. Других полезных данных в теле запроса нет.
- Сервис обрабатывает запрос GetServicePublicKey от клиента. Он считывает эфемерный открытый ключ клиента (действителен только для этого запроса + ответа) и вычисляет общий секрет, используя алгоритм Диффи-Хеллмана эллиптической кривой (ECDH), используя открытый ключ клиента.
- Служба отправляет ответ, устанавливающий заголовок конкретного протокола приложения (например, x-key-exchange-service-publickey) на открытый ключ эфемерной службы.
- Если служба использует сеансы, она также может установить этот эфемерный открытый ключ службы в переменной сеанса.
- Сервис отправляет ответ клиенту.
- Клиент читает заголовок ответа, содержащий открытый ключ службы.
- Он также вычисляет общий секрет, используя ECDH с открытым ключом службы.
- Теперь и у клиента, и у сервиса есть общий секретный ключ, о котором никто не знает.
- Клиент генерирует токен авторизации в своей локальной памяти. Он шифрует этот токен с помощью общего секретного ключа и немедленно очищает токен аутентификации из локальной памяти.
- Клиент отправляет зашифрованный токен аутентификации в службу с помощью вызова API, снова устанавливая заголовок x-key-exchange-client-publickey для протокола приложения.
- Сервис получает токен авторизации. Он ищет сеанс клиента, используя открытый ключ клиента, присутствующий в заголовке x-key-exchange-client-publickey. Затем он расшифровывает токен аутентификации, используя общий секрет
- Сервис отправляет ответ клиенту, тем самым завершая транзакцию.
Обоснование
- HTTPS используется для защиты сообщений приложений на уровне проводов. Даже если по какой-либо причине это шифрование HTTPS нарушено, шифрование на уровне приложения, описанное выше, действует как второй уровень защиты. Центры сертификации, такие как LetsEncrypt, предоставляют бесплатные сертификаты SSL.
- Описанный выше протокол уровня приложения является основой для сквозного шифрования между клиентом и сервером.
- Существует гибкость в отношении срока действия ключей сеанса. Это решение по производительности. Для высоких требований безопасности эфемерные ключи можно выбросить после однократного использования. Это защитит от атак Man-in-the-middle (MITM), потому что посредник должен постоянно взламывать ключи шифрования, которые постоянно меняются для каждой транзакции. Если вам не нужен этот уровень параноидальной безопасности, вы можете сохранить ключи сеанса на весь сеанс клиента. Если вы это сделаете, вы можете добавить несколько примитивов API для управления клиентским сеансом (например: BeginSession, EndSession и т. Д.)
Особенности реализации
- Выберите алгоритм шифрования секретного ключа (симметричное шифрование). AES-256 - достойный выбор. Используйте как минимум 96-битный вектор инициализации. Вектор инициализации должен быть случайным, но не обязательно секретным. Что очень важно, IV никогда не используется повторно. Вы можете добавить IV к зашифрованному выводу. Установка длины IV до 96 битов помогает упростить дешифрование на принимающей стороне, поскольку данные, следующие за начальными 96 битами, представляют собой фактическую зашифрованную полезную нагрузку.
+---------------------------+---------------------------------- . . . -----+
| 96 bits Init. Vector | Encrypted payload (same length as input) |
+---------------------------+---------------------------------- . . . -----+
- На стороне клиента вы можете использовать SubtleCrypto API, доступный во всех браузерах. На стороне сервера, если вы используете node JS, используйте встроенную криптографическую библиотеку node JS. Если вы используете.NET, вы можете использовать классы криптографии.
- Если вы когда-нибудь собираетесь хранить секретные ключи на диске, храните их в зашифрованном виде. Кандидаты - это зашифрованные контейнеры, предлагаемые операционной системой. Например: Windows позволяет хранить ключевые данные в зашифрованных контейнерах, доступных только зарегистрированному пользователю. Другой вариант - использовать ключи оболочки (т. Е. Другой ключ для шифрования секретного ключа). Вы также должны обезопасить упаковочный ключ.
Критика и противодействие
- У нас есть HTTPS. Зачем беспокоиться?
См. CVE-2014-0160 - также известную как Heartbleed Bug в TLS.
Нам потребуется защита второго уровня на уровне приложений посредством сквозного шифрования с применением принципа глубокой защиты.
- Разве это не будет медленным?
Да, но приложения должны быть правильными и безопасными, а не быстрыми и небезопасными. Существуют шаблоны проектирования / реализации приложений, которые могут гарантировать, что приложения будут использовать доступные ресурсы - несколько ядер, память, мультиплексирование ввода-вывода - для управления производительностью современного оборудования и программного обеспечения.