aboutsummaryrefslogtreecommitdiff
path: root/core/verification.go
blob: b48c0b749a3ccab31f45a17b8a47e4f10767c53b (plain) (blame)
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 core

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/axtloss/fsverify/config"
	"github.com/jedisct1/go-minisign"
	"github.com/tarm/serial"
)

func fileReadKey() (string, error) {
	if _, err := os.Stat(config.KeyLocation); os.IsNotExist(err) {
		return "", fmt.Errorf("Key location %s does not exist", config.KeyLocation)
	}
	file, err := os.Open(config.KeyLocation)
	if err != nil {
		return "", err
	}
	defer file.Close()
	key := make([]byte, 56)
	reader := bufio.NewReader(file)
	n, err := reader.Read(key)
	if n != 56 {
		return "", fmt.Errorf("Error: Key does not match expected key size. expected 56, got %d", n)
	}
	if err != nil {
		return "", err
	}
	return string(key), nil
}

func serialReadKey() (string, error) {
	if _, err := os.Stat(config.KeyLocation); !os.IsNotExist(err) {
		fmt.Println("Reconnect arduino now")
		for true {
			if _, err := os.Stat(config.KeyLocation); os.IsNotExist(err) {
				break
			}
		}
	} else {
		fmt.Println("Connect arduino now")
	}
	for true {
		if _, err := os.Stat(config.KeyLocation); !os.IsNotExist(err) {
			break
		}
	}
	fmt.Println("Arduino connected")
	c := &serial.Config{Name: config.KeyLocation, Baud: 9600}
	s, err := serial.OpenPort(c)
	if err != nil {
		return "", err
	}

	key := ""
	for true {
		buf := make([]byte, 128)
		n, err := s.Read(buf)
		if err != nil {
			return "", err
		}
		defer s.Close()
		key = key + fmt.Sprintf("%q", buf[:n])
		if strings.Count(key, "\\t") == 2 {
			break
		}
	}
	key = strings.ReplaceAll(key, "\\t", "")
	key = strings.ReplaceAll(key, "\"", "")
	if len(key) != 56 {
		return "", fmt.Errorf("Error: Key does not match expected key size. expected 56, got %d", len(key))
	}
	return key, nil
}

func ReadKey() (string, error) {
	switch config.KeyStore {
	case 0:
		return fileReadKey()
	case 1:
		return fileReadKey()
	case 2:
		return "", nil
	case 3:
		return serialReadKey()
	}
	return "", nil
}

func ReadBlock(node Node, part *bufio.Reader) ([]byte, error) {
	block := make([]byte, node.BlockEnd-node.BlockStart)
	blockSize := node.BlockEnd - node.BlockStart
	_, err := part.Discard(node.BlockStart)
	if err != nil {
		return []byte{}, err
	}
	block, err = part.Peek(blockSize)
	return block, err
}

func VerifySignature(key string, signature string, database string) error {
	pk, err := minisign.NewPublicKey(key)
	if err != nil {
		return err
	}

	sig, err := minisign.DecodeSignature(signature)
	if err != nil {
		return err
	}

	data, err := os.ReadFile(database)
	if err != nil {
		return err
	}

	verified, err := pk.Verify(data, sig)
	if err != nil || !verified {
		return err
	}

	return nil
}

func VerifyBlock(block []byte, node Node) error {
	calculatedBlockHash, err := CalculateBlockHash(block)
	if err != nil {
		return err
	}
	wantedBlockHash := node.BlockSum
	if strings.Compare(calculatedBlockHash, strings.TrimSpace(wantedBlockHash)) == 0 {
		return nil
	}
	return fmt.Errorf("Error: Node %s ranging from %d to %d does not match block", node.PrevNodeSum, node.BlockStart, node.BlockEnd)
}

func VerifyNode(node Node, nextNode Node) error {
	nodeHash, err := calculateStringHash(fmt.Sprintf("%d%d%s%s", node.BlockStart, node.BlockEnd, node.BlockSum, node.PrevNodeSum))
	if err != nil {
		return err
	}
	if strings.Compare(nodeHash, nextNode.PrevNodeSum) != 0 {
		return fmt.Errorf("Node %s is not valid!", node.PrevNodeSum)
	}
	return nil
}