Задать вопрос
@arseniylebedev

Безопасно ли шифрование в моем коде?

Доброго времени суток! Написал простой мессенджер с шифрованием aes. Шифрование работает так:
1) При подключении сервер генерирует новые RSA ключи для клиента, Отправляет клиенту публичный RSA ключ.
2) Клиент генерирует AES 256 ключ, зашифровывает его публичным RSA ключом и отправляет серверу.
3) Далее обмен сообщениями идет с использованием AES ключа.

Сервер
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const aes256 = require('aes256');
const NodeRSA = require('node-rsa');
const crypto = require('crypto');
const clients = require('./clients');

app.get('/', function(req, res){
    res.send('Messenger srv :)')
});

io.on('connection', function(socket){
    const socket_data = {
        socket: socket,
        rsa_key: new NodeRSA({b: 1024}),
        aes_key: undefined,
        aes_sipher: undefined,
        aes_test: crypto.randomBytes(64).toString('hex'),
    };

    clients.addClient(socket.id, socket_data);

    const addr = socket.handshake.address;
    console.log('IP ' + addr + ' connected!');

    socket.emit('rsa_public_swap', socket_data.rsa_key.exportKey('pkcs8-public-pem'));

    socket.on('aes_swap', function (data) {
        socket_data.aes_key = socket_data.rsa_key.decrypt(data, 'utf8');
        socket_data.aes_sipher = aes256.createCipher(socket_data.aes_key);
        socket_data.aes_test = crypto.randomBytes(64).toString('hex');
        clients.modifyClient(socket.id, socket_data);
        socket.emit('aes_test', socket_data.aes_sipher.encrypt(socket_data.aes_test));
    });

    socket.on('aes_test', function (data) {
        data = socket_data.aes_sipher.decrypt(data);

        socket_data.aes_test += '1';

        if (socket_data.aes_test !== data) {
            socket.disconnect();
        } else {
            socket_data.rsa_key = undefined;
            socket_data.aes_test = undefined;
            clients.modifyClient(socket.id, socket_data);
        }
    });

    socket.on('all_chat', function (data) {
        data = socket_data.aes_sipher.decrypt(data);

        for (const index in clients.getClients()) {
            const client = clients.getClients()[index];

            // if (client.socket.id === socket.id) continue;

            client.socket.emit('all_chat', client.aes_sipher.encrypt(data));
        }
    });

    socket.on('disconnect', function () {
        clients.removeClient(socket.id);
    });
});

http.listen(3000, function(){
    console.log('listening on *:3000');
});

Клиент
const io = require('socket.io-client');
const aes256 = require('aes256');
const NodeRSA = require('node-rsa');
const crypto = require('crypto');
const readline = require('readline');

const socket = io('http://localhost:3000');
let rsa_key = undefined;
let aes_key = undefined;
let aes_sipher = undefined;

socket.on('connect', function() {
    console.log('Connected!');

    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    rl.on('line', (line) => {
        if (line.length === 0) return;

        socket.emit('all_chat', aes_sipher.encrypt(line));
    });
});

socket.on('rsa_public_swap', function(data) {
    console.log('Получил RSA public key...');
    
    rsa_key = new NodeRSA();
    rsa_key.importKey(data);
    
    console.log(rsa_key.encrypt('test', 'base64'));
    console.log('Импортировал RSA public key');

    console.log('Генерирую AES 256 ключ');
    aes_key = crypto.randomBytes(256).toString('hex');
    aes_sipher = aes256.createCipher(aes_key);
    console.log('Сгенерировал AES 256 ключ');

    console.log('Обмениваюсь AES 256 ключем с сервером');

    socket.emit('aes_swap', rsa_key.encrypt(aes_key, 'base64'))
});

socket.on('aes_test', function(data) {
    console.log('Проверяю RSA шифрование с сервером');
    data = aes_sipher.decrypt(data);

    data += '1';

    socket.emit('aes_test', aes_sipher.encrypt(data));
    console.log('Отправил пакет проверки RSA шифрования серверу. Если нас не дисконнектнет то проверка пройдена.');
});

socket.on('all_chat', function(data) {
    data = aes_sipher.decrypt(data);
    console.log(data);
});

socket.on('disconnect', function() {
    console.log('Disconnected!');
});

  • Вопрос задан
  • 195 просмотров
Подписаться 1 Средний 18 комментариев
Решения вопроса 1
@CHolfield
по всей видимости, ты взял пример из интернета или хз откуда-то, и не до конца понимаешь принципы безопасного обмена информацией с помощью криптографии.
В общем случае, код твой верен, будет работать. Но делать надо чуть по-другому.
обязательные требования:
1. публичный ключ сервера должен быть вшит в клиентскую часть, Публичный ключ клиента должен быть известен серверу до начала коммуникации (это называется обмен ключами по защищенному каналу). Либо поднимай свой Certification Authority и выстраивай инфраструктуру публичных ключей и пространство доверия на основе Certificate Trust List.
2. каждый новый сеанс обмена информацией должен начинаться с генерации нового ключа AES и вектора инициализации.
3. Каждый пакет отправляемых данных должен быть подписан электронной подписью (секретным ключем отправителя) и зашифрован AES ключом. Также каждый пакет должен содержать зашифрованный публичным ключем получателя сеансовый AES ключ и зашифрованный таким же способом вектор инициализации.
4. получающая сторона расшифровывает AES ключ и вектор инициализации своим секретным ключем, расшифровывает сеансовым ключем данные, проверяет подпись данных с помощью сертификата отправителя, в случае положительного результата обрабатывает данные.

как-то так.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы