diff --git a/.DS_Store b/.DS_Store index d0563da..a3dd3bd 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/dist/centos/connector b/dist/centos/connector new file mode 100755 index 0000000..fcc017c Binary files /dev/null and b/dist/centos/connector differ diff --git a/merkle/map.go b/merkle/map.go index 727e45b..bb8e37c 100644 --- a/merkle/map.go +++ b/merkle/map.go @@ -9,18 +9,20 @@ import ( func MapToNodes(rows *sql.Rows) []*Node { var ID int var Val, LVal, RVal string + var Deleted bool var nodes []*Node defer rows.Close() for rows.Next() { - err := rows.Scan(&ID, &Val, &LVal, &RVal) + err := rows.Scan(&ID, &Val, &LVal, &RVal, &Deleted) if err != nil { log.Fatal(err) } nodes = append(nodes, &Node{ - ID: ID, - Val: Val, - LVal: LVal, - RVal: RVal, + ID: ID, + Val: Val, + LVal: LVal, + RVal: RVal, + Deleted: Deleted, }) } return nodes @@ -31,11 +33,11 @@ func (n *Node) Save(s *Store) { var q string var id int if n.ID == 0 { - q = `INSERT INTO nodes (val, l_val, r_val) - VALUES($1, $2, $3) + q = `INSERT INTO nodes (val, l_val, r_val, deleted) + VALUES($1, $2, $3, $4) RETURNING id;` } else { - q = `UPDATE nodes SET val=$2, l_val=$3, r_val=$4 WHERE id = $1;` + q = `UPDATE nodes SET val=$2, l_val=$3, r_val=$4, deleted=$5 WHERE id = $1;` } s.Save(func(tx *sql.Tx) { stmt, err := tx.Prepare(q) @@ -44,13 +46,13 @@ func (n *Node) Save(s *Store) { } defer stmt.Close() if n.ID == 0 { - err = stmt.QueryRow(n.Val, n.LVal, n.RVal).Scan(&id) + err = stmt.QueryRow(n.Val, n.LVal, n.RVal, n.Deleted).Scan(&id) if err != nil { log.Fatal(err) } n.ID = id } else { - _, err := stmt.Exec(n.ID, n.Val, n.LVal, n.RVal) + _, err := stmt.Exec(n.ID, n.Val, n.LVal, n.RVal, n.Deleted) if err != nil { log.Fatal(err) } diff --git a/merkle/node.go b/merkle/node.go index e7fb7a5..6de313b 100644 --- a/merkle/node.go +++ b/merkle/node.go @@ -12,6 +12,7 @@ type Node struct { P, L, R *Node LVal, RVal, Val string Epoch uint + Deleted bool // For DB purposes, probably unnecessary to include ID int } @@ -22,6 +23,10 @@ func (n *Node) HashVal() string { if n.IsLeaf() { return n.Val } + if n.Deleted { + h.Write([]byte("EMPTY NODE")) + return hex.EncodeToString(h.Sum(nil)) + } if len(n.LVal) == 0 && n.L != nil { n.LVal = n.L.HashVal() } diff --git a/merkle/store.go b/merkle/store.go index c1f34ea..9a43817 100644 --- a/merkle/store.go +++ b/merkle/store.go @@ -9,11 +9,12 @@ import ( ) var schema = ` - CREATE TABLE nodes ( + CREATE TABLE IF NOT EXISTS nodes ( id serial primary key, val varchar(64), l_val varchar(64), - r_val varchar(64) + r_val varchar(64), + deleted boolean ); ` diff --git a/merkle/tree.go b/merkle/tree.go index 3931c6b..5057ba7 100644 --- a/merkle/tree.go +++ b/merkle/tree.go @@ -7,6 +7,7 @@ import ( "log" "math" "strconv" + "transparency/merkle" ) // Tree comment @@ -202,13 +203,19 @@ func (t *Tree) AddLeaf(n *Node, s *Store) { return } - leafCount := t.CountLeaves(s) - log.Print("Tree.AddLeaf():leafCount=" + strconv.Itoa(leafCount)) - node := t.Root.RMostEntry(s) - node.ShiftInsert(n, leafCount, s) + var o = merkle.FindNode(store, n.Val) + if o != nil { + o.Deleted = false + n = o + } else { + leafCount := t.CountLeaves(s) + log.Print("Tree.AddLeaf():leafCount=" + strconv.Itoa(leafCount)) + node := t.Root.RMostEntry(s) + node.ShiftInsert(n, leafCount, s) - if t.Root.P != nil { - t.Root = t.Root.P + if t.Root.P != nil { + t.Root = t.Root.P + } } // Recursively rehash beginning with new leaf @@ -218,6 +225,17 @@ func (t *Tree) AddLeaf(n *Node, s *Store) { walkSave(n, s) } +// RemoveLeaf comment +func (t *Tree) RemoveLeaf(n *Node, s *Store) { + n.Deleted = true + + // Recursively rehash beginning with new leaf + walkHash(n, s) + + // Recursively save nodes affected by update + walkSave(n, s) +} + // walkSave comment func walkSave(n *Node, s *Store) { // Save the current node diff --git a/static/js/file_upload.js b/static/js/file_upload.js index 6f44247..5231f8e 100644 --- a/static/js/file_upload.js +++ b/static/js/file_upload.js @@ -1,4 +1,5 @@ function handleFileSelect(evt) { + console.log("handleFileSelect():firing event"); evt.stopPropagation(); evt.preventDefault(); $(".box__error:first").hide(); @@ -11,7 +12,9 @@ function handleFileSelect(evt) { var reader = new FileReader(); reader.onload = function(e) { + console.log("handleFileSelect():result="+e.target.result); var data = new Uint8Array(e.target.result); + console.log("handleFileSelect():data=" + data); verify_file("stanford.edu", data); } reader.readAsArrayBuffer(f); @@ -20,12 +23,14 @@ function handleFileSelect(evt) { } function handleDragOver(evt) { + console.log("handleDragOver()"); evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } function verify_file(origin, data) { + console.log("verify_file()"); var hash = sha256(data); xhr = new XMLHttpRequest(); xhr.onload = function(e) { diff --git a/static/verifier.html b/static/verifier.html index 21bf36a..3449aaf 100644 --- a/static/verifier.html +++ b/static/verifier.html @@ -390,9 +390,9 @@
var reader = new FileReader(); reader.onload = function(e) { + console.log("triggering ") var data = new Uint8Array(e.target.result); - var hash = sha256(data); - verify_file("stanford.edu", hash); + verify_file("stanford.edu", data); } reader.readAsArrayBuffer(f); } diff --git a/transparency.go b/transparency.go index 757eabc..faec0c7 100644 --- a/transparency.go +++ b/transparency.go @@ -38,14 +38,16 @@ func main() { log.Fatalln(err) } store = &merkle.Store{DB: db} + store.AddTables() //pub, priv, err = ed25519.GenerateKey(rand.Reader) - //leaves := loadLeaves() - //addLoadedLeaves(leaves, store) + leaves := loadLeaves() + addLoadedLeaves(leaves, store) fs := http.FileServer(http.Dir("static")) http.HandleFunc("/verify/", verifyReq) http.HandleFunc("/add/", addReq) + http.HandleFunc("/remove/", removeReq) http.HandleFunc("/reset/", resetReq) http.Handle("/", fs) http.ListenAndServe(port, nil) @@ -98,11 +100,11 @@ func addReq(w http.ResponseWriter, r *http.Request) { log.Println(string(requestDump)) // TODO naive authentication, redo this before production-ready - /*if r.Header.Get("X-Access-Token") != authToken { + if r.Header.Get("X-Access-Token") != authToken { log.Println("addReq():failed authentication check") http.Error(w, "Authentication Failed", http.StatusInternalServerError) return - }*/ + } log.Println("addReq():passed authentication") if r.Body == nil { @@ -126,6 +128,43 @@ func addReq(w http.ResponseWriter, r *http.Request) { } } +func removeReq(w http.ResponseWriter, r *http.Request) { + log.Print("addReq():received request to add leaves=") + requestDump, err := httputil.DumpRequest(r, true) + if err != nil { + log.Println(err) + } + log.Println(string(requestDump)) + + // TODO naive authentication, redo this before production-ready + if r.Header.Get("X-Access-Token") != authToken { + log.Println("addReq():failed authentication check") + http.Error(w, "Authentication Failed", http.StatusInternalServerError) + return + } + + log.Println("addReq():passed authentication") + if r.Body == nil { + log.Println("addReq():no body found") + http.Error(w, "Please send a request body", 400) + return + } + var nodes []merkle.Node + err = json.NewDecoder(r.Body).Decode(&nodes) + log.Println(err) + log.Println(nodes) + if err != nil { + log.Fatal(err) + } + tree := &merkle.Tree{Root: merkle.RootEntry(store)} + for _, n := range nodes { + log.Println("addReq():trying to add node with val=" + n.Val) + if merkle.FindNode(store, n.Val) != nil { + tree.RemoveLeaf(&n, store) + } + } +} + // TODO may not want this in the db func resetReq(w http.ResponseWriter, r *http.Request) { if r.Header.Get("X-Access-Token") != authToken { diff --git a/verified/CeD.0000-0000-0000.12345678.JohnDoe.pdf b/verified/CeD.0000-0000-0000.12345678.JohnDoe.pdf new file mode 100644 index 0000000..13dfc4f Binary files /dev/null and b/verified/CeD.0000-0000-0000.12345678.JohnDoe.pdf differ diff --git a/verified/CeD.17A7-037C-B7I3.09637094.12132016.LEAD_Certificate.Corporate_Innovation.pdf b/verified/CeD.17A7-037C-B7I3.09637094.12132016.LEAD_Certificate.Corporate_Innovation.pdf new file mode 100644 index 0000000..04d457a Binary files /dev/null and b/verified/CeD.17A7-037C-B7I3.09637094.12132016.LEAD_Certificate.Corporate_Innovation.pdf differ