Skip to content

crypto/elliptic: unexpected P256.ScalarMult result #26020

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

Closed
cdz620 opened this issue Jun 23, 2018 · 5 comments
Closed

crypto/elliptic: unexpected P256.ScalarMult result #26020

cdz620 opened this issue Jun 23, 2018 · 5 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@cdz620
Copy link

cdz620 commented Jun 23, 2018

Please answer these questions before submitting your issue. Thanks!

What did you do?

A link on play.golang.org is https://play.golang.org/p/prLYofpthWy

package main

import (
	"encoding/pem"
	"crypto/x509"
	"crypto/ecdsa"
	"fmt"
	"encoding/base64"
)

var cliPubBytes = []byte(`-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJr/X/vpUoAlJ5RBMW9m4bI13RkXI
Jx5CUsYPk+JC1EANHkeH5lpEeY1uxIJ8WEDyfgy6YVfPJri93X9KEQixng==
-----END PUBLIC KEY-----`)

var cliPriBytes = []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEsKvptgL3Lg/u059YkRdshoev3XskrciFjjhqu6z8OEoAoGCCqGSM49
AwEHoUQDQgAEJr/X/vpUoAlJ5RBMW9m4bI13RkXIJx5CUsYPk+JC1EANHkeH5lpE
eY1uxIJ8WEDyfgy6YVfPJri93X9KEQixng==
-----END EC PRIVATE KEY-----`)

var serPriBytes = []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEII7BB2KdPVOppd5X8O2tB6MSNoSk25PX2fvSOmHkP2fUoAoGCCqGSM49
AwEHoUQDQgAEdDndAOfQ8aYEK7JECZ0+a0J9aWHjS9FyV+i68qE4zCOdGWN6Q7td
zjPkK5LvNusUCFbv6nLKlk1j8t2Hrc+3lw==
-----END EC PRIVATE KEY-----`)

func main() {

	// pem --> der
	block, _ := pem.Decode(serPriBytes)
	if block == nil {
		panic("invalid private key")
	}
	// parse der
	serPriKey, err := x509.ParseECPrivateKey(block.Bytes)
	if err != nil {
		panic(err)
	}

	block, _ = pem.Decode(cliPubBytes)
	if block == nil {
		panic("invalid public key")
	}
	tp, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		panic(err)
	}

	cliPubkey := tp.(*ecdsa.PublicKey)

	shareKey, _ := serPriKey.Curve.ScalarMult(cliPubkey.X, cliPubkey.Y, serPriKey.D.Bytes())

	fmt.Println(string(base64.StdEncoding.EncodeToString(shareKey.Bytes())))
}

What did you expect to see?

The shared key expected is ACjIKHvl1FAT1zAEQ882cmRQjT75GoLk6MpGHsiDqno=

What did you see instead?

The actual shared key is KMgoe+XUUBPXMARDzzZyZFCNPvkaguToykYeyIOqeg==

Trying to use openssl cmd tool and python to generate shared key

This different shared key case rarely happens. I am sure cliPubBytes and serPriBytes in this case is validated. I used go bench to test ScalarMult's performance and I found the issue. I don't know how to slove it. Hope to get help.

System details

go version go1.10.2 darwin/amd64
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/ivan/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/ivan/code/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.10.2/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.10.2/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/g9/r_m_97ts62z3f1vt2xs_bltm0000gn/T/go-build941244241=/tmp/go-build -gno-record-gcc-switches -fno-common"
GOROOT/bin/go version: go version go1.10.2 darwin/amd64
GOROOT/bin/go tool compile -V: compile version go1.10.2
uname -v: Darwin Kernel Version 17.5.0: Mon Mar  5 22:24:32 PST 2018; root:xnu-4570.51.1~1/RELEASE_X86_64
ProductName:	Mac OS X
ProductVersion:	10.13.4
BuildVersion:	17E199
lldb --version: lldb-902.0.79.2
  Swift-4.1
@ianlancetaylor ianlancetaylor changed the title The shared key generated by P256.ScalarMult is different from that generated by openssl cmd line tool (or python cryptography) encoding/pem: shared key generated by P256.ScalarMult is different from that generated by openssl cmd line tool (or python cryptography) Jun 23, 2018
@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jun 23, 2018
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Jun 23, 2018
@ianlancetaylor
Copy link
Member

CC @FiloSottile

@odeke-em
Copy link
Member

/cc @agl too

@FiloSottile FiloSottile changed the title encoding/pem: shared key generated by P256.ScalarMult is different from that generated by openssl cmd line tool (or python cryptography) crypto/elliptic: unexpected P256.ScalarMult result Jun 26, 2018
@conradoplg
Copy link
Contributor

These are the same values, but the one generated by OpenSSL has a leading zero:

$ echo ACjIKHvl1FAT1zAEQ882cmRQjT75GoLk6MpGHsiDqno= | base64 -d | xxd -p -c 256
0028c8287be5d45013d7300443cf367264508d3ef91a82e4e8ca461ec883aa7a
$ echo KMgoe+XUUBPXMARDzzZyZFCNPvkaguToykYeyIOqeg== | base64 -d | xxd -p -c 256
28c8287be5d45013d7300443cf367264508d3ef91a82e4e8ca461ec883aa7a

This is because the .Bytes() method in the Go code strips any leading zeros. If you need the same byte string, you'll need to left-pad it with something like

	shareKeyBytes := shareKey.Bytes()
	for len(shareKeyBytes) < len(cliPubkey.Curve.Params().N.Bytes()) {
		shareKeyBytes = append([]byte{0}, shareKeyBytes...)
	}

@FiloSottile
Copy link
Contributor

Thanks @conradoplg, that's right. This is a common annoying corner of big.Int, but unfortunately part of the API.

@cdz620
Copy link
Author

cdz620 commented Jul 13, 2018

Thank all. It helps me a lot.

@golang golang locked and limited conversation to collaborators Jul 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

6 participants