Created
March 31, 2014 20:49
-
-
Save elazarl/9901904 to your computer and use it in GitHub Desktop.
An ECDSA based signature scheme compatible with openssl sha256 -sign/-verify
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A signer/verifier compatible with openssl ecdsa signature scheme | |
// | |
// $ openssl ecparam -name prime256v1 -genkey -noout >ec.pem | |
// $ openssl ec -pubout <ec.pem >ecpub.pem | |
// | |
// and with sha256 verification | |
// | |
// $ echo a|openssl sha256 -sign ec.pem > sig.bin | |
// $ echo a|openssl sha256 -verify ecpub.pem -signature sig.bin | |
// | |
// Usage example: | |
// | |
// $ echo a|go run ecdsa_sign.go -key ec.pem > sig.bin | |
// $ echo a|go run ecdsa_sign.go -key ecpub.pem -verify sig.bin | |
// true | |
// $ echo aa|go run ecdsa_sign.go -key ecpub.pem -verify sig.bin | |
// false | |
package main | |
import ( | |
"crypto/ecdsa" | |
"crypto/rand" | |
"crypto/sha256" | |
"crypto/x509" | |
"encoding/asn1" | |
"encoding/hex" | |
"encoding/pem" | |
"flag" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"math/big" | |
"os" | |
) | |
func orDie(msg string, err error) { | |
if err != nil { | |
fmt.Println(msg+":", err) | |
os.Exit(1) | |
} | |
} | |
type ECSignature struct { | |
R *big.Int | |
S *big.Int | |
} | |
func main() { | |
keyfile := flag.String("key", "", "relevant key (public to verify, private to sign") | |
verify := flag.String("verify", "", "signature file to verify input with") | |
hexOut := flag.Bool("hex", false, "should I output hexadecimal string") | |
flag.Parse() | |
if *keyfile == "" { | |
fmt.Println("Argument key must be provided") | |
os.Exit(1) | |
} | |
pemdata, err := ioutil.ReadFile(*keyfile) | |
orDie("Error reading key "+*keyfile, err) | |
der, _ := pem.Decode(pemdata) | |
h := sha256.New() | |
io.Copy(h, os.Stdin) | |
if *verify == "" { | |
key, err := x509.ParseECPrivateKey(der.Bytes) | |
orDie("Parsing key", err) | |
var sig ECSignature | |
// no need to trim anything, prime256 param has 256 bit, | |
// exactly like sha256 output | |
sig.R, sig.S, err = ecdsa.Sign(rand.Reader, key, h.Sum(nil)) | |
orDie("signing", err) | |
sigBytes, err := asn1.Marshal(sig) | |
orDie("marshal to ASN.1", err) | |
if *hexOut { | |
sigBytes = []byte(hex.EncodeToString(sigBytes) + "\n") | |
} | |
os.Stdout.Write(sigBytes) | |
} else { | |
key, err := x509.ParsePKIXPublicKey(der.Bytes) | |
orDie("Parsing key", err) | |
if _, ok := key.(*ecdsa.PublicKey); !ok { | |
fmt.Printf("Provided key is not an ECDSA key: %T\n", key) | |
os.Exit(1) | |
} | |
sigder, err := ioutil.ReadFile(*verify) | |
orDie("Read signature", err) | |
var sig ECSignature | |
_, err = asn1.Unmarshal(sigder, &sig) | |
orDie("Parsing signature", err) | |
fmt.Println(ecdsa.Verify(key.(*ecdsa.PublicKey), h.Sum(nil), sig.R, sig.S)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment