{"action":"opened","issue":{"url":"https://api.github.com/repos/ethereum/go-ethereum/issues/269","labels_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/269/labels{/name}","comments_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/269/comments","events_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/269/events","html_url":"https://github.com/ethereum/go-ethereum/issues/269","id":55148929,"number":269,"title":"crypto.Sign panics for some inputs","user":{"login":"fjl","id":6915,"avatar_url":"https://avatars.githubusercontent.com/u/6915?v=3","gravatar_id":"","url":"https://api.github.com/users/fjl","html_url":"https://github.com/fjl","followers_url":"https://api.github.com/users/fjl/followers","following_url":"https://api.github.com/users/fjl/following{/other_user}","gists_url":"https://api.github.com/users/fjl/gists{/gist_id}","starred_url":"https://api.github.com/users/fjl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fjl/subscriptions","organizations_url":"https://api.github.com/users/fjl/orgs","repos_url":"https://api.github.com/users/fjl/repos","events_url":"https://api.github.com/users/fjl/events{/privacy}","received_events_url":"https://api.github.com/users/fjl/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-01-22T12:44:31Z","updated_at":"2015-01-22T12:44:31Z","closed_at":null,"body":"There are two problems, both of which were introduced [by this change]( https://github.com/obscuren/secp256k1-go/commit/7a58ba75df031897c4cb94bb3b7792959fc06c22#diff-6aebad42932d2e784d6882a9ac024599L106). Note that the change is not mentioned in the commit message.\r\n\r\nOne problem is that package crypto uses `privateKey.D.Bytes()` to marshal the private key. The value returned by `Bytes` will not have length 32 in all cases because `math/big` returns the minimum number of bytes required to hold the number. \r\n\r\n*I think we should pad the key with zeroes.*\r\n\r\nThe other problem is that the message being signed cannot be larger than 32 bytes, because\r\n`nonce` will be accessed with an index > 31.\r\nIf it is smaller than 32 bytes, the remaining bytes of the nonce will be the rest of the private key.\r\n\r\n*The parameter is called `hash` in package crypto. I think we should document that the value\r\nfor this parameter must have length 32*\r\n\r\nCrash:\r\n```text\r\nPanic at i=534.\r\nKey: (len=31) [139 238 11 176 202 152 178 4 145 65 239 166 32 93 76 229 172 233 51 179 54 143 168 210 31 183 235 209 38 188 56]\r\nruntime error: index out of range\r\ngoroutine 1 [running]:\r\nmain.func·001()\r\n\t/Users/fjl/develop/eth/src/github.com/ethereum/go-ethereum/p2p/discover/ktest.go:31 +0x3d2\r\ngithub.com/obscuren/secp256k1-go.Sign(0xc20809deb8, 0x20, 0x20, 0xc20801fc01, 0x1f, 0x1f, 0x0, 0x0, 0x0, 0x0, ...)\r\n\t/Users/fjl/develop/eth/src/github.com/obscuren/secp256k1-go/secp256.go:130 +0x492\r\ngithub.com/ethereum/go-ethereum/crypto.Sign(0xc20809deb8, 0x20, 0x20, 0xc208097770, 0x0, 0x0, 0x0, 0x0, 0x0)\r\n\t/Users/fjl/develop/eth/src/github.com/ethereum/go-ethereum/crypto/crypto.go:108 +0xc0\r\nmain.main()\r\n\t/Users/fjl/develop/eth/src/github.com/ethereum/go-ethereum/p2p/discover/ktest.go:42 +0x306\r\nexit status 1\r\n```\r\n\r\nRepro tool:\r\n```go\r\nimport (\r\n\t\"crypto/ecdsa\"\r\n\t\"crypto/rand\"\r\n\t\"fmt\"\r\n\t\"os\"\r\n\t\"runtime\"\r\n\r\n\t\"github.com/ethereum/go-ethereum/crypto\"\r\n)\r\n\r\nfunc main() {\r\n\tvar (\r\n\t\thash = make([]byte, 32)\r\n\t\tk    *ecdsa.PrivateKey\r\n\t\ti    int\r\n\t\terr  error\r\n\t)\r\n\tdefer func() {\r\n\t\tif err := recover(); err != nil {\r\n\t\t\tfmt.Printf(\"Panic at i=%d.\\n\", i)\r\n\t\t\tif k != nil {\r\n\t\t\t\tenc := k.D.Bytes()\r\n\t\t\t\tfmt.Printf(\"Key: (len=%d) %v\\n\", len(enc), enc)\r\n\t\t\t}\r\n\t\t\tfmt.Println(err)\r\n\t\t\tsb := make([]byte, 1000)\r\n\t\t\tfmt.Print(string(sb[:runtime.Stack(sb, false)]))\r\n\t\t\tos.Exit(1)\r\n\t\t}\r\n\t}()\r\n\r\n\tfor ; i < 10000; i++ {\r\n\t\tk, err = ecdsa.GenerateKey(crypto.S256(), rand.Reader)\r\n\t\tif err != nil {\r\n\t\t\tfmt.Println(\"cannot generate key:\", err)\r\n\t\t\tos.Exit(1)\r\n\t\t}\r\n\t\tcrypto.Sign(hash, k)\r\n\t}\r\n}\r\n```"}}