]>
src.bluestatic.org Git - macgdbp.git/blob - dev/signer-ed25519.go
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.
57 keyPath
= flag
.String("key", "", "Path to the key file.")
58 inPath
= flag
.String("file", "", "Path to the file to sign/verify.")
59 sigPath
= flag
.String("signature", "", "Path to the signature file.")
60 doSign
= flag
.Bool("sign", false, "Sign the given file.")
61 doVerify
= flag
.Bool("verify", false, "Verify the given file.")
62 doNewKey
= flag
.Bool("new-key", false, "Generate a new keypair.")
73 if (!*doSign
&& !*doVerify
) ||
(*doSign
&& *doVerify
) {
74 fmt
.Fprintf(os
.Stderr
, "Must specify either -sign or -verify.\n")
78 keyPemData
, err
:= ioutil
.ReadFile(*keyPath
)
80 fmt
.Fprintf(os
.Stderr
, "Failed to read key: %v.\n", err
)
84 keyPem
, _
:= pem
.Decode(keyPemData
)
86 fmt
.Fprintf(os
.Stderr
, "Failed to decode PEM.\n", err
)
100 pub
, priv
, err
:= ed25519
.GenerateKey(nil)
102 fmt
.Fprintf(os
.Stderr
, "Failed to generate new key pair: %v.\n", err
)
106 pemPub
:= &pem
.Block
{Type
: "ED25519 PUBLIC KEY"}
107 pemPriv
:= &pem
.Block
{Type
: "ED25519 PRIVATE KEY"}
109 pemPub
.Bytes
, err
= x509
.MarshalPKIXPublicKey(pub
)
111 fmt
.Fprintf(os
.Stderr
, "Failed to marshal public key: %v.\n", err
)
115 pemPriv
.Bytes
, err
= x509
.MarshalPKCS8PrivateKey(priv
)
117 fmt
.Fprintf(os
.Stderr
, "Failed to marshal private key: %v.\n", err
)
121 if err
:= pem
.Encode(os
.Stdout
, pemPub
); err
!= nil {
122 fmt
.Fprintf(os
.Stderr
, "Failed to write public key: %v.\n", err
)
124 if err
:= pem
.Encode(os
.Stdout
, pemPriv
); err
!= nil {
125 fmt
.Fprintf(os
.Stderr
, "Failed to write private key: %v.\n", err
)
129 func sign(keyPem
*pem
.Block
) {
130 var key ed25519
.PrivateKey
132 // The first version of this tool simply output the raw key bytes into the
133 // PEM. To be compatible with openssl, the tool now uses PKCS8 to encode
135 if keyPem
.Type
== "PRIVATE KEY" {
136 key
= ed25519
.PrivateKey(keyPem
.Bytes
)
137 } else if keyPem
.Type
== "ED25519 PRIVATE KEY" {
138 if derKey
, err
:= x509
.ParsePKCS8PrivateKey(keyPem
.Bytes
); err
== nil {
139 key
= derKey
.(ed25519
.PrivateKey
)
141 fmt
.Fprintf(os
.Stderr
, "Failed to parse private key: %v.\n", err
)
145 fmt
.Fprintf(os
.Stderr
, "Signing expects a private key.\n")
149 signature
, err
:= key
.Sign(nil, readInput(), crypto
.Hash(0))
151 fmt
.Fprintf(os
.Stderr
, "Failed to sign file: %v.\n", err
)
155 if _
, err
:= os
.Stdout
.Write(signature
); err
!= nil {
156 fmt
.Fprintf(os
.Stderr
, "Failed to write output: %v.\n", err
)
161 func verify(keyPem
*pem
.Block
) {
162 var key ed25519
.PublicKey
164 // The first version of this tool simply output the raw key bytes into the
165 // PEM. To be compatible with openssl, the tool now DER-encodes the public
167 if keyPem
.Type
== "PUBLIC KEY" {
168 key
= ed25519
.PublicKey(keyPem
.Bytes
)
169 } else if keyPem
.Type
== "ED25519 PUBLIC KEY" {
170 if derKey
, err
:= x509
.ParsePKIXPublicKey(keyPem
.Bytes
); err
== nil {
171 key
= derKey
.(ed25519
.PublicKey
)
173 fmt
.Fprintf(os
.Stderr
, "Failed to parse public key: %v.\n", err
)
177 fmt
.Fprintf(os
.Stderr
, "Verifying expects a public key.\n")
181 signature
, err
:= ioutil
.ReadFile(*sigPath
)
183 fmt
.Fprintf(os
.Stderr
, "Failed to read signature file: %v.\n", err
)
187 if ed25519
.Verify(key
, readInput(), signature
) {
188 fmt
.Println("Verify OK.")
190 fmt
.Println("Verify FAILED!")
194 func readInput() (fileData
[]byte) {
195 fileData
, err
:= ioutil
.ReadFile(*inPath
)
197 fmt
.Fprintf(os
.Stderr
, "Failed to read input file: %v.\n", err
)