-
Notifications
You must be signed in to change notification settings - Fork 18k
crypto/elliptic: numsp256t1 fails to verify #50938
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CC @golang/security |
To better exemplify, I made two implementations with standard curves, the conflict also occurs:
|
What verification fails? For what key and message? |
Fails for* verify digital signature, for all kind of messages/files and any key. I implemented both algorithms in the same way, secp128r1 and secp128r2, but the latter doesn't work like in the NUMS example. https://github.com/pedroalbanese/secp128r1 (working) This example works with 9 algorithms from 128 to 512-bit: package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors"
"flag"
"fmt"
"hash"
"io"
"log"
"math/big"
"os"
"github.com/pedroalbanese/secp128r1"
// "github.com/pedroalbanese/secp128r2"
)
var (
derive = flag.Bool("derive", false, "Derive shared secret key.")
keygen = flag.Bool("keygen", false, "Generate keypair.")
key = flag.String("key", "", "Private/Public key.")
public = flag.String("pub", "", "Remote's side Public key.")
sig = flag.String("signature", "", "Signature.")
sign = flag.Bool("sign", false, "Sign with Private key.")
verify = flag.Bool("verify", false, "Verify with Public key.")
)
func main() {
flag.Parse()
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "Usage of", os.Args[0]+":")
flag.PrintDefaults()
os.Exit(2)
}
var privatekey *ecdsa.PrivateKey
var pubkey ecdsa.PublicKey
var pub *ecdsa.PublicKey
var err error
var pubkeyCurve elliptic.Curve
pubkeyCurve = secp128r1.Secp128r1()
// pubkeyCurve = secp128r2.Secp128r2()
if *keygen {
if *key != "" {
privatekey, err = ReadPrivateKeyFromHex(*key)
if err != nil {
log.Fatal(err)
}
} else {
privatekey = new(ecdsa.PrivateKey)
privatekey, err = ecdsa.GenerateKey(pubkeyCurve, rand.Reader)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
pubkey = privatekey.PublicKey
fmt.Println("Private= " + WritePrivateKeyToHex(privatekey))
fmt.Println("Public= " + WritePublicKeyToHex(&pubkey))
os.Exit(0)
}
if *derive {
private, err := ReadPrivateKeyFromHex(*key)
if err != nil {
log.Fatal(err)
}
public, err := ReadPublicKeyFromHex(*public)
if err != nil {
log.Fatal(err)
}
b, _ := public.Curve.ScalarMult(public.X, public.Y, private.D.Bytes())
shared := sha256.Sum256(b.Bytes())
fmt.Printf("Shared= %x\n", shared)
os.Exit(0)
}
if *sign {
var h hash.Hash
h = sha256.New()
if _, err := io.Copy(h, os.Stdin); err != nil {
panic(err)
}
privatekey, err = ReadPrivateKeyFromHex(*key)
if err != nil {
log.Fatal(err)
}
signature, err := Sign(h.Sum(nil), privatekey)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%x\n", signature)
os.Exit(0)
}
if *verify {
var h hash.Hash
h = sha256.New()
if _, err := io.Copy(h, os.Stdin); err != nil {
panic(err)
}
pub, err = ReadPublicKeyFromHex(*key)
if err != nil {
log.Fatal(err)
}
sig, _ := hex.DecodeString(*sig)
verifystatus := Verify(h.Sum(nil), sig, pub)
fmt.Println(verifystatus)
os.Exit(0)
}
}
func Sign(data []byte, privkey *ecdsa.PrivateKey) ([]byte, error) {
digest := sha256.Sum256(data)
r, s, err := ecdsa.Sign(rand.Reader, privkey, digest[:])
if err != nil {
return nil, err
}
params := privkey.Curve.Params()
curveOrderByteSize := params.P.BitLen() / 8
rBytes, sBytes := r.Bytes(), s.Bytes()
signature := make([]byte, curveOrderByteSize*2)
copy(signature[curveOrderByteSize-len(rBytes):], rBytes)
copy(signature[curveOrderByteSize*2-len(sBytes):], sBytes)
return signature, nil
}
func Verify(data, signature []byte, pubkey *ecdsa.PublicKey) bool {
digest := sha256.Sum256(data)
curveOrderByteSize := pubkey.Curve.Params().P.BitLen() / 8
r, s := new(big.Int), new(big.Int)
r.SetBytes(signature[:curveOrderByteSize])
s.SetBytes(signature[curveOrderByteSize:])
return ecdsa.Verify(pubkey, digest[:], r, s)
}
func ReadPrivateKeyFromHex(Dhex string) (*ecdsa.PrivateKey, error) {
c := secp128r1.Secp128r1()
// c := secp128r2.Secp128r2()
d, err := hex.DecodeString(Dhex)
if err != nil {
return nil, err
}
k := new(big.Int).SetBytes(d)
params := c.Params()
one := new(big.Int).SetInt64(1)
n := new(big.Int).Sub(params.N, one)
if k.Cmp(n) >= 0 {
return nil, errors.New("privateKey's D is overflow.")
}
priv := new(ecdsa.PrivateKey)
priv.PublicKey.Curve = c
priv.D = k
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
return priv, nil
}
func WritePrivateKeyToHex(key *ecdsa.PrivateKey) string {
d := key.D.Bytes()
if n := len(d); n < 16 {
d = append(zeroByteSlice()[:32-n], d...)
}
c := []byte{}
c = append(c, d...)
return hex.EncodeToString(c)
}
func ReadPublicKeyFromHex(Qhex string) (*ecdsa.PublicKey, error) {
q, err := hex.DecodeString(Qhex)
if err != nil {
return nil, err
}
if len(q) == 33 && q[0] == byte(0x04) {
q = q[1:]
}
if len(q) != 32 {
return nil, errors.New("publicKey is not uncompressed.")
}
pub := new(ecdsa.PublicKey)
pub.Curve = secp128r1.Secp128r1()
// pub.Curve = secp128r2.Secp128r2()
pub.X = new(big.Int).SetBytes(q[:16])
pub.Y = new(big.Int).SetBytes(q[16:])
return pub, nil
}
func WritePublicKeyToHex(key *ecdsa.PublicKey) string {
x := key.X.Bytes()
y := key.Y.Bytes()
if n := len(x); n < 16 {
x = append(zeroByteSlice()[:16-n], x...)
}
if n := len(y); n < 16 {
y = append(zeroByteSlice()[:16-n], y...)
}
c := []byte{}
c = append(c, x...)
c = append(c, y...)
c = append([]byte{0x04}, c...)
return hex.EncodeToString(c)
}
func zeroByteSlice() []byte {
return []byte{
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
}
} When I change the library to secp128r2, numsp256/512t1 it fails, but works fine with numsp256/512d1. The DH function always works, but the verification function always fails. $ ./secp128r1 -keygen
$ ./secp128r1 -sign -key $privatekey < main.go
$ ./secp128r1 -verify -key $publickey -signature $sign < main.go Theoretically it should work with both curves just changing the library. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Digital signature with NUMS256t1, as is possible with NUMS256d1:
As:
I need to do the same with numsp256t1 (http://www.watersprings.org/pub/id/draft-black-numscurves-01.html):
I
What did you expect to see?
verify = true
What did you see instead?
verify is always false for signature and verification, but works for ECDH. Sry bad English.
The text was updated successfully, but these errors were encountered: