Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Кодировка пароля (https://javascript.ru/forum/misc/77240-kodirovka-parolya.html)

loutston 09.04.2019 16:47

Кодировка пароля
 
P.s. Немного содержательности для моего поста:
"Помогите!", "Не работает скрипт!", "Я нуб, нужен совет" :D

laimas 09.04.2019 16:51

Цитата:

Сообщение от loutston
его в принципе будет видно если чекнуть код страницы

А кодера/декодера значит не будет видно?

loutston 09.04.2019 16:55

Одно дело кодер/декодер, и совсем другое сам пароль в чистом виде "abc123", это разные вещи. Сайт образовательного характера, для подростков, так что кодер/декодер то что нужно, в отличае от чистого пароля.

laimas 09.04.2019 17:04

Цитата:

Сообщение от loutston
Одно дело кодер/декодер, и совсем другое сам пароль в чистом виде "abc123", это разные вещи.

Точно? Вы же на клиенте собираетесь проверять и "образец" проверки тоже на нем. А если я знаю образец и код преобразования, то трудно ли мне будет подобрать ключик?

В таком случае код самого кодека должен быть таким, чтобы разобраться в его работе было не легким процессом, в противном случае ваша защита просто забава. Если при этом страница уже есть, но не отображается, то и ключика подбирать не нужно.

loutston 09.04.2019 17:19

Ну если вы не знаете, зачем пишите? Я же не просил нотации читать, а попросил помочь с конкретным вопросом. Если не хотите помогать, зачем вообще писать? Пройдите мимо, буду очень благодарен.

laimas 09.04.2019 17:33

Цитата:

Сообщение от loutston
Ну если вы не знаете, зачем пишите?

Я знаю, что ваша защита, это утопия, странно только почему вас беспокоит доступность "образца", но при этом не понимаете, что также доступно самое главное - как получить образец. Более того, можно ничего не подбираться, а найти в вашем коде то место, в котором финал - получение страницы, и просто выполнить с этого места.

Где сама защищенная страница до поры до времени, на сервере? Вот на сервер и передавайте "abc123", которое он сравнит с хешем этого пароля. В этом случае подобрать будет очень сложно.

loutston 09.04.2019 17:37

Умное решение отправить обработчику и ждать ответ, вопрос был как объединить то, что выше) Конкретный вопрос)

laimas 09.04.2019 17:46

Цитата:

Сообщение от loutston
мное решение отправить обработчику и ждать ответ

А вы чего хотите? Это единственное решение, которое действительно способно обеспечить защиту, а то чего вы хотите, полное решение на клиенте, это чушь полнейшая, надо которой даже заморачиваться не стоит.

loutston 09.04.2019 17:58

Даже если завтра у меня будет болеть голова, сегодня я буду пить. Вы не понимаете самого главного) Я попросил помощи в решении "КОНКРЕТНОЙ" проблемы (с моей стороны), но вместо того что бы помочь, вы пишите что угодно, но только не то что нужно))

loutston 09.04.2019 19:23

Благодарю за отсутствие помощи, разобрался в коде самостоятельно, это было проще чем казалось. Смысла от такого форума, к сожалению не вижу.

Malleys 09.04.2019 20:16

Цитата:

Сообщение от loutston
Благодарю за отсутствие помощи, разобрался в коде самостоятельно, это было проще чем казалось.

Как вы её решили?

Malleys 11.04.2019 13:18

Цитата:

Сообщение от laimas
Где сама защищенная страница до поры до времени, на сервере? Вот на сервер и передавайте "abc123", которое он сравнит с хешем этого пароля. В этом случае подобрать будет очень сложно.

Давайте внимательно посмотрим на вашу схему. Ваша схема должна использовать две страницы. Один для входа в систему, второй для секретной страницы.

Но это большая уязвимость безопасности, если не существует единственного четкого способа доступа к данным вашего приложения. Я не говорю о коде, который я написал таким образом, я думаю, что он должен работать, но кажется, что существует второй способ доступа. Вам нужно два, это нормально, но не более того числа, которое вы предполагаете. Допустим, вы просто перенаправляете своего пользователя на секретную страницу, если предоставленные учетные данные верны. Да, ваши пользователи могут даже не знать, что можно получить секретную страницу, просто вставив правильный адрес в адресную строку, но ничто не мешает поисковому боту Google проиндексировать эту страницу.

На самом деле я нашел вашу идею в одном приложении для камер системы безопасности, которое было разработано так, как вы описали ... люди верили, что они защищены, но на самом деле эта "защищенная" страница была доступна всем, кто делает правильный поисковый запрос.

Я думаю, было бы излишне делать две страницы для этого приложения викторины.

В любом случае, вы можете написать свое решение полностью на JavaScript. В современных браузерах есть API веб-криптографии. Почему бы не использовать это? Таким образом, вы можете создать свое приложение, в котором хранятся вопросы и ответы на вопросы викторины, а также данные, которые будут показаны кому-то, кто прошел тест.

<script>

	var data = {
		quiz: {cipherText:"kqiyEf7WQl9774pyF3PI2w4gmpt0yZDtESUfgNyKaItOvJWzzKBGdLu5q2d9fO2CDlMPldGXJCesA9w7CE73S53hE25HWQSTYuqTZ69tVeQBix4N8QS+8lec8l1ZHawBele5l8A/4Smie77p9sJCakFcF/WYYy1iJJ93UlNzmc00TS7kTOA71D8zYthR/xnfBrnmuwrACgJN+kyUtnpHXKRpuCoicn+NqD2xm63HpbTJnME9Ns/BStttyyWtoYCKvuaB9ZpQYyM5BAR+w0liTiicrawkFslnpTVwY9MqhkNeEq7GZgYkKSXiJmP3H50BVBeozZWSW3lGxJhAk9TVnoQRIvhzP7DqX7NPbL5GUqY8HciSDfwBwPAtPBGBfdP62MZRnFpnW9X7Fmt7tdW4CaaMzjCL2+tg5y5T7GKK0ymgxmohuqRiQnuriOVTxcDAQwNkW2ntZYo+RxU9X2ONiEOienc5SSqGAivNOfReU5UcUJj+8FslyCXhL6AeinxjG9Kis0uVvHKKUMyawM3cT9t3BH1shoVB1e37mJ6g1QKlyUd0VwY8sBqW5TZdCWFJjB65YcicibBEbciXIWcUbUDRqKyS0w==",iv:"CGE/wWm0eEJzWzKu"},
		code: {cipherText:"pNavP6FL6bCxtB9D6fVXhFqRJXWOw/XkCHLohPcWclrYwstm9Rd+NOrtTCAFU7bpDN5VD8wjc9V1gNZpLRAzhfi0kw==",iv:"F6tJKgxCXPveHGYq"}
	};

class App {
	constructor() {}

	async start(encrypted) {
		class State {
			constructor(points) {
				this.points = points;
				Object.freeze(this);
			}
		}
		try {
			const popQuiz = await this.decrypt(encrypted.quiz, () => prompt("Password:", ""));
			var rightAnswers = 0;
			var answers = [];

			alert("Добро пожаловать в викторину!");

			questions: for(const { question, answer } of popQuiz) {
				do {
					var guess = prompt(question);

					if(guess == null) break questions;

					if((await this.hash(guess)) === answer) {
						rightAnswers++;
						answers.push(answer);
						continue questions;
					}
				} while(confirm("Ответ неверен! Попробовать ещё?"));

				break;
			}

			if(rightAnswers === popQuiz.length) {
				var message;
				try {
					message = await this.decrypt(encrypted.code, () => JSON.stringify(answers));
				} catch(error) {}
			}

			alert(`Пройдено ${rightAnswers} из ${popQuiz.length}\n${message ? message : "Чтобы получить расширенный доступ, вы должный пройти тест!"}`);
		} catch(error) {
			console.log(error);
			if(confirm("Авторизация не удалась! Попробовать ещё раз?")) {
				this.start(encrypted);
			}
		}
	}

	static hash(algo, str) {
		return crypto.subtle.digest(algo, new TextEncoder().encode(str));
	}

	static async genEncryptionKey(password, mode, length) {
		var algo = {
			name: 'PBKDF2',
			hash: 'SHA-256',
			salt: new TextEncoder().encode('a-unique-salt'),
			iterations: 1000
		};

		var derived = { name: mode, length: length };
		var encoded = new TextEncoder().encode(password);
		var key = await crypto.subtle.importKey('raw', encoded, { name: 'PBKDF2' }, false, ['deriveKey']);
	
		return crypto.subtle.deriveKey(algo, key, derived, false, ['encrypt', 'decrypt']);
	}

	static async encrypt(text, password, mode, length, ivLength) {
		var algo = {
			name: mode,
			length: length,
			iv: crypto.getRandomValues(new Uint8Array(ivLength))
		};
		var key = await this.genEncryptionKey(password, mode, length);
		var encoded = new TextEncoder().encode(text);

		return {
			cipherText: await crypto.subtle.encrypt(algo, key, encoded),
			iv: algo.iv,
			toJSON() {
				return {
					cipherText: App.encode64(this.cipherText),
					iv: App.encode64(this.iv)
				};
			}
		};
	}

	static async decrypt(encrypted, password, mode, length) {
		var algo = {
			name: mode,
			length: length,
			iv: encrypted.iv
		};
		var key = await this.genEncryptionKey(password, mode, length);
		var decrypted = await crypto.subtle.decrypt(algo, key, encrypted.cipherText);

		return new TextDecoder().decode(decrypted);
	}

	static encode64(buff) {
		return btoa(new Uint8Array(buff).reduce((s, b) => s + String.fromCharCode(b), ""));
	}

	async encrypt(object, passwordCallback) {
		var mode = 'AES-GCM', length = 256, ivLength = 12;
		var encrypted = await App.encrypt(JSON.stringify(object), passwordCallback(), mode, length, ivLength);
		return encrypted.toJSON();
	}

	async decrypt(object, passwordCallback) {
		var mode = 'AES-GCM', length = 256, ivLength = 12;

		function toBuffer(encrypted, property) {
			return fetch(`data:text/plain;base64,${encrypted[property]}`).then(r => r.arrayBuffer());
		}

		var encrypted = {
			cipherText: await toBuffer(object, "cipherText"),
			iv: new Uint8Array(await toBuffer(object, "iv"))
		};

		var decrypted = await App.decrypt(encrypted, passwordCallback(), mode, length);
		return JSON.parse(decrypted);
	}

	async hash(string) {
		var hashed = await App.hash('SHA-256', `#DATA<${string}>`);
		return App.encode64(hashed);
	}
}

var app = new App();

</script>
<button onclick="app.start(data);">Начать викторину для избранных!</button>

рони 11.04.2019 14:14

Malleys,
спасибо за код(концепция понятна), жаль только знаний маловато, не могу его ни дополнить, ни использовать.


Часовой пояс GMT +3, время: 13:09.