Failing to verify ECDSA signature - go

I have a signature:
3044022014d647cd08f1ea5b31d1e6539b6cbceb9182f6e7b2e29fb969354ef7e3434923022028bb4eda36af410149baa936322e7c0e46cc5540a3aa89c811bc3c360028bfd301
a hash
f27c6c3aa42563c958292922be1e53fe107f4db0dfadba11122f0b12bf77f3ab
and a pubkey
04b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b
Below is my Go code to verify the signature but it fails! I have information that the three pieces should validate OK and some other person has verified them in other ways. So I want to kown what mistake in this Go code make me get the false result.
if you want more information,this link is about how i build my signature and how someone say he success verify in other ways. I feel helpless now:
https://bitcointalk.org/index.php?topic=4879014.msg43992837#msg43992837
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
"fmt"
"math/big"
)
func main() {
pubkey, err := hex.DecodeString("b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b")
if err != nil {
panic(err)
}
curve := elliptic.P256()
// length
keyLen := len(pubkey)
x := big.Int{}
y := big.Int{}
x.SetBytes(pubkey[:(keyLen / 2)])
y.SetBytes(pubkey[(keyLen / 2):])
rawPubKey := ecdsa.PublicKey{curve, &x, &y}
// hash
hash, err := hex.DecodeString("f27c6c3aa42563c958292922be1e53fe107f4db0dfadba11122f0b12bf77f3ab")
if err != nil {
panic(err)
}
r := big.Int{}
s := big.Int{}
rr, err := hex.DecodeString("14d647cd08f1ea5b31d1e6539b6cbceb9182f6e7b2e29fb969354ef7e3434923")
if err != nil {
panic(err)
}
ss, err := hex.DecodeString("28bb4eda36af410149baa936322e7c0e46cc5540a3aa89c811bc3c360028bfd3")
if err != nil {
panic(err)
}
r.SetBytes(rr)
s.SetBytes(ss)
fmt.Printf("%v\n", ecdsa.Verify(&rawPubKey, hash[:], &r, &s))
}

You are trying to use the wrong curve. P-256, also known as secp256r1, is not the same as the curve used in Bitcoin, which is secp256k1. Your public key doesn’t correspond to a point on P-256 (you can check with curve.IsOnCurve(&x, &y)), but it is a point on secp256k1.
Golang doesn’t include support for the Bitcoin curve, so you will need to find a library that does ECDSA using it.
I can confirm that signature does verify that data for that key if you use the correct curve.

Related

Golang equivalent of Java's SHA256withRSA

Is there any Golang equivalent of Java's java.security.Signature's SHA256withRSA? A couple of research is that I could not simple calculate the SHA256 hash and then signing it with RSA.
Figured it out if someone stumbled on the same question, here's how it works in Go
func main() {
privateKey := loadPrivateKey()
h := sha256.New()
h.Write([]byte(`your message`))
d := h.Sum(nil)
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, d)
if err != nil {
panic(err)
}
fmt.Printf("Signature in byte: %v\n\n", signature)
encodedSig := base64.StdEncoding.EncodeToString(signature)
fmt.Printf("Encoded signature: %v\n\n", encodedSig)
}

Random 64-bit integer from crypto/rand

I want to generate 64-bit random integer using the secure crypto/rand package. I found this online:
package main
import (
"crypto/rand"
"encoding/base64"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
But it seems to generate random bytes instead. I want a random 64-bit int. Namely, I want something like var i uint64 = rand(). Any ideas how to achieve this?
You can generate a random number with crypto.Rand, and then convert those bytes to an int64 using the binary package:
func randint64() (int64, error) {
var b [8]byte
if _, err := rand.Read(b[:]); err != nil {
return 0, err
}
return int64(binary.LittleEndian.Uint64(b[:])), nil
}
https://play.golang.org/p/2Q8tvttqbJ (result is cached)
If you look at the source code for LittleEndian.Uint64, you can see it's simply performing a few bit operations on the data; something that you could implemented for yourself.
You also use rand.Int in crypto/rand package
func randint64() (int64, error) {
val, err := rand.Int(rand.Reader, big.NewInt(int64(math.MaxInt64)))
if err != nil {
return 0, err
}
return val.Int64(), nil
}
https://play.golang.org/p/fqoQxpmjOSu

How can I generate a random int using the "crypto/rand" package?

Say I would like to generate a secure random int between 0 and 27 using:
func Int(rand io.Reader, max *big.Int) (n *big.Int, err error)
in the "crypto/rand" package.
How would I do that?
I do not really understand how this works, why does it not return one of the built in Go ints instead of pointer to some big.Int type?
EDIT:
Would this be considered secure enough for tokens?
func getToken(length int) string {
token := ""
codeAlphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
codeAlphabet += "abcdefghijklmnopqrstuvwxyz"
codeAlphabet += "0123456789"
for i := 0; i < length; i++ {
token += string(codeAlphabet[cryptoRandSecure(int64(len(codeAlphabet)))])
}
return token
}
func cryptoRandSecure(max int64) int64 {
nBig, err := rand.Int(rand.Reader, big.NewInt(max))
if err != nil {
log.Println(err)
}
return nBig.Int64()
}
func main() {
fmt.Println(getToken(32))
}
This would output something like this:
qZDbuPwNQGrgVmZCU9A7FUWbp8eIfn0Z
EwZVoQ5D5SEfdhiRsDfH6dU6tAovILCZ
cOqzODVP0GwbiNBwtmqLA78rFgV9d3VT
Here is some working code :
package main
import (
"fmt"
"crypto/rand"
"math/big"
)
func main() {
nBig, err := rand.Int(rand.Reader, big.NewInt(27))
if err != nil {
panic(err)
}
n := nBig.Int64()
fmt.Printf("Here is a random %T in [0,27) : %d\n", n, n)
}
But to generate a random token, I'd do something like this :
package main
import (
"crypto/rand"
"encoding/base32"
"fmt"
)
func main() {
token := getToken(10)
fmt.Println("Here is a random token : ", token)
}
func getToken(length int) string {
randomBytes := make([]byte, 32)
_, err := rand.Read(randomBytes)
if err != nil {
panic(err)
}
return base32.StdEncoding.EncodeToString(randomBytes)[:length]
}
If you're generating secure tokens for session IDs, OAuth Bearer tokens, CSRF or similar: you want to generate a token of (ideally) 256 bits (32 bytes) or no less than 192 bits (24 bytes).
A token with values between (0-27) can be brute-forced in less than a second and could not be considered secure.
e.g.
package main
import (
"crypto/rand"
"encoding/base64"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
// GenerateRandomString returns a URL-safe, base64 encoded
// securely generated random string.
func GenerateRandomString(s int) (string, error) {
b, err := GenerateRandomBytes(s)
return base64.URLEncoding.EncodeToString(b), err
}
func main() {
// Example: this will give us a 44 byte, base64 encoded output
token, err := GenerateRandomString(32)
if err != nil {
// Serve an appropriately vague error to the
// user, but log the details internally.
}
}
The base64 output is safe for headers, HTTP forms, JSON bodies, etc.
If you need an integer it may help to explain your use-case, as it would be odd for a system to require tokens as ints.
If you only need a small number (i.e. [0, 255]), you could just read a byte out of the package's Reader:
b := []byte{0}
if _, err := rand.Reader.Read(b); err != nil {
panic(err)
}
n := b[0]
fmt.Println(n)
Playground: http://play.golang.org/p/4VO52LiEVh (the example won't work there, I don't know if it's working as intended or it's a playground bug).

Go: zlib uncompressing a slice of bytes

I am trying to parse a file that annoying consists of many separately zipped segments. I have parsed these segments one at a time into a slice of bytes and I want to uncompress them as I go.
Here is my current code that does the decompressing, which doesn't work. from and to are just set at the top as an example, in reality they are set by the code. data is the byte array containing the entire file. I don't want to seek it while it's on disk because its location on another server, so it's only realistic for me to load the entire file to []byte first and then parse it.
from, to := 0, 1000;
b := bytes.NewReader(data[from:from+to])
z, err := zlib.NewReader(b)
CheckErr(err)
defer z.Close()
p := make([]byte,0,1024)
z.Read(p)
fmt.Println(string(p))
So how is it so massively difficult just to unzip a slice of bytes? Anyway...
The problem appears to with how I am reading it out. Where it says z.Read, that doesn't seem to do anything.
How can I read the entire thing in one go into a slice of bytes?
Here's an outline for you. Note: In Go, CHECK FOR ERRORS!
package main
import (
"bytes"
"compress/zlib"
"fmt"
"io/ioutil"
)
func readSegment(data []byte, from, to int) ([]byte, error) {
b := bytes.NewReader(data[from : from+to])
z, err := zlib.NewReader(b)
if err != nil {
return nil, err
}
defer z.Close()
p, err := ioutil.ReadAll(z)
if err != nil {
return nil, err
}
return p, nil
}
func main() {
from, to := 0, 1000
data := make([]byte, from+to)
// ** parse input segments into data **
p, err := readSegment(data, from, to)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(p))
}
Use ReadAll(r io.Reader) ([]byte, error) from the io/ioutil package.
p, err := ioutil.ReadAll(b)
fmt.Println(string(p))
Read only reads up to the length of the given slice (1024 bytes in your case).
To read in chunks of 1024 bytes:
p := make([]byte,1024)
for {
numBytes, err := l.Read(p)
if err == io.EOF {
// you are done, numBytes might be less than len(p)
break
}
// do what you want with p
}
If you are getting the data from a webserver, you might even do
import (
"net/http"
"io/ioutil"
)
...
resp, errGet := http.Get("http://example.com/somefile")
// do error handling
z, errZ := zlib.NewReader(resp.Body)
// do error handling
resp.Body.Close()
p, err := ioutil.ReadAll(b)
// do error handling
since resp.Body happens to be an io.Reader as most io related types.

equivalent salt and hash in golang

Here's an example of salting and hashing a given password in python.
import scrypt
import os
# Length of salt
PW_SALT_BYTES = 32
# Length of scrypt hash of passwords
PW_HASH_BYTES = 64
# test password
password = "hello"
salt = os.urandom(PW_SALT_BYTES).encode('hex')
# hash(password, salt, N=1 << 14, r=8, p=1, buflen=64)
hashed_password = scrypt.hash(str(password), salt.decode('hex'), buflen=PW_HASH_BYTES).encode('hex')
print(hashed_password)
Which would give us a hashed and salted string in return:-
4d1da45b401961fccb10e094ecd70ec79510f05483ca293d300bbd0024e35866ca39fe09fbc15f83a359431021a1ed9644f7d2b871b357e37a186300877edb18
How would I implement this in golang?
Rather than using scrypt, a great library for securely hashing passwords with random salts in Golang is golang.org/x/crypto/bcrypt, as mentioned in the following answer:
Bcrypt password hashing in Golang (compatible with Node.js)?
A couple benefits of using bcrypt instead of scrypt:
The salt is automatically (and randomly) generated upon hashing a password, so that you don't have to worry about salt generation.
When storing hashed passwords in a database, you no longer have to worry about storing the salt for each password hash as well.
The syntax is simplified for hashing and checking passwords.
The hash produced by bcrypt includes the bcrypt version, cost, salt and cipher, not only the cipher.
Here's an example of using bcrypt taken from the above answer:
package main
import (
"golang.org/x/crypto/bcrypt"
"fmt"
)
func main() {
password := []byte("MyDarkSecret")
// Hashing the password with the default cost of 10
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Println(string(hashedPassword))
// Comparing the password with the hash
err = bcrypt.CompareHashAndPassword(hashedPassword, password)
fmt.Println(err) // nil means it is a match
}
Go doesn't have scrypt in the standard library but there is an "official" implementation in the go.crypto repo.
import (
"crypto/rand"
"fmt"
"io"
"log"
"code.google.com/p/go.crypto/scrypt"
)
const (
PW_SALT_BYTES = 32
PW_HASH_BYTES = 64
password = "hello"
)
func main() {
salt := make([]byte, PW_SALT_BYTES)
_, err := io.ReadFull(rand.Reader, salt)
if err != nil {
log.Fatal(err)
}
hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, PW_HASH_BYTES)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%x\n", hash)
}
It looks like now Go has scrypt in official library. Its subrepository x/crypto among many other crypto functions has an scrypt.
Here is an example of how you can use it:
package main
import (
"golang.org/x/crypto/scrypt"
"fmt"
)
func main(){
salt := []byte("asdfasdf")
dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
fmt.Println(dk)
fmt.Println(err)
}
Here's a complete hashing utilities funcs I wrote based on RFC 2898 / PKCS #5 v2.0.
Hash can be used to hash passwords, straight forward something like Hash("hello")
while Verify can be used to raw password against a hash, basically what it does is to hashes the raw string and compares it with the actual hash.
package common
import (
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"golang.org/x/crypto/pbkdf2"
"io"
"strconv"
"strings"
)
const (
SALT_BYTE_SIZE = 24
HASH_BYTE_SIZE = 24
PBKDF2_ITERATIONS = 1000
)
func Hash(password string) (string, error) {
salt := make([]byte, SALT_BYTE_SIZE)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
fmt.Print("Err generating random salt")
return "", errors.New("Err generating random salt")
}
//todo: enhance: randomize itrs as well
hbts := pbkdf2.Key([]byte(password), salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE, sha1.New)
//hbtstr := fmt.Sprintf("%x", hbts)
return fmt.Sprintf("%v:%v:%v",
PBKDF2_ITERATIONS,
base64.StdEncoding.EncodeToString(salt),
base64.StdEncoding.EncodeToString(hbts)), nil
}
func Verify(raw, hash string) (bool, error) {
hparts := strings.Split(hash, ":")
itr, err := strconv.Atoi(hparts[0])
if err != nil {
fmt.Printf("wrong hash %v", hash)
return false, errors.New("wrong hash, iteration is invalid")
}
salt, err := base64.StdEncoding.DecodeString(hparts[1])
if err != nil {
fmt.Print("wrong hash, salt error:", err)
return false, errors.New("wrong hash, salt error:" + err.Error())
}
hsh, err := base64.StdEncoding.DecodeString(hparts[2])
if err != nil {
fmt.Print("wrong hash, hash error:", err)
return false, errors.New("wrong hash, hash error:" + err.Error())
}
rhash := pbkdf2.Key([]byte(raw), salt, itr, len(hsh), sha1.New)
return equal(rhash, hsh), nil
}
//bytes comparisons
func equal(h1, h2 []byte) bool {
diff := uint32(len(h1)) ^ uint32(len(h2))
for i := 0; i < len(h1) && i < len(h2); i++ {
diff |= uint32(h1[i] ^ h2[i])
}
return diff == 0
}
Here's unit test that would help you figuring out how to call such funcs
package common
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestHash(t *testing.T) {
hash, err := Hash("hello")
assert.Nil(t, err)
assert.NotEmpty(t, hash)
}
func TestVerify(t *testing.T) {
hash, err := Hash("hello")
assert.Nil(t, err)
assert.NotEmpty(t, hash)
ok, err := Verify("hello", hash)
assert.Nil(t, err)
assert.True(t, ok)
}

Resources