3 * Copyright (c) 2019, Blue Static <https://www.bluestatic.org>
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 signer-ed25519 provides a sign/verify interface for ED25519 operations.
20 Until https://github.com/openssl/openssl/issues/6988 is fixed, OpenSSL cannot
21 be used to generate and verify signatures of files using ED25519 keys. Sparkle
22 only supports ED25519 keys, so this tool is used to bridge the gap.
26 Create a new key pair:
28 ./signer-ed25519 -new-key
32 ./signer-ed25519 -sign -key privkey.pem -file file.zip | openssl enc -a -A
36 ./signer-ed25519 -verify -signature <(openssl enc -d -a sig.b64) -key pubkey.pem -file file.zip
40 - Encrypted private keys are not supported as no password input is provided.
56 keyPath = flag.String("key", "", "Path to the key file.")
57 inPath = flag.String("file", "", "Path to the file to sign/verify.")
58 sigPath = flag.String("signature", "", "Path to the signature file.")
59 doSign = flag.Bool("sign", false, "Sign the given file.")
60 doVerify = flag.Bool("verify", false, "Verify the given file.")
61 doNewKey = flag.Bool("new-key", false, "Generate a new keypair.")
72 if (!*doSign && !*doVerify) || (*doSign && *doVerify) {
73 fmt.Fprintf(os.Stderr, "Must specify either -sign or -verify.\n")
77 keyPemData, err := ioutil.ReadFile(*keyPath)
79 fmt.Fprintf(os.Stderr, "Failed to read key: %v.\n", err)
83 keyPem, _ := pem.Decode(keyPemData)
85 fmt.Fprintf(os.Stderr, "Failed to decode PEM.\n", err)
99 pub := &pem.Block{Type: "PUBLIC KEY"}
100 priv := &pem.Block{Type: "PRIVATE KEY"}
102 pub.Bytes, priv.Bytes, err = ed25519.GenerateKey(nil)
104 fmt.Fprintf(os.Stderr, "Failed to generate new key pair: %v.\n", err)
108 if err := pem.Encode(os.Stdout, pub); err != nil {
109 fmt.Fprintf(os.Stderr, "Failed to write public key: %v.\n", err)
111 if err := pem.Encode(os.Stdout, priv); err != nil {
112 fmt.Fprintf(os.Stderr, "Failed to write private key: %v.\n", err)
116 func sign(keyPem *pem.Block) {
117 if keyPem.Type != "PRIVATE KEY" {
118 fmt.Fprintf(os.Stderr, "Signing expects a private key.\n")
122 key := ed25519.PrivateKey(keyPem.Bytes)
124 signature, err := key.Sign(nil, readInput(), crypto.Hash(0))
126 fmt.Fprintf(os.Stderr, "Failed to sign file: %v.\n", err)
130 if _, err := os.Stdout.Write(signature); err != nil {
131 fmt.Fprintf(os.Stderr, "Failed to write output: %v.\n", err)
136 func verify(keyPem *pem.Block) {
137 if keyPem.Type != "PUBLIC KEY" {
138 fmt.Fprintf(os.Stderr, "Verifying expects a public key.\n")
142 key := ed25519.PublicKey(keyPem.Bytes)
144 signature, err := ioutil.ReadFile(*sigPath)
146 fmt.Fprintf(os.Stderr, "Failed to read signature file: %v.\n", err)
150 if ed25519.Verify(key, readInput(), signature) {
151 fmt.Println("Verify OK.")
153 fmt.Println("Verify FAILED!")
157 func readInput() (fileData []byte) {
158 fileData, err := ioutil.ReadFile(*inPath)
160 fmt.Fprintf(os.Stderr, "Failed to read input file: %v.\n", err)