mirror of
https://github.com/number571/hes.git
synced 2026-09-12 19:50:01 +05:00
update v1.1.1
This commit is contained in:
parent
472748b7dd
commit
6d7ff3cc89
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
server
|
||||
gclient
|
||||
gclient.exe
|
||||
server.exe
|
||||
server.db
|
||||
client.db
|
||||
|
||||
1
Makefile
1
Makefile
@ -5,6 +5,7 @@ default: build
|
||||
install:
|
||||
$(GI) github.com/number571/gopeer
|
||||
$(GI) github.com/mattn/go-sqlite3
|
||||
$(GI) github.com/boombuler/barcode
|
||||
$(GI) golang.org/x/net/proxy
|
||||
build: gclient.go server.go database.go
|
||||
$(GC) gclient.go
|
||||
|
||||
21
README.md
21
README.md
@ -1,6 +1,6 @@
|
||||
# HES
|
||||
|
||||
> Hidden email service. Version 1.1.0s.
|
||||
> Hidden email service. Version 1.1.1s.
|
||||
|
||||
### Characteristics:
|
||||
1. End to end encryption;
|
||||
@ -17,6 +17,7 @@
|
||||
$ make install
|
||||
> go get github.com/number571/gopeer
|
||||
> go get github.com/mattn/go-sqlite3
|
||||
> go get github.com/boombuler/barcode
|
||||
> go get golang.org/x/net/proxy
|
||||
```
|
||||
|
||||
@ -55,7 +56,8 @@ CREATE TABLE IF NOT EXISTS emails (
|
||||
#### Client side
|
||||
```sql
|
||||
/* !key_pasw = hash(password, salt)^20 */
|
||||
/* pasw = hash(!key_pasw) */
|
||||
/* name = hash(name) */
|
||||
/* pasw = hash(!key_pasw, name) */
|
||||
/* priv = encrypt[!key_pasw](private_key) */
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER,
|
||||
@ -65,7 +67,7 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
priv TEXT,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
/* hash = hash(host, !key_pasw, salt) */
|
||||
/* hash = hash(host, !key_pasw) */
|
||||
/* host = encrypt[!key_pasw](host) */
|
||||
CREATE TABLE IF NOT EXISTS connects (
|
||||
id INTEGER,
|
||||
@ -75,19 +77,22 @@ CREATE TABLE IF NOT EXISTS connects (
|
||||
PRIMARY KEY(id),
|
||||
FOREIGN KEY(id_user) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
/* hash = hash(pack_hash, !key_pasw, salt) */
|
||||
/* spubl = encrypt[!key_pasw](public_key) */
|
||||
/* sname = encrypt[!key_pasw](nickname) */
|
||||
/* head = encrypt[!key_pasw](title) */
|
||||
/* body = encrypt[!key_pasw](message) */
|
||||
/* hash = hash(pack_hash, !key_pasw) */
|
||||
/* spubl = encrypt[!key_pasw](public_key) */
|
||||
/* sname = encrypt[!key_pasw](nickname) */
|
||||
/* head = encrypt[!key_pasw](title) */
|
||||
/* body = encrypt[!key_pasw](message) */
|
||||
/* addtime = encrypt[!key_pasw](time_rec) */
|
||||
CREATE TABLE IF NOT EXISTS emails (
|
||||
id INTEGER,
|
||||
id_user INTEGER,
|
||||
deleted BOOLEAN DEFAULT 0,
|
||||
hash VARCHAR(255) UNIQUE,
|
||||
spubl TEXT,
|
||||
sname VARCHAR(255),
|
||||
head VARCHAR(255),
|
||||
body TEXT,
|
||||
addtime TEXT,
|
||||
PRIMARY KEY(id),
|
||||
FOREIGN KEY(id_user) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
11
database.go
11
database.go
@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS emails (
|
||||
recv VARCHAR(255),
|
||||
hash VARCHAR(255) UNIQUE,
|
||||
data TEXT,
|
||||
addtime DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
`)
|
||||
@ -58,6 +59,16 @@ func (db *DB) GetEmail(id int, recv string) string {
|
||||
return data
|
||||
}
|
||||
|
||||
func (db *DB) DelEmailsByDay(day int) error {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
_, err := db.ptr.Exec(
|
||||
"DELETE FROM emails WHERE addtime < datetime('now', '-' | $1 | ' days')",
|
||||
day,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) Size(recv string) int {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
|
||||
62
gclient.go
62
gclient.go
@ -6,9 +6,12 @@ import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"image/png"
|
||||
"strconv"
|
||||
gp "github.com/number571/gopeer"
|
||||
"golang.org/x/net/proxy"
|
||||
"github.com/boombuler/barcode"
|
||||
"github.com/boombuler/barcode/qr"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -186,6 +189,12 @@ func signoutPage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func accountPage(w http.ResponseWriter, r *http.Request) {
|
||||
type AccountTemplateResult struct {
|
||||
TemplateResult
|
||||
PublicKey string
|
||||
PrivateKey string
|
||||
}
|
||||
retcod, result := makeResult(RET_SUCCESS, "")
|
||||
t, err := template.ParseFiles(
|
||||
PATH_VIEWS+"base.html",
|
||||
PATH_VIEWS+"account.html",
|
||||
@ -193,12 +202,33 @@ func accountPage(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
panic("error: load account.html")
|
||||
}
|
||||
if SESSIONS.Get(r) == nil {
|
||||
user := SESSIONS.Get(r)
|
||||
if user == nil {
|
||||
http.Redirect(w, r, "/", 302)
|
||||
return
|
||||
}
|
||||
t.Execute(w, TemplateResult{
|
||||
Auth: getName(SESSIONS.Get(r)),
|
||||
if r.Method == "POST" && r.FormValue("delete") != "" {
|
||||
name := r.FormValue("username")
|
||||
pasw := r.FormValue("password")
|
||||
cuser := DATABASE.GetUser(name, pasw)
|
||||
switch {
|
||||
case cuser == nil || cuser.Id != user.Id:
|
||||
retcod, result = makeResult(RET_DANGER, "username of password incorrect")
|
||||
default:
|
||||
SESSIONS.Del(w, r)
|
||||
DATABASE.DelUser(cuser)
|
||||
http.Redirect(w, r, "/", 302)
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Execute(w, AccountTemplateResult{
|
||||
TemplateResult: TemplateResult{
|
||||
Auth: getName(SESSIONS.Get(r)),
|
||||
Result: result,
|
||||
Return: retcod,
|
||||
},
|
||||
PublicKey: gp.PublicKeyToString(&user.Priv.PublicKey),
|
||||
PrivateKey: gp.PrivateKeyToString(user.Priv),
|
||||
})
|
||||
}
|
||||
|
||||
@ -208,7 +238,18 @@ func accountPublicKeyPage(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "session is nil")
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, gp.PublicKeyToString(&user.Priv.PublicKey))
|
||||
dataString := gp.PublicKeyToString(&user.Priv.PublicKey)
|
||||
qrCode, err := qr.Encode(dataString, qr.Q, qr.Auto)
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "qrcode generate error")
|
||||
return
|
||||
}
|
||||
qrCode, err = barcode.Scale(qrCode, 768, 768)
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "qrcode scale error")
|
||||
return
|
||||
}
|
||||
png.Encode(w, qrCode)
|
||||
}
|
||||
|
||||
func accountPrivateKeyPage(w http.ResponseWriter, r *http.Request) {
|
||||
@ -217,7 +258,18 @@ func accountPrivateKeyPage(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "session is nil")
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, gp.PrivateKeyToString(user.Priv))
|
||||
dataString := gp.PrivateKeyToString(user.Priv)
|
||||
qrCode, err := qr.Encode(dataString, qr.Q, qr.Auto)
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "qrcode generate error")
|
||||
return
|
||||
}
|
||||
qrCode, err = barcode.Scale(qrCode, 768, 768)
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "qrcode scale error")
|
||||
return
|
||||
}
|
||||
png.Encode(w, qrCode)
|
||||
}
|
||||
|
||||
func networkPage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"time"
|
||||
"fmt"
|
||||
gp "github.com/number571/gopeer"
|
||||
"net/http"
|
||||
@ -30,6 +31,12 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
go func() {
|
||||
for {
|
||||
DATABASE.DelEmailsByDay(1)
|
||||
time.Sleep(6 * time.Hour)
|
||||
}
|
||||
}()
|
||||
http.HandleFunc("/", indexPage)
|
||||
http.HandleFunc("/send", emailSendPage)
|
||||
http.HandleFunc("/recv", emailRecvPage)
|
||||
|
||||
@ -3,6 +3,7 @@ package userside
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
"bytes"
|
||||
"strings"
|
||||
"crypto/rsa"
|
||||
@ -11,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
DIFF_ENTR = 20 // bits
|
||||
DIFF_ENTR = 20 // bits
|
||||
SEPARATOR = "\005\007\001"
|
||||
)
|
||||
|
||||
@ -21,6 +22,8 @@ func NewDB(name string) *DB {
|
||||
return nil
|
||||
}
|
||||
_, err = db.Exec(`
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA secure_delete=ON;
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER,
|
||||
name NVARCHAR(255) UNIQUE,
|
||||
@ -40,11 +43,13 @@ CREATE TABLE IF NOT EXISTS connects (
|
||||
CREATE TABLE IF NOT EXISTS emails (
|
||||
id INTEGER,
|
||||
id_user INTEGER,
|
||||
deleted BOOLEAN DEFAULT 0,
|
||||
hash VARCHAR(255) UNIQUE,
|
||||
spubl TEXT,
|
||||
sname VARCHAR(255),
|
||||
head VARCHAR(255),
|
||||
body TEXT,
|
||||
addtime TEXT,
|
||||
PRIMARY KEY(id),
|
||||
FOREIGN KEY(id_user) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
@ -60,15 +65,22 @@ CREATE TABLE IF NOT EXISTS emails (
|
||||
func (db *DB) SetUser(name, pasw string, priv *rsa.PrivateKey) error {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
name = strings.TrimSpace(name)
|
||||
if db.userExist(name) {
|
||||
return fmt.Errorf("user already exist")
|
||||
}
|
||||
salt := gp.GenerateBytes(32)
|
||||
bpasw := RaiseEntropy([]byte(pasw), salt, DIFF_ENTR)
|
||||
hpasw := gp.HashSum(bpasw)
|
||||
hpasw := gp.HashSum(bytes.Join(
|
||||
[][]byte{
|
||||
bpasw,
|
||||
[]byte(name),
|
||||
},
|
||||
[]byte{},
|
||||
))
|
||||
_, err := db.ptr.Exec(
|
||||
"INSERT INTO users (name, pasw, salt, priv) VALUES ($1, $2, $3, $4)",
|
||||
name,
|
||||
gp.Base64Encode(gp.HashSum([]byte(name))),
|
||||
gp.Base64Encode(hpasw),
|
||||
gp.Base64Encode(salt),
|
||||
gp.Base64Encode(gp.EncryptAES(bpasw, gp.PrivateKeyToBytes(priv))),
|
||||
@ -80,14 +92,15 @@ func (db *DB) GetUser(name, pasw string) *User {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
var (
|
||||
id int
|
||||
id int
|
||||
hpasw string
|
||||
ssalt string
|
||||
spriv string
|
||||
)
|
||||
name = strings.TrimSpace(name)
|
||||
row := db.ptr.QueryRow(
|
||||
"SELECT id, pasw, salt, priv FROM users WHERE name=$1",
|
||||
name,
|
||||
gp.Base64Encode(gp.HashSum([]byte(name))),
|
||||
)
|
||||
row.Scan(&id, &hpasw, &ssalt, &spriv)
|
||||
if spriv == "" {
|
||||
@ -95,7 +108,14 @@ func (db *DB) GetUser(name, pasw string) *User {
|
||||
}
|
||||
salt := gp.Base64Decode(ssalt)
|
||||
bpasw := RaiseEntropy([]byte(pasw), salt, DIFF_ENTR)
|
||||
if !bytes.Equal(gp.HashSum(bpasw), gp.Base64Decode(hpasw)) {
|
||||
chpasw := gp.HashSum(bytes.Join(
|
||||
[][]byte{
|
||||
bpasw,
|
||||
[]byte(name),
|
||||
},
|
||||
[]byte{},
|
||||
))
|
||||
if !bytes.Equal(chpasw, gp.Base64Decode(hpasw)) {
|
||||
return nil
|
||||
}
|
||||
priv := gp.BytesToPrivateKey(gp.DecryptAES(bpasw, gp.Base64Decode(spriv)))
|
||||
@ -106,11 +126,20 @@ func (db *DB) GetUser(name, pasw string) *User {
|
||||
Id: id,
|
||||
Name: name,
|
||||
Pasw: bpasw,
|
||||
Salt: salt,
|
||||
Priv: priv,
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) DelUser(user *User) error {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
_, err := db.ptr.Exec(
|
||||
"DELETE FROM users WHERE id=$1",
|
||||
user.Id,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) GetEmails(user *User, start, quan int) []Email {
|
||||
var (
|
||||
email *Email
|
||||
@ -135,13 +164,14 @@ func (db *DB) GetEmail(user *User, id int) *Email {
|
||||
head string
|
||||
body string
|
||||
hash string
|
||||
atime string
|
||||
)
|
||||
row := db.ptr.QueryRow(
|
||||
"SELECT spubl, sname, head, body, hash FROM emails WHERE id_user=$1 ORDER BY id DESC LIMIT 1 OFFSET $2",
|
||||
"SELECT spubl, sname, head, body, hash, addtime FROM emails WHERE id_user=$1 AND deleted=0 ORDER BY id DESC LIMIT 1 OFFSET $2",
|
||||
user.Id,
|
||||
id,
|
||||
)
|
||||
row.Scan(&spubl, &sname, &head, &body, &hash)
|
||||
row.Scan(&spubl, &sname, &head, &body, &hash, &atime)
|
||||
if spubl == "" {
|
||||
return nil
|
||||
}
|
||||
@ -152,6 +182,7 @@ func (db *DB) GetEmail(user *User, id int) *Email {
|
||||
SenderName: string(gp.DecryptAES(user.Pasw, gp.Base64Decode(sname))),
|
||||
Head: string(gp.DecryptAES(user.Pasw, gp.Base64Decode(head))),
|
||||
Body: string(gp.DecryptAES(user.Pasw, gp.Base64Decode(body))),
|
||||
Time: string(gp.DecryptAES(user.Pasw, gp.Base64Decode(atime))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,13 +197,14 @@ func (db *DB) SetEmail(user *User, pack *gp.Package) error {
|
||||
return fmt.Errorf("len.splited != 2")
|
||||
}
|
||||
_, err := db.ptr.Exec(
|
||||
"INSERT INTO emails (id_user, hash, spubl, sname, head, body) VALUES ($1, $2, $3, $4, $5, $6)",
|
||||
"INSERT INTO emails (id_user, hash, spubl, sname, head, body, addtime) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||
user.Id,
|
||||
hashWithSecret(user, pack.Body.Hash),
|
||||
gp.Base64Encode(gp.EncryptAES(user.Pasw, []byte(pack.Head.Sender))),
|
||||
gp.Base64Encode(gp.EncryptAES(user.Pasw, []byte(splited[0]))),
|
||||
gp.Base64Encode(gp.EncryptAES(user.Pasw, []byte(splited[1]))),
|
||||
gp.Base64Encode(gp.EncryptAES(user.Pasw, []byte(pack.Body.Data))),
|
||||
gp.Base64Encode(gp.EncryptAES(user.Pasw, []byte(time.Now().Format(time.RFC850)))),
|
||||
)
|
||||
return err
|
||||
}
|
||||
@ -181,7 +213,7 @@ func (db *DB) DelEmail(user *User, hash string) error {
|
||||
db.mtx.Lock()
|
||||
defer db.mtx.Unlock()
|
||||
_, err := db.ptr.Exec(
|
||||
"DELETE FROM emails WHERE id_user=$1 AND hash=$2",
|
||||
"UPDATE emails SET deleted=1, spubl=NULL, sname=NULL, head=NULL, body=NULL, addtime=NULL WHERE id_user=$1 AND hash=$2",
|
||||
user.Id,
|
||||
hash,
|
||||
)
|
||||
@ -247,7 +279,7 @@ func (db *DB) userExist(name string) bool {
|
||||
)
|
||||
row := db.ptr.QueryRow(
|
||||
"SELECT name FROM users WHERE name=$1",
|
||||
name,
|
||||
gp.Base64Encode(gp.HashSum([]byte(name))),
|
||||
)
|
||||
row.Scan(&namee)
|
||||
return namee != ""
|
||||
@ -284,7 +316,6 @@ func hashWithSecret(user *User, data string) string {
|
||||
[][]byte{
|
||||
[]byte(data),
|
||||
user.Pasw,
|
||||
user.Salt,
|
||||
},
|
||||
[]byte{},
|
||||
)))
|
||||
|
||||
@ -16,7 +16,6 @@ type User struct {
|
||||
Id int
|
||||
Name string
|
||||
Pasw []byte
|
||||
Salt []byte
|
||||
Priv *rsa.PrivateKey
|
||||
}
|
||||
|
||||
@ -27,6 +26,7 @@ type Email struct {
|
||||
Head string
|
||||
Body string
|
||||
Hash string
|
||||
Time string
|
||||
}
|
||||
|
||||
type Sessions struct {
|
||||
|
||||
@ -3,19 +3,99 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<div id="message_copy" class="text-light mx-auto"></div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-secondary divtext w-100" disabled>{{ .Auth }}</button>
|
||||
<button type="button" class="btn btn-secondary divtext w-100" disabled><h5>{{ .Auth }}</h5></button>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 w-50">
|
||||
<form class="text-center" method="POST" action="/account/private_key">
|
||||
<input type="submit" name="submit" value="Look private key" class="btn btn-success w-100">
|
||||
<button type="button" class="btn btn-success w-100" onclick="copy_public_key()">CP public key</button>
|
||||
</div>
|
||||
<div class="col-md-6 w-50">
|
||||
<button type="button" class="btn btn-success w-100" onclick="copy_private_key()">CP private key</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 w-50">
|
||||
<form class="text-center" method="POST" action="/account/public_key">
|
||||
<input type="submit" name="submit" value="QR public key" class="btn btn-info w-100">
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 w-50">
|
||||
<form class="text-center" method="POST" action="/account/public_key">
|
||||
<input type="submit" name="submit" value="Look public key" class="btn btn-success w-100">
|
||||
<form class="text-center" method="POST" action="/account/private_key">
|
||||
<input type="submit" name="submit" value="QR private key" class="btn btn-info w-100">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">Public key</h5>
|
||||
<div class="card-body">
|
||||
<h6 class="card-text">{{ .PublicKey }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">Private key</h5>
|
||||
<div class="card-body">
|
||||
<h6 class="card-text">{{ .PrivateKey }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-danger w-100" onclick="hide_input()">Delete account</button>
|
||||
</div>
|
||||
<div id="input_password" class="form-group"></div>
|
||||
<div style="opacity:0">
|
||||
<input id="private_key" type="text" value="{{ .PrivateKey }}">
|
||||
<input id="public_key" type="text" value="{{ .PublicKey }}">
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
function copy_public_key() {
|
||||
var copyText = document.getElementById("public_key");
|
||||
copyText.select();
|
||||
document.execCommand("copy");
|
||||
let newInput = `
|
||||
<div class="alert alert-success" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
Public key copied
|
||||
</div>
|
||||
`
|
||||
document.getElementById("message_copy").innerHTML = newInput;
|
||||
}
|
||||
function copy_private_key() {
|
||||
var copyText = document.getElementById("private_key");
|
||||
copyText.select();
|
||||
document.execCommand("copy");
|
||||
let newInput = `
|
||||
<div class="alert alert-success" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
Private key copied
|
||||
</div>
|
||||
`
|
||||
document.getElementById("message_copy").innerHTML = newInput;
|
||||
}
|
||||
function hide_input() {
|
||||
let elem = document.getElementById("password-form");
|
||||
if (elem) {
|
||||
document.getElementById("password-form").remove();
|
||||
} else {
|
||||
let newInput = `
|
||||
<form id='password-form' class="text-center" method="POST" action="/account">
|
||||
<div class="form-group">
|
||||
<input type='text' class='form-control bg-dark text-light' name='username' placeholder='Username'>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type='password' class='form-control bg-dark text-light' name='password' placeholder='Password'>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="delete" value="Confirm deletion " class="btn btn-warning w-100">
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
document.getElementById("input_password").innerHTML = newInput;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{{ end }}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">HES project</h5>
|
||||
<div class="card-body">
|
||||
<h6 class="card-text">version: 1.1.0;</h6>
|
||||
<h6 class="card-text">version: 1.1.1;</h6>
|
||||
<h6 class="card-text">project: <a target="_blank" class="text-info" href="https://github.com/Number571/HES">hes.git</a>;</h6>
|
||||
<h6 class="card-text">author: <a target="_blank" class="text-info" href="https://github.com/Number571">number571</a>;</h6>
|
||||
</div>
|
||||
@ -17,6 +17,7 @@
|
||||
<h6 class="card-text">protocol: <a target="_blank" class="text-info" href="https://github.com/Number571/gopeer">gopeer.git</a>;</h6>
|
||||
<h6 class="card-text">database: <a target="_blank" class="text-info" href="https://github.com/mattn/go-sqlite3">go-sqlite3.git</a>;</h6>
|
||||
<h6 class="card-text">design: <a target="_blank" class="text-info" href="https://github.com/twbs/bootstrap">bootstrap.git</a>;</h6>
|
||||
<h6 class="card-text">qrcode: <a target="_blank" class="text-info" href="https://github.com/boombuler/barcode">barcode.git</a>;</h6>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
@ -3,6 +3,18 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<div id="message_copy" class="text-light mx-auto"></div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 w-50">
|
||||
<button type="button" class="btn btn-success w-100" onclick="copy_public_key()">Copy public key</button>
|
||||
</div>
|
||||
<div class="col-md-6 w-50">
|
||||
<form class="text-center" method="POST" action="/network">
|
||||
<input type="hidden" name="email" value="{{ .Email.Hash }}">
|
||||
<input type="submit" name="delete" value="Delete" class="btn btn-danger w-100">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">Email</h5>
|
||||
<div class="card-body">
|
||||
@ -17,18 +29,35 @@
|
||||
<h6 class="card-text">{{ .Email.SenderPubl }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-success w-100" onclick="copy()">Copy public key</button>
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">Time</h5>
|
||||
<div class="card-body">
|
||||
<h6 class="card-text">{{ .Email.Time }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card text-white bg-dark mb-3">
|
||||
<h5 class="card-header bg-secondary">Hash</h5>
|
||||
<div class="card-body">
|
||||
<h6 class="card-text">{{ .Email.Hash }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div style="opacity:0">
|
||||
<input id="public_key" type="text" value="{{ .Email.SenderPubl }}">
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
function copy() {
|
||||
function copy_public_key() {
|
||||
var copyText = document.getElementById("public_key");
|
||||
copyText.select();
|
||||
document.execCommand("copy");
|
||||
alert('Public key copied');
|
||||
let newInput = `
|
||||
<div class="alert alert-success" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
Public key copied
|
||||
</div>
|
||||
`
|
||||
document.getElementById("message_copy").innerHTML = newInput;
|
||||
}
|
||||
</script>
|
||||
{{ end }}
|
||||
|
||||
@ -3,6 +3,16 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<div>
|
||||
The server stores all received information, including private keys.
|
||||
<br>
|
||||
Be careful when logging in to the global network.
|
||||
</div>
|
||||
</div>
|
||||
<form id="feedbackForm" class="text-center" method="POST" action="/signup">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control bg-dark text-light" name="username" placeholder="Username">
|
||||
@ -14,21 +24,21 @@
|
||||
<input type="password" class="form-control bg-dark text-light" name="password_repeat" placeholder="Repeat Password">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-danger w-100" onclick="hide()">Load private key</button>
|
||||
<button type="button" class="btn btn-danger w-100" onclick="hide_input()">Load private key</button>
|
||||
</div>
|
||||
<div id="input-priv-key" class="form-group"></div>
|
||||
<div id="input_private_key" class="form-group"></div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="submit" value="Create account" id="feedbackSubmit" class="btn btn-success w-100">
|
||||
</div>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
function hide() {
|
||||
let elem = document.getElementById("priv-key");
|
||||
function hide_input() {
|
||||
let elem = document.getElementById("private-key");
|
||||
if (elem) {
|
||||
document.getElementById("priv-key").remove();
|
||||
document.getElementById("private-key").remove();
|
||||
} else {
|
||||
let newInput = "<textarea id='priv-key' class='form-control bg-dark text-light' name='private_key' placeholder='Private key'></textarea>";
|
||||
document.getElementById("input-priv-key").innerHTML = newInput;
|
||||
let newInput = "<textarea id='private-key' class='form-control bg-dark text-light' name='private_key' placeholder='Private key'></textarea>";
|
||||
document.getElementById("input_private_key").innerHTML = newInput;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user