Имам логин система. Досега беше с Digest authentication, обаче това е доста неудобно. Не може да се контролира например pop-up прозореца дето изкача за име и парола - и е доста стряскащо за обикновеният юзер.
Варианта с веб форма за име и парола е много удобен за юзерите, може да са украси по всякакъв начин, обаче HTML-а не поддържа нищо друго освен Plain text автентификация

Не ми се плаща за https:// сертификат. Данните които хвърчат по мрежата не са толкова важни че да бъдат криптирани. Интересува ме само да се изпраща криптирана парола, така че ако някой слухти по мрежата а не може да открадне паролата.
---------------------------------------------------------------
След доста мислене и четене стигнах до такова решение с обикновена web форма:
от страна на клиента (браузера):
--------------------------------
<script language="JavaScript" type="text/javascript" src="jsbn.js"></script>
<script language="JavaScript" type="text/javascript" src="rsa.js"></script>
<script language="JavaScript">
function encryptData(){
// Don't forget to escape the lines:
var pem="-----BEGIN PUBLIC KEY-----\
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz8X1t1+7xQ+hZe6NkJQ5\
ip8OE2pqduTGGyds+JQLFHhtfJ9q/GhEPUDk1vw73JPoi3mBYchHtX7KEsx0UDv6\
vMKjuato0x+CGlZ193bFs5G3BkLWsQCTiqF8XaOrEJjLxq4irpKDoWTl7qfC6XPE\
eftumqSHPv6yl0efnYmDBUAIswXZZ02oRyMokQj9sEYq4n7YdI+dTQ2SqGlS7R/6\
ojzM4/JmmkyTXpEzeFtCv1LTwxhBS1j0Lt/SIi38IgONCzE0gsxGbFpXAfToEkNO\
KdGfs7/C3rSBzSaVENAS5N1fCWSAW/byILfSwvN0/HquiUydUpe9aN3TYOkvKtjZ\
cQIDAQAB\
-----END PUBLIC KEY-----";
var key = RSA.getPublicKey(pem);
element=document.getElementById('password');
element.value=RSA.encrypt(element.value, key);
// submit the form
document.getElementById('txtAuth').action='';
document.getElementById('txtAuth').submit();
}
</script>
<form action="javascript:void(0);" method='POST' id='txtAuth' onsubmit='encryptData()'>
<input type='text' name='username'/><BR>
<input type='password' name='password' id='password' placeholder="password"/><BR>
<INPUT type="hidden" name="nonce" value="qwvfjpopdsw">
<input type='submit' name='button' value='Submit'>
</form>
От страна на сървера:
--------------------------------
// Load private key:
$private = @file_get_contents('include-dir/rsa/KEYS/key.pem');
if (false === $private) die("Can't read private key");
if (! $privateKey = openssl_pkey_get_private($private)) die('Loading Private Key failed');
// Decrypt
$decrypted_text = '';
if (! openssl_private_decrypt(base64_decode($_POST['password']), $decrypted_text, $privateKey))
die('Failed to decrypt data');
// Decrypted :)
//print $decrypted_text;
// Free key
openssl_free_key($privateKey);
Клиента кодира паролата с публичният ключ чрез JavaScript RSA функция и събмитва формата. Сърверската (PHP) част декодира паролата с частният ключ и логва клиента.
Проблема е че така реализирано много лесно някой който слуша мрежата може направо да запомни цялата RSA.encrypt('passworд') стойност и да я използва за логване. Нямам идея как такава 'reply' атака се избягва, нито как го правят на практика в протоколите за автентификация.
Това което ми идва на ума е следното:
1. генериране всеки път на нова двойка ключове- това не ме прави поради performance проблеми.
2. наред с изпращането на криптираната парола да се изпраща и случайно генерирано число - 'nonce'.
'nonce'-то се генерира от сървера. Всеки път е различно и важи само един път. Клиента го препраща обратно към сървера.
RSA.encrypt('passworд') ->
nonce ->Ако някой слухти и запомни цялата криптирана парола. То няма да може да използва 2-ри път защото тя си върви в 'пакет' с 'nonce' стойност.
3. 'nonce'-то да се вмъкне като под стринг в паролата:
RSA.encrypt('password:nonce') ->
Идея кой е най-правилният подход и не греша ли някъде в цялата постановка.