forked from input-output-hk/vit-kedqr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
145 lines (124 loc) · 4.19 KB
/
main.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
//$(which go) run $0 $@; exit $?
package main
import (
"encoding/hex"
"flag"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/input-output-hk/vit-kedqr/internal/bech32"
"github.com/input-output-hk/vit-kedqr/internal/ked"
"github.com/skip2/go-qrcode"
)
const (
PIN_LENGTH = 4 // 4-digit numer
KEY_HRP = "ed25519e_sk" // bech32 hrp of ed25519extended secret key
KEY_LENGTH = 64 // bytes of ed25519extended secret key
)
func main() {
var (
input = flag.String("input", "", "path to file containing ed25519extended bech32 value")
output = flag.String("output", "", "path to file to save qr code output, if not provided console output will be attempted")
pin = flag.String("pin", "", "Pin code. 4-digit number is used on Catalyst")
)
flag.Parse()
/* PIN/PASSWORD check */
password := []byte(strings.TrimSpace(*pin))
if len(password) != PIN_LENGTH {
fmt.Fprintf(os.Stderr, "%s: needs %d digits, but %d provided\n", "pin", PIN_LENGTH, len(password))
os.Exit(1)
}
// convert pin/password digits from string to int value
for i := range password {
s := string(password[i])
d, err := strconv.Atoi(s)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: needs %d digits, but non digits detected\n", "pin", PIN_LENGTH)
os.Exit(1)
}
password[i] = byte(d)
}
/* OUTPUT checks */
*output = strings.TrimSpace(*output)
/* INPUT checks */
*input = strings.TrimSpace(*input)
if *input == "" {
fmt.Fprintf(os.Stderr, "flag needs an argument: -%s\n", "input")
os.Exit(1)
}
// read input file data
fileData, err := ioutil.ReadFile(*input)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error reading file %s - [%v]\n", "input", *input, err.Error())
os.Exit(1)
}
// convert file data to string
inputData := strings.TrimSpace(string(fileData))
// bech32 decoding and convert to base256 (from base32)
hrp, data, err := bech32.DecodeAndConvert(inputData)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error %s\n", "bech32.DecodeAndConvert", err.Error())
os.Exit(1)
}
// check hrp and key length expectations
switch {
case hrp != KEY_HRP:
fmt.Fprintf(os.Stderr, "%s: error, expected %s, got %s\n", "HRP", KEY_HRP, hrp)
os.Exit(1)
case len(data) != KEY_LENGTH:
fmt.Fprintf(os.Stderr, "%s: error, expected length %d, got %d\n", "KEY", KEY_LENGTH, len(data))
os.Exit(1)
}
// encrypt the data
encData, err := ked.Encrypt(password, data)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "ked.Encrypt", err.Error())
os.Exit(1)
}
// Prepare the qr code with hex encoded data
qrData := hex.EncodeToString(encData)
qrc, err := qrcode.New(qrData, qrcode.Medium)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "qrcode.New", err.Error())
os.Exit(1)
}
// write to output file if provided
if *output != "" {
err = qrc.WriteFile(256, *output)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "qrc.WriteFile", err.Error())
fmt.Printf("\n%s\n", qrc.ToSmallString(false)) // output to console if write to file fails
}
} else {
fmt.Printf("\n%s\n", qrc.ToSmallString(false)) // output to console in no output provided
}
/***** we are done and all the data are outputed *****/
/*********************************************************************/
/* Perform some reverse checks, encoded data -> original bech32, jic */
/*********************************************************************/
// read hex string data used to build the qr code
qrEncData, err := hex.DecodeString(qrData)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "hex.DecodeString", err.Error())
os.Exit(1)
}
// decrypt the data
qrDecData, err := ked.Decrypt(password, qrEncData)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "ked.Decrypt", err.Error())
os.Exit(1)
}
// convert to bech32
qrInputData, err := bech32.ConvertAndEncode(KEY_HRP, qrDecData)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error, %s\n", "bech32.ConvertAndEncode", err.Error())
os.Exit(1)
}
// check if the original bech32 ed25519extended key matches the decrypted output
if inputData != qrInputData {
fmt.Fprintf(os.Stderr, "Encryption - Decryption checks resulted in missmatch error. The outputs may be corrupted/wrong\n")
os.Exit(1)
}
}