summaryrefslogtreecommitdiffstats
path: root/cmd/stsigtool/main.go
blob: 021de6365e4e26a27fbb09d113a24fabadf899d6 (plain)
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
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

package main

import (
	"flag"
	"io"
	"log"
	"os"

	"github.com/syncthing/syncthing/lib/signature"
	"github.com/syncthing/syncthing/lib/upgrade"
	_ "go.uber.org/automaxprocs"
)

func main() {
	log.SetFlags(0)
	log.SetOutput(os.Stdout)

	flag.Parse()

	if flag.NArg() < 1 {
		log.Print(`Usage:
	stsigtool <command>

Where command is one of:

	gen
		- generate a new key pair

	sign <privkeyfile> [datafile]
		- sign a file

	verify <signaturefile> <datafile>
		- verify a signature, using the built in public key

	verify <signaturefile> <datafile> <pubkeyfile>
		- verify a signature, using the specified public key file

`)
	}

	switch flag.Arg(0) {
	case "gen":
		gen()
	case "sign":
		sign(flag.Arg(1), flag.Arg(2))
	case "verify":
		if flag.NArg() == 4 {
			verifyWithFile(flag.Arg(1), flag.Arg(2), flag.Arg(3))
		} else {
			verifyWithKey(flag.Arg(1), flag.Arg(2), upgrade.SigningKey)
		}
	}
}

func gen() {
	priv, pub, err := signature.GenerateKeys()
	if err != nil {
		log.Fatal(err)
	}

	os.Stdout.Write(priv)
	os.Stdout.Write(pub)
}

func sign(keyname, dataname string) {
	privkey, err := os.ReadFile(keyname)
	if err != nil {
		log.Fatal(err)
	}

	var input io.Reader
	if dataname == "-" || dataname == "" {
		input = os.Stdin
	} else {
		fd, err := os.Open(dataname)
		if err != nil {
			log.Fatal(err)
		}
		defer fd.Close()
		input = fd
	}

	sig, err := signature.Sign(privkey, input)
	if err != nil {
		log.Fatal(err)
	}

	os.Stdout.Write(sig)
}

func verifyWithFile(signame, dataname, keyname string) {
	pubkey, err := os.ReadFile(keyname)
	if err != nil {
		log.Fatal(err)
	}
	verifyWithKey(signame, dataname, pubkey)
}

func verifyWithKey(signame, dataname string, pubkey []byte) {
	sig, err := os.ReadFile(signame)
	if err != nil {
		log.Fatal(err)
	}

	fd, err := os.Open(dataname)
	if err != nil {
		log.Fatal(err)
	}
	defer fd.Close()

	err = signature.Verify(pubkey, sig, fd)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("correct signature")
}