-
Notifications
You must be signed in to change notification settings - Fork 0
/
dasmaps_validator.go
149 lines (137 loc) · 3.11 KB
/
dasmaps_validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
// DASTools: dasmaps_validator validates DAS maps
// Copyright (c) 2018 - Valentin Kuznetsov <vkuznet AT gmail dot com>
import (
"bufio"
"crypto/md5"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"runtime"
"time"
)
// Record represents DAS map record
type Record map[string]interface{}
// NOTE: The json package always orders keys when marshalling. Specifically:
// - Maps have their keys sorted lexicographically
// - Structs keys are marshalled in the order defined in the struct
func checkHash(rec Record) bool {
keys := mapKeys(rec)
if inList("hash", keys) {
h := rec["hash"]
// reset hash value to calculate new md5 checksum
rec["hash"] = ""
data, err := json.Marshal(rec)
if err != nil {
log.Fatal(err)
}
rh := fmt.Sprintf("%x", md5.Sum(data))
if rh != h {
fmt.Println(string(data))
fmt.Println("")
fmt.Println(" record type", recordType(rec))
fmt.Println(" record hash", h)
fmt.Println("computed md5", rh)
log.Fatal("Invalid hash")
}
}
return true
}
// inList helper function to check item in a list
func inList(a string, list []string) bool {
check := 0
for _, b := range list {
if b == a {
check += 1
}
}
if check != 0 {
return true
}
return false
}
// mapKeys helper function to return keys from a map
func mapKeys(rec map[string]interface{}) []string {
keys := make([]string, 0, len(rec))
for k := range rec {
keys = append(keys, k)
}
return keys
}
func recordType(rec Record) string {
keys := mapKeys(rec)
if inList("arecord", keys) {
return "arecord"
} else if inList("notations", keys) {
return "notation"
} else if inList("verification_token", keys) {
return "verification"
} else if inList("input_values", keys) {
return "input_values"
} else if inList("presentation", keys) {
return "presentation"
} else if inList("urn", keys) {
return "das"
}
return ""
}
func validateDasmaps(input string, verbose int) {
if verbose > 0 {
fmt.Println("validate dasmaps", input)
}
file, err := os.Open(input)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
jsonBytes := scanner.Bytes()
var rec Record
err := json.Unmarshal(jsonBytes, &rec)
if err != nil {
log.Fatal(err)
}
switch t := recordType(rec); t {
case "das":
checkHash(rec)
case "arecord":
checkHash(rec)
case "notation":
checkHash(rec)
case "verification":
checkHash(rec)
case "presentation":
checkHash(rec)
case "input_values":
checkHash(rec)
default:
r, e := json.Marshal(rec)
if e != nil {
log.Fatal(e)
}
log.Fatal(fmt.Sprintf("unknown record type: %s %s", t, string(r)))
}
}
}
func info() string {
goVersion := runtime.Version()
tstamp := time.Now()
return fmt.Sprintf("git={{VERSION}} go=%s date=%s", goVersion, tstamp)
}
func main() {
var version bool
flag.BoolVar(&version, "version", false, "Show version")
var dasmaps string
flag.StringVar(&dasmaps, "dasmaps", "", "dasmaps file")
var verbose int
flag.IntVar(&verbose, "verbose", 0, "verbosity level")
flag.Parse()
if version {
fmt.Println(info())
return
}
validateDasmaps(dasmaps, verbose)
}