• Forum has been upgraded, all links, images, etc are as they were. Please see Official Announcements for more information

Authentication with wallet

Balych

Active member
English translate, original here.

I got an idea, why should server keep passwords and users remember it, when we have such a wonderful thing - blockchain.
User provide public key (address) and confirms ownership of it by sign random string obtained from server, and server can validate session by verifying signed string.

Here some example, demo available at https://auth.dashnetwork.info/

Enter your DASH-address (actually it can be any other coin, which support signing/verifying messages):

LosHnfK.png


Server generate random string (need some work of it randomness...) and ask user to sign it:

yeXwKvw.png


It would be nice to see something like BIP-0021, but for messaging.

So, sign message with dash-cli or Dash Core:

5U9xkK0.png


Paste signature and enjoy success login:

aMi6D4f.png


Source:

PHP:
<?php
session_start();
require_once('easydash.php');

if ($_POST['login']) {
    $_SESSION['login'] = filter_input(INPUT_POST, 'login', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[X][a-km-zA-HJ-NP-Z1-9]{25,34}$/')));
    if ($_SESSION['login'] == true) {
        $_SESSION['message'] = sha1(crypt(time().inet_pton($_SERVER['REMOTE_ADDR']).$_SESSION['login']));
        echo '
            Sign this message:<br /><br />
            <input type="text" id="message" value="'.$_SESSION['message'].'" readonly /><br /><br />
            <input type="text" name="signature" id="signature" placeholder="Input signature"  ><br /><br />
            <input type="submit" value="Login" />';
    }
}

if ($_POST['signature']) {
    $_SESSION['signature'] = filter_input(INPUT_POST, 'signature', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/[a-zA-Z0-9=\/+]{88}/')));
    $dash = new \elbereth\EasyDash('rpc_username','rpc_password');
    $_SESSION['auth'] = $dash->verifymessage($_SESSION['login'],$_SESSION['signature'],$_SESSION['message']);
}

if ($_POST['logout']) {
    $_SESSION = array();
    session_destroy();
}

function is_auth() {
    if ($_SESSION['auth'] == true) {
        echo '
            Hello, '.$_SESSION['login'].'!<br /><br /><input type="hidden" name="logout" value="1"><input type="submit" value="Logout" />';
    } else if (!$_POST['login'] || ($_SESSION['login']==false && $_POST['login'])){
        echo '
            Hello, guest!<br /><br />
                <input type="text" name="login" id="login" placeholder="Input your DASH address" /><br /><br />
                <input type="submit" value="Login" />';
        $_SESSION = array();
        session_destroy();
    }
}

is_auth();
?>

HTML:
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dash Network Info</title>
<style type="text/css">
body {
    margin: 0;
    padding: 0;
}
html, body, #wrapper { height: 100%; }
#wrapper {
    width: 100%;
    display:table;
}
#main_cell, #link_cell {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
#main_cell { height: 95%; }
#link_cell { height: 5%; }
body * {
    font-family: Verdana;
    font-size: 3vmin;
    font-size: 3vm;
}
input {
    min-width: 70vmin;
    min-width: 70vm;
    text-align: center;
}
#login, #signature, #message {
    outline: none;
    border: 0;
    border-bottom: #ccc 1px solid;
}
.row { display: table-row; }
a { text-decoration:none; }
a:link, a:visited { color: #1c75bc; }
a:hover, a:active { color: #ec2227; }
</style>
<script src="jquery.min.js"></script>
<script>
$(function() {
    auth();
    $("#auth_form").submit(function() {
        auth();
        return false;
    })
})
function auth() {
    $.ajax({
        url: "auth.php",
        type: "post",
        dataType: "html",
        data: $("#auth_form").serialize(),
        success: function(data) {
            $('#auth_div').html(data);
        },
        error: function() {
            $('#auth_div').html('Authentication not available');
        }
    })
}
</script>
</head>
<body>
<div id="wrapper">
    <div class="row">
        <div id="main_cell">
            <form action="" method="POST" id="auth_form">
                <div id="auth_div">
               
                </div>
            </form>
        </div>
    </div>
    <div class="row">
        <div id="link_cell">
            <a id="link" href="https://www.dash.org">www.dash.org</a>
        </div>
    </div>
</div>
</body>
</html>

3rd-party script easydash.php is used to verify the signature, but can be achieved with dash-cli. Also it requires JQuery.

Not sure about regex accuracy..

Of course it's not complete solution, but may be useful to someone for further idea development. As 2FA element, for example.
 
Added possibility to authenticate with BTC-address. Server-side verifying with Electrum wallet instead of Bitcoin Core for HDD space economy.

PHP:
<?php
session_start();
require_once('easydash.php');

if ($_POST['login']) {
    $_SESSION['login'] = filter_input(INPUT_POST, 'login', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[X][a-km-zA-HJ-NP-Z1-9]{25,34}$/')));
    $_SESSION['coin'] = 'dash';
    if ($_SESSION['login'] == false) {
        $_SESSION['login'] = filter_input(INPUT_POST, 'login', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/')));
        $_SESSION['coin'] = 'btc';
    }
    if ($_SESSION['login'] == true) {
        $_SESSION['message'] = sha1(crypt(time().inet_pton($_SERVER['REMOTE_ADDR']).$_SESSION['login']));
        echo '
            Sign this message:<br /><br />
            <input type="text" id="message" value="'.$_SESSION['message'].'" readonly /><br /><br />
            <input type="text" name="signature" id="signature" placeholder="Input signature"  ><br /><br />
            <input type="submit" value="Login" />';
    }
}

if ($_POST['signature']) {
    $_SESSION['signature'] = filter_input(INPUT_POST, 'signature', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/[a-zA-Z0-9=\/+]{88}/')));
    switch ($_SESSION['coin']) {
        case 'btc':
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_URL, 'http://127.0.0.1:7777');
            $data = '{"id":"curltext","method":"verifymessage","params":["'.$_SESSION['login'].'","'.$_SESSION['signature'].'","'.$_SESSION['message'].'"]}';
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            $result = json_decode(curl_exec($curl), true);
            $_SESSION['auth'] = $result['result'];
            break;
        case 'dash':
            $dash = new \elbereth\EasyDash('rpc_user','rpc_password');
            $_SESSION['auth'] = $dash->verifymessage($_SESSION['login'],$_SESSION['signature'],$_SESSION['message']);
            break;
    }
}

if ($_POST['logout']) {
    $_SESSION = array();
    session_destroy();
}

function is_auth() {
    if ($_SESSION['auth'] == true) {
        echo '
            Hello, '.$_SESSION['login'].'!<br /><br /><input type="hidden" name="logout" value="1"><input type="submit" value="Logout" />';
    } else if (!$_POST['login'] || ($_SESSION['login']==false && $_POST['login'])){
        echo '
            Hello, guest!<br /><br />
                <input type="text" name="login" id="login" placeholder="Input your BTC or DASH address" /><br /><br />
                <input type="submit" value="Login" />';
        $_SESSION = array();
        session_destroy();
    }
}

is_auth();
?>
 
Last edited:
Back
Top