/* * MacGDBp * Copyright (c) 2019, Blue Static * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /* signer-ed25519 provides a sign/verify interface for ED25519 operations. Until https://github.com/openssl/openssl/issues/6988 is fixed, OpenSSL cannot be used to generate and verify signatures of files using ED25519 keys. Sparkle only supports ED25519 keys, so this tool is used to bridge the gap. Usage: Create a new key pair: ./signer-ed25519 -new-key Get base64 signature: ./signer-ed25519 -sign -key privkey.pem -file file.zip | openssl enc -a -A Verify signature: ./signer-ed25519 -verify -signature <(openssl enc -d -a sig.b64) -key pubkey.pem -file file.zip Usage Notes: - Encrypted private keys are not supported as no password input is provided. */ package main import ( "crypto" "crypto/ed25519" "encoding/pem" "flag" "fmt" "io/ioutil" "os" ) var ( keyPath = flag.String("key", "", "Path to the key file.") inPath = flag.String("file", "", "Path to the file to sign/verify.") sigPath = flag.String("signature", "", "Path to the signature file.") doSign = flag.Bool("sign", false, "Sign the given file.") doVerify = flag.Bool("verify", false, "Verify the given file.") doNewKey = flag.Bool("new-key", false, "Generate a new keypair.") ) func main() { flag.Parse() if *doNewKey { newKey() os.Exit(0) } if (!*doSign && !*doVerify) || (*doSign && *doVerify) { fmt.Fprintf(os.Stderr, "Must specify either -sign or -verify.\n") os.Exit(1) } keyPemData, err := ioutil.ReadFile(*keyPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read key: %v.\n", err) os.Exit(1) } keyPem, _ := pem.Decode(keyPemData) if keyPem == nil { fmt.Fprintf(os.Stderr, "Failed to decode PEM.\n", err) os.Exit(1) } if *doSign { sign(keyPem) } if *doVerify { verify(keyPem) } } func newKey() { pub := &pem.Block{Type: "PUBLIC KEY"} priv := &pem.Block{Type: "PRIVATE KEY"} var err error pub.Bytes, priv.Bytes, err = ed25519.GenerateKey(nil) if err != nil { fmt.Fprintf(os.Stderr, "Failed to generate new key pair: %v.\n", err) os.Exit(1) } if err := pem.Encode(os.Stdout, pub); err != nil { fmt.Fprintf(os.Stderr, "Failed to write public key: %v.\n", err) } if err := pem.Encode(os.Stdout, priv); err != nil { fmt.Fprintf(os.Stderr, "Failed to write private key: %v.\n", err) } } func sign(keyPem *pem.Block) { if keyPem.Type != "PRIVATE KEY" { fmt.Fprintf(os.Stderr, "Signing expects a private key.\n") os.Exit(1) } key := ed25519.PrivateKey(keyPem.Bytes) signature, err := key.Sign(nil, readInput(), crypto.Hash(0)) if err != nil { fmt.Fprintf(os.Stderr, "Failed to sign file: %v.\n", err) os.Exit(1) } if _, err := os.Stdout.Write(signature); err != nil { fmt.Fprintf(os.Stderr, "Failed to write output: %v.\n", err) os.Exit(1) } } func verify(keyPem *pem.Block) { if keyPem.Type != "PUBLIC KEY" { fmt.Fprintf(os.Stderr, "Verifying expects a public key.\n") os.Exit(1) } key := ed25519.PublicKey(keyPem.Bytes) signature, err := ioutil.ReadFile(*sigPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read signature file: %v.\n", err) os.Exit(1) } if ed25519.Verify(key, readInput(), signature) { fmt.Println("Verify OK.") } else { fmt.Println("Verify FAILED!") } } func readInput() (fileData []byte) { fileData, err := ioutil.ReadFile(*inPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read input file: %v.\n", err) os.Exit(1) } return }