Что такое симметричное шифрование и как работают ключи
Что проверяют
Понимаете ли вы, что в симметричной схеме вся стойкость держится на секретности одного ключа, и умеете ли зашифровать данные в Go так, чтобы их нельзя было незаметно подменить. Следом почти всегда спрашивают, как передать ключ второй стороне и чем симметричное шифрование отличается от асимметричного.
Как отвечать
Один и тот же ключ и шифрует, и расшифровывает. Это быстро, поэтому так шифруют почти весь объём данных: трафик внутри TLS, файлы, поля в базе. Каркас ответа:
- алгоритмы: стандарт это AES с ключом 128 или 256 бит (для
aes.NewCipherключ длиной 16, 24 или 32 байта) и ChaCha20-Poly1305 изgolang.org/x/crypto/chacha20poly1305. DES и 3DES устарели; - режим: блочный шифр напрямую не используют, нужен режим. Правильный выбор это AEAD:
cipher.NewGCMдаёт и шифрование, и проверку целостности. ECB раскрывает структуру данных, CBC без отдельного MAC уязвим к подмене; - nonce: для GCM это 12 байт, уникальные для каждого сообщения под одним ключом. Обычно его берут из
crypto/randи кладут перед шифртекстом; - ключ: только из
crypto/rand. Если исходно есть пароль, ключ выводят функцией вродеargon2.IDKeyилиscrypt, а не берут байты пароля как есть; - обмен ключами: симметричный ключ не пересылают открытым. Его согласуют асимметрично (
crypto/ecdh, как это делает TLS) или хранят в KMS либо Vault, шифруя ключи данных мастер-ключом (envelope encryption).
Хорошо закончить ротацией: ключу дают идентификатор и сохраняют его рядом с шифртекстом. Тогда старые данные расшифровываются прежним ключом, а новые пишутся свежим.
Где спотыкаются
Повторяют nonce в GCM, например берут константу или счётчик, который обнуляется после рестарта. Два сообщения с одним nonce и ключом раскрывают XOR открытых текстов и позволяют подделывать метки.
Генерируют ключ через math/rand. Такой генератор предсказуем, для криптографии годится только crypto/rand.
Путают шифрование с хешированием и предлагают «шифровать пароли AES». Пароли хешируют через bcrypt или argon2, расшифровывать их не нужно никогда.