Разница между шифрованием, кодированием и хешированием

В области информационной безопасности и разработки программного обеспечения термины «шифрование», «кодирование» и «хеширование» часто используются рядом, однако они решают принципиально разные задачи. Непонимание различий между ними приводит к критическим ошибкам: хранению паролей в открытом виде, неправильной защите API, небезопасной передаче данных и уязвимостям аутентификации.

Сравнительная таблица

Технология Основная цель Возможность восстановления данных Используется ключ Пример
Кодирование Представление данных в другом формате Да Нет Base64
Шифрование Защита данных от чтения Да Да AES
Хеширование Получение уникального отпечатка данных Нет Нет SHA-256

Кодирование

Назначение кодирования

Кодирование применяется для преобразования данных в формат, удобный для хранения, передачи или обработки различными системами.

Главная особенность:

Кодирование не предназначено для защиты информации.

После кодирования данные можно восстановить без секретного ключа.


Пример Base64

Base64 — один из самых распространённых способов кодирования.

Кодирование строки

const text = "password123";

const encoded = Buffer.from(text).toString("base64");

console.log(encoded);

Результат:

cGFzc3dvcmQxMjM=

Декодирование

const decoded = Buffer.from(encoded, "base64").toString();

console.log(decoded);

Результат:

password123

Где используется кодирование

Передача бинарных данных

Например:

  • изображения в JSON;
  • файлы в HTTP;
  • email-вложения;
  • JWT-токены.

URL-кодирование

const value = encodeURIComponent("hello world");

console.log(value);

Результат:

hello%20world

Ошибочное использование Base64

Одна из самых опасных ошибок начинающих разработчиков — считать Base64 защитой.

Неправильно:

const password = Buffer
    .from("myPassword")
    .toString("base64");

Такой «защищённый» пароль мгновенно восстанавливается.


Шифрование

Назначение шифрования

Шифрование используется для сокрытия информации от посторонних лиц.

Данные можно восстановить только при наличии:

  • ключа;
  • алгоритма;
  • иногда — вектора инициализации.

Симметричное шифрование

Принцип работы

Один и тот же ключ используется:

  • для шифрования;
  • для расшифровки.

AES в Node.js

Шифрование

const crypto = require("crypto");

const algorithm = "aes-256-cbc";
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);

const text = "secret data";

const cipher = crypto.createCipheriv(
    algorithm,
    key,
    iv
);

let encrypted = cipher.update(
    text,
    "utf8",
    "hex"
);

encrypted += cipher.final("hex");

console.log(encrypted);

Расшифровка

const decipher = crypto.createDecipheriv(
    algorithm,
    key,
    iv
);

let decrypted = decipher.update(
    encrypted,
    "hex",
    "utf8"
);

decrypted += decipher.final("utf8");

console.log(decrypted);

Где применяется шифрование

HTTPS

TLS использует шифрование для защиты:

  • логинов;
  • паролей;
  • cookie;
  • банковских данных.

VPN

Создание защищённых туннелей связи.

Мессенджеры

Например:

  • Signal;
  • WhatsApp;
  • Telegram Secret Chats.

Шифрование файлов

Используется:

  • в облачных хранилищах;
  • архиваторах;
  • системах резервного копирования.

Асимметричное шифрование

Принцип работы

Используются два ключа:

Ключ Назначение
Публичный Шифрование
Приватный Расшифровка

RSA в Node.js

Генерация ключей

const crypto = require("crypto");

const {
    publicKey,
    privateKey
} = crypto.generateKeyPairSync("rsa", {
    modulusLength: 2048
});

Шифрование

const encrypted = crypto.publicEncrypt(
    publicKey,
    Buffer.from("secret")
);

console.log(encrypted.toString("base64"));

Расшифровка

const decrypted = crypto.privateDecrypt(
    privateKey,
    encrypted
);

console.log(decrypted.toString());

Хеширование

Назначение хеширования

Хеширование создаёт фиксированный отпечаток данных.

Главная особенность:

Исходные данные невозможно восстановить обратно.


Свойства криптографических хешей

Детерминированность

Одинаковые данные всегда дают одинаковый результат.

hash("123") === hash("123")

Односторонность

Из хеша невозможно получить исходное значение.


Лавинный эффект

Даже минимальное изменение данных полностью меняет результат.


Устойчивость к коллизиям

Сложно найти:

A != B

но:

hash(A) === hash(B)

SHA-256

Создание хеша

const crypto = require("crypto");

const hash = crypto
    .createHash("sha256")
    .update("password123")
    .digest("hex");

console.log(hash);

Результат

ef92b778bafe771e...

Почему SHA-256 недостаточен для паролей

Простое хеширование небезопасно для хранения паролей.

Причины:

  • высокая скорость вычисления;
  • уязвимость к brute force;
  • атаки словарями;
  • rainbow tables.

Password Hashing

Специализированные алгоритмы

Для хранения паролей применяются специальные алгоритмы:

Алгоритм Статус
bcrypt Популярный
scrypt Более устойчивый
Argon2 Современный стандарт

bcrypt

Установка

npm install bcrypt

Хеширование пароля

const bcrypt = require("bcrypt");

const password = "mySecretPassword";

const hash = await bcrypt.hash(password, 10);

console.log(hash);

Проверка пароля

const isValid = await bcrypt.compare(
    "mySecretPassword",
    hash
);

console.log(isValid);

Почему bcrypt безопаснее SHA-256

bcrypt:

  • медленный;
  • использует salt;
  • защищает от rainbow tables;
  • усложняет brute force.

Salt

Что такое salt

Salt — случайная строка, добавляемая к паролю перед хешированием.

Пример:

password + randomSalt

Зачем нужен salt

Без salt два одинаковых пароля создают одинаковые хеши.

С salt:

password123 -> hash1
password123 -> hash2

bcrypt автоматически использует salt

const hash = await bcrypt.hash(password, 10);

Salt уже встроен внутрь результата.


Argon2

Современный алгоритм хеширования

Argon2 победил в конкурсе Password Hashing Competition.

Сильные стороны:

  • защита от GPU-атак;
  • защита от ASIC;
  • высокая устойчивость к brute force;
  • контроль потребления памяти.

Установка

npm install argon2

Хеширование

const argon2 = require("argon2");

const hash = await argon2.hash(
    "superPassword"
);

console.log(hash);

Проверка

const valid = await argon2.verify(
    hash,
    "superPassword"
);

console.log(valid);

Отличие хеширования от шифрования

Ключевая разница

Шифрование

Данные должны быть восстановлены.

Примеры:

  • сообщения;
  • документы;
  • банковские операции.

Хеширование

Данные восстанавливать не нужно.

Примеры:

  • пароли;
  • контроль целостности;
  • цифровые подписи.

Типичная ошибка хранения паролей

Неправильно

const encryptedPassword =
    encrypt(password);

Проблема:

если злоумышленник получит ключ шифрования — все пароли будут раскрыты.


Правильно

const passwordHash =
    await bcrypt.hash(password, 12);

Проверка выполняется сравнением хешей.


Проверка целостности файлов

Использование SHA-256

const fs = require("fs");
const crypto = require("crypto");

const file = fs.readFileSync("file.zip");

const hash = crypto
    .createHash("sha256")
    .update(file)
    .digest("hex");

console.log(hash);

Для чего это используется

  • проверка загрузок;
  • контроль резервных копий;
  • обнаружение повреждений;
  • защита от подмены файлов.

HMAC

Хеширование с секретным ключом

HMAC объединяет:

  • хеширование;
  • секретный ключ.

Пример

const crypto = require("crypto");

const hmac = crypto
    .createHmac(
        "sha256",
        "secret-key"
    )
    .update("message")
    .digest("hex");

console.log(hmac);

Где применяется HMAC

  • JWT;
  • API-подписи;
  • webhook-проверки;
  • защита запросов.

Rainbow Tables

Что это такое

Rainbow table — заранее вычисленная база:

пароль -> хеш

Проблема простых хешей

Если два пользователя имеют пароль:

123456

то SHA-256 создаст одинаковый хеш.


Как salt решает проблему

Даже одинаковые пароли получают разные хеши.


Brute Force

Перебор паролей

Атакующий массово проверяет варианты:

123456
password
qwerty
admin

Почему медленные алгоритмы лучше

bcrypt и Argon2 специально делают вычисления дорогими.

Это:

  • снижает скорость атак;
  • увеличивает стоимость взлома;
  • усложняет GPU-перебор.

Pepper

Дополнительная защита

Pepper — секретное значение, известное только серверу.


Пример

const pepper = process.env.PEPPER;

const hash = await bcrypt.hash(
    password + pepper,
    12
);

Отличие salt от pepper

Salt Pepper
Хранится рядом с хешем Хранится отдельно
Уникален для пользователя Общий для системы
Не секретен Секретен

Типичные ошибки разработчиков

Использование Base64 вместо защиты

Ошибка:

Buffer.from(password)
    .toString("base64");

Использование MD5

MD5 считается криптографически сломанным.

Нельзя использовать:

  • для паролей;
  • цифровой подписи;
  • защиты данных.

Использование SHA-1

SHA-1 также считается устаревшим.


Отсутствие salt

Одинаковые пароли получают одинаковые хеши.


Слишком маленький cost factor

Например:

bcrypt.hash(password, 2)

Такой хеш слишком быстрый.


Рекомендуемые алгоритмы

Задача Рекомендуемое решение
Хранение паролей Argon2
Совместимость со старыми системами bcrypt
Контроль целостности SHA-256
Подпись запросов HMAC-SHA256
Шифрование данных AES-256

Практическая схема авторизации

Регистрация

Сервер получает пароль

myPassword123

Создаётся хеш

const hash =
    await argon2.hash(password);

В базу сохраняется только хеш

$argon2id$v=19$m=65536...

Вход пользователя

Пользователь вводит пароль

myPassword123

Сервер сравнивает хеши

await argon2.verify(
    storedHash,
    enteredPassword
);

Исходный пароль не хранится

Даже администратор базы данных не должен видеть реальные пароли пользователей.


Когда использовать каждую технологию

Сценарий Технология
Передача бинарных данных Кодирование
Сокрытие содержимого Шифрование
Хранение паролей Хеширование
Проверка целостности Хеширование
Безопасная связь Шифрование
JWT payload Кодирование
HTTPS Шифрование
API signatures HMAC

Главная концепция

Кодирование меняет формат данных.

Шифрование скрывает данные.

Хеширование создаёт необратимый отпечаток данных.

Для паролей применяется не обычное хеширование, а специализированные алгоритмы password hashing:

  • bcrypt;
  • scrypt;
  • Argon2.

Именно они обеспечивают устойчивость современных систем аутентификации к массовому перебору, утечкам баз данных и криптографическим атакам.