How to generate the ECDSA public key from its private key? - go

The following site is frequently referenced and, I assume, accurate:
https://gobittest.appspot.com/Address
I'm trying to repro these steps in Golang but failing at the first step :-(
Is someone able to provide me with a Golang snippet that, given a ECDSA private key, returns the public key? I think I may specifically mean the private key exponent and public key exponent per the above site's examples.
i.e. given e.g. a randomly-generated (hex-encoded) private key (exponent?) E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75 returns the public key 04369D83469A66920F31E4CF3BD92CB0BC20C6E88CE010DFA43E5F08BC49D11DA87970D4703B3ADBC9A140B4AD03A0797A6DE2D377C80C369FE76A0F45A7A39D3F
I've found many (relevant) results:
https://crypto.stackexchange.com/questions/5756/how-to-generate-a-public-key-from-a-private-ecdsa-key
But none that includes a definitive example.
Go's crypto/ecdsa module allows keys to generated and includes a Public function on the type but this returns the PublicKey property.
Alternative ways that start from a private key appear to require going through a PEM-encoded (including a DER-encoded ASN) form of the key which feels circuitous (and I would need to construct).
Update:
See the answers below: andrew-w-phillips# and kelsnare# provided the (same|correct) solution. Thanks to both of them!
For posterity, Bitcoin (and Ethereum) use an elliptic curve defined by secp256k1. The following code from andrew-w-phillips# and kelsnare# using Ethereum's implementation of this curve, works:
import (
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
)
func Public(privateKey string) (publicKey string) {
var e ecdsa.PrivateKey
e.D, _ = new(big.Int).SetString(privateKey, 16)
e.PublicKey.Curve = secp256k1.S256()
e.PublicKey.X, e.PublicKey.Y = e.PublicKey.Curve.ScalarBaseMult(e.D.Bytes())
return fmt.Sprintf("%x", elliptic.Marshal(secp256k1.S256(), e.X, e.Y))
}
func main() {
privateKey := "E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75"
log.Println(strings.ToUpper(Public(privateKey)))
}
yields:
04369D83469A66920F31E4CF3BD92CB0BC20C6E88CE010DFA43E5F08BC49D11DA87970D4703B3ADBC9A140B4AD03A0797A6DE2D377C80C369FE76A0F45A7A39D3F

After reading the answer by Andrew W. Phillips and a little help from https://github.com/bitherhq/go-bither/tree/release/1.7/crypto
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"log"
"math/big"
)
func PubBytes(pub *ecdsa.PublicKey) []byte {
if pub == nil || pub.X == nil || pub.Y == nil {
return nil
}
return elliptic.Marshal(elliptic.P256(), pub.X, pub.Y)
}
func toECDSAFromHex(hexString string) (*ecdsa.PrivateKey, error) {
pk := new(ecdsa.PrivateKey)
pk.D, _ = new(big.Int).SetString(hexString, 16)
pk.PublicKey.Curve = elliptic.P256()
pk.PublicKey.X, pk.PublicKey.Y = pk.PublicKey.Curve.ScalarBaseMult(pk.D.Bytes())
return pk, nil
}
func main() {
pHex := "E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75"
pk, err := toECDSAFromHex(pHex)
if err != nil {
log.Fatal(err.Error())
}
fmt.Printf("Generated Public Key: %x\n", PubBytes(&pk.PublicKey))
hash := []byte("Hello Gopher!")
fmt.Printf("\nSigning...\n\n")
r, s, err := ecdsa.Sign(rand.Reader, pk, hash)
if err != nil {
log.Fatal(err.Error())
}
fmt.Printf("\nVerifying..\n\n")
if ecdsa.Verify(&pk.PublicKey, hash, r, s) {
fmt.Println("Success!!")
} else {
fmt.Println("Failure!!")
}
}
// Output
// Generated Public Key: 04265a5015c0cfd960e5a41f35e0a87874c1d8a28289d0d6ef6ac521ad49c3d80a8a7019ceef189819f066a947ad5726db1a4fe70a3208954c46b0e60f2bf7809c
//
// Signing...
//
//
// Verifying..
//
// Success!!
======== ORIGINAL ANSWER ===========
Dunno much of crypto but crypto/elliptic has a Marshal function
So once you have a *PrivateKey maybe the below will work
import (
"crypto/elliptic"
"crypto/ecdsa"
)
var privKey *ecdsa.PrivateKey
func main() {
// some init to privKey
pk := privKey.PublicKey()
keybuf := elliptic.Marshal(pk.Curve, pk.X, pk.Y)
log.Printf("Key: %s\n", string(keybuf))
}
I'm shooting completely in the dark with this. Hope it helps

I haven't got that low-level but maybe something like this:
var pri ecdsa.PrivateKey
pri.D, _ = new(big.Int).SetString("E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75",16)
pri.PublicKey.Curve = elliptic.P256()
pri.PublicKey.X, pri.PublicKey.Y = pri.PublicKey.Curve.ScalarBaseMult(pri.D.Bytes())

Related

How to validate API key with function in Martini?

So I currently have a function that will take in a string APIKey to check it against my Mongo collection. If nothing is found (not authenticated), it returns false - if a user is found, it returns true. My problem, however, is I'm unsure how to integrate this with a Martini POST route. Here is my code:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/go-martini/martini"
_ "github.com/joho/godotenv/autoload"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
Name string
APIKey string
}
func validateAPIKey(users *mongo.Collection, APIKey string) bool {
var user User
filter := bson.D{{"APIKey", APIKey}}
if err := users.FindOne(context.TODO(), filter).Decode(&user); err != nil {
fmt.Printf("Found 0 results for API Key: %s\n", APIKey)
return false
}
fmt.Printf("Found: %s\n", user.Name)
return true
}
func uploadHandler() {
}
func main() {
mongoURI := os.Getenv("MONGO_URI")
mongoOptions := options.Client().ApplyURI(mongoURI)
client, _ := mongo.Connect(context.TODO(), mongoOptions)
defer client.Disconnect(context.TODO())
if err := client.Ping(context.TODO(), nil); err != nil {
log.Fatal(err, "Unable to access MongoDB server, exiting...")
}
// users := client.Database("sharex_api").Collection("authorized_users") // commented out when testing to ignore unused warnings
m := martini.Classic()
m.Post("/api/v1/upload", uploadHandler)
m.RunOnAddr(":8085")
}
The validateAPIKey function works exactly as intended if tested alone, I am just unsure how I would run this function for a specific endpoint (in this case, /api/v1/upload).

How to find full package import from CallExpr

The following method extracts all public method calls from the AST of a file. I need to find out the full package from the CallExpr, for example: ast.Inspect() is imported from "go/ast". I want to match the list of pkgsInclude strings with the imported package name:
func functionCalls(path string, node *ast.File, pkgsInclude []string) int {
fCalls := 0
ast.Inspect(node, func(n ast.Node) bool {
switch fCall := n.(type) {
case *ast.CallExpr:
if fun, ok := fCall.Fun.(*ast.SelectorExpr); ok {
if fun.Sel.IsExported() {
fCalls += 1
}
}
}
return true
})
return fCalls
}
To get fully qualified names, the code has to be type checked with the go/types package.
The go/types article by Alan Donovan goes into great detail on how to use the type checker properly, but here is the gist of it. I left a few type assertions in the Visit method for brevity. In production code you shouldn't assume specific node types.
package main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
// code to parse. It includes two variants of calling a package function.
var code = `package main
import (
foo "io/ioutil"
. "io/ioutil"
)
func main() {
foo.ReadFile("")
ReadFile("")
}
`
func main() {
fset := &token.FileSet{}
f, err := parser.ParseFile(fset, "", code, 0)
if err != nil {
log.Fatal(err)
}
// info.Uses allows to lookup import paths for identifiers.
info := &types.Info{
Uses: make(map[*ast.Ident]types.Object),
}
// Type check the parsed code using the default importer.
// Use golang.org/x/tools/go/loader to check a program
// consisting of multiple packages.
conf := types.Config{Importer: importer.Default()}
pkg, err := conf.Check("main", fset, []*ast.File{f}, info)
if err != nil {
log.Fatal(err)
}
// Do something with ast, info, and possibly pkg
var _ = pkg
ast.Walk(v{info}, f)
}
type v struct {
info *types.Info
}
func (v v) Visit(node ast.Node) (w ast.Visitor) {
switch node := node.(type) {
case *ast.CallExpr:
// Get some kind of *ast.Ident for the CallExpr that represents the
// package. Then we can look it up in v.info. Where exactly it sits in
// the ast depends on the form of the function call.
switch node := node.Fun.(type) {
case *ast.SelectorExpr: // foo.ReadFile
pkgID := node.X.(*ast.Ident)
fmt.Println(v.info.Uses[pkgID].(*types.PkgName).Imported().Path())
case *ast.Ident: // ReadFile
pkgID := node
fmt.Println(v.info.Uses[pkgID].Pkg().Path())
}
}
return v
}
// Output:
// io/ioutil
// io/ioutil

How do I find implementations of a function type?

In Go, it's possible to create function types (https://golang.org/ref/spec#Function_types) like this
type Printer func(s string)
How can I find all of the functions which satisfy this type? For example, if I had the file below, how could I find out that consolePrinter is a Printer?
package main
import "fmt"
func main() {
printToScreen(consolePrinter)
}
// Printer defines a function that prints a string.
type Printer func(s string)
func printToScreen(p Printer) {
p("Hello")
}
// consolePrinter is a Printer (the function signature is identical).
func consolePrinter(s string) {
fmt.Println(s)
}
I tried out guru, but the implements feature doesn't seem to support function types.
guru implements ./main.go:#134
/Users/adrian/go/gurutest/main.go:10.6-10.12: signature type Printer implements only interface{}
You are looking for functions that are assignable to Printer.
The guru tool does not support an "assignable to" query.
You can write a program to find functions that are assignable to Printer using the go/types package. Follow the tutorial to type check code and use AssignableTo to find the functions.
If you are only interested in finding functions declared at package level in gofmted code, then searching your code with a regexp might be good enough. This approach is not accurate, but is simple to do in many editors or the command line.
Here consolePrinter is not of type Printer it is required to declare consolePrinter to be of type Printer.You see console.Printer is a function with same underlying type that's why it can be pass to printToScreen which takes Printer type. Have a Look at the difference with their types
package main
import (
"fmt"
"reflect"
)
func main() {
printToScreen(consolePrinter)
fmt.Println(reflect.TypeOf(consolePrinter)) // Prints func(string) as its type
}
// Printer defines a function that prints a string.
type Printer func(s string)
func printToScreen(p Printer) {
var consoleprint Printer // declare to be of type Printer
fmt.Println(reflect.TypeOf(consoleprint)) // Prints main.Printer
p("Hello")
}
// consolePrinter is a Printer (the function signature is identical).
func consolePrinter(s string) {
fmt.Println(s)
}
Playground Example
Working example, based on Thundercat's answer. guru would need to do something like this to provide support for looking up suitable functions to pass in (e.g. implementations of http.HandleFunc).
package main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
const hello = `package main
import "fmt"
const x = 1;
func main() {
fmt.Println("Hello, world")
}
// Printer defines a function that prints a string.
type Printer func(s string)
func consolePrinter(s string) {
fmt.Println(s)
}
`
func main() {
fset := token.NewFileSet()
// Parse the input string, []byte, or io.Reader,
// recording position information in fset.
// ParseFile returns an *ast.File, a syntax tree.
f, err := parser.ParseFile(fset, "hello.go", hello, 0)
if err != nil {
log.Fatal(err) // parse error
}
// A Config controls various options of the type checker.
// The defaults work fine except for one setting:
// we must specify how to deal with imports.
conf := types.Config{Importer: importer.Default()}
// Type-check the package containing only file f.
// Check returns a *types.Package.
pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil)
if err != nil {
log.Fatal(err) // type error
}
names, signatures := getFunctionTypes(pkg)
for i, name := range names {
fmt.Println("Functions which implement", name)
for _, implementor := range getFunctionsWhichImplement(signatures[i], pkg) {
fmt.Println(implementor)
}
}
}
func getFunctionTypes(pkg *types.Package) (names []string, signatures []*types.Signature) {
for _, name := range pkg.Scope().Names() {
o := pkg.Scope().Lookup(name)
if _, isType := o.(*types.TypeName); !isType {
continue
}
var sig *types.Signature
var isFunc bool
if sig, isFunc = o.Type().Underlying().(*types.Signature); !isFunc {
continue
}
signatures = append(signatures, sig)
names = append(names, name)
}
return
}
func getFunctionsWhichImplement(sig *types.Signature, pkg *types.Package) (fns []types.Object) {
for _, name := range pkg.Scope().Names() {
o := pkg.Scope().Lookup(name)
if _, isType := o.(*types.TypeName); isType {
continue
}
var csig *types.Signature
var isFunc bool
if csig, isFunc = o.Type().Underlying().(*types.Signature); !isFunc {
continue
}
if types.AssignableTo(sig, csig) {
fns = append(fns, o)
}
}
return
}
The output of this code is shown below:
Functions which implement Printer
func cmd/hello.consolePrinter(s string)
I'm sure there are better ways for the specific case of printing, but in general you may be better to take a more idiomatic go approach of using interfaces.
Declare an interface and types that implement the interface:
type StringPrinter interface {
PrintString(string)
}
type Console struct {
// console specific stuff
}
func (c *Console) PrintString(s string) {
// Printing code
}
type Paper struct {
// paper specific stuff
}
func (p *Paper) PrintString(s string) {
// Printing code
}
Then to print in different ways you can access through an interface in a generic way:
func main() {
var sp StringPrinter
sp = &Console{ /* member inits */ }
sp.PrintString("Hello on console")
sp = &Paper{ /* member inits */ }
sp.PrintString("Hello on paper")
}
You will be able to use guru on this form of code to find objects that implement the StringPrinter interface.

Golang JSON Array

I am trying to use WordNik () to get random words for the dictionary for this script: https://github.com/jmagrippis/password
WordNik is outputting:
[{"id":7936915,"word":"Tanganyikan"},{"id":27180,"word":"cartographic"},{"id":48094,"word":"deterministic"},{"id":1485119,"word":"higher-risk"},{"id":120986,"word":"juristic"},{"id":1830806,"word":"magnetorheological"},{"id":320495,"word":"quelled"},{"id":324610,"word":"remoter"},{"id":215158,"word":"telemetric"},{"id":225207,"word":"uninquisitive"}]
Here is my code:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/jmagrippis/password"
)
type Words struct {
id []int64
word []string
}
type GetWordsResponse struct {
WordList []Words
}
func getWords(speech string) (*GetWordsResponse, error) {
url := fmt.Sprintf("http://api.wordnik.com/v4/words.json/randomWords?hasDictionaryDef=false&includePartOfSpeech=%s&minCorpusCount=0&maxCorpusCount=-1&minDictionaryCount=1&maxDictionaryCount=-1&minLength=5&maxLength=-1&limit=10&api_key=api_key", speech)
res, err := http.Get(url)
if err != nil {
panic(err.Error())
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err.Error())
}
var s = new(GetWordsResponse)
var arr []string
_ = json.Unmarshal([]byte(body), &arr)
log.Printf("Unmarshaled: %v", arr)
return s, err
}
func main() {
dictionary := &password.Dictionary{
Adjectives: []string{"beautiful", "homely", "magical", "posh", "excellent"},
Subjects: []string{"mermaids", "unicorns", "lions", "piranhas"},
Verbs: []string{"love", "fancy", "eat", "bring", "fear", "aggravate"},
Adverbs: []string{"cuddling", "slapping", "shouting", "jumping"},
Objects: []string{"teddy-bears", "diamonds", "buckets", "boxes"},
}
generator := password.NewGenerator(dictionary, time.Now().UnixNano())
pass := generator.Generate()
fmt.Printf("%s", pass)
getWords("Verb")
}
As you can see, what I am trying to do is use WordNik API to request Adverbs, nouns, etc and then make a dictionary based off those words to generate a password. I am horrible with arrays and handling data.
As pointed out in the comments you need to export the fields so they can be unmarshaled
The encoding/json package relies on reflection and since it is in another package, it cannot access unexported fields. ( in go, fields, methods or functions that start with a small letter are unexported whereas with capital letters they are exported )
Then your example json does not contain the WordList at all, so what you want is unmarshaling directly into the array of Words. Also a words object only consists of Id and Word and not of arrays themselves.
type Words struct {
Id int64
Word string
}
func main() {
....
var words []Words
// you don't need to read the whole body first, you can decode in the same turn like this
err := json.NewDecoder(req.Body).Decode(&words)
if nil != err {
log.Fatal(err)
}
...
}
Another very important thing is that you should not ignore errors. This would have helped you to debug the issue. ( What I mean is _ = json.Unmarshal)
As for beginning with go, you could implement a simple test to see if your code works as intended.
https://play.golang.org/p/nuz9uXdka5S < check this working example for reference.

How to get all constants of a type in Go

Here is an example:
package main
type State int
const (
Created State = iota
Modified
Deleted
)
func main() {
// Some code here where I need the list
// of all available constants of this type.
}
The use case for this is to create a Finite State Machine (FSM). Being able to get all constants will help me in writing a test case that will ensure that every new value has a corresponding entry in the FSM map.
If your constants are all in an order, you can use this:
type T int
const (
TA T = iota
TB
TC
NumT
)
func AllTs() []T {
ts := make([]T, NumT)
for i := 0; i < int(NumT); i++ {
ts[i] = T(i)
}
return ts
}
You can also cache the output in e.g. init(). This will only work when all constants are initialised with iota in order. If you need something that works for all cases, use an explicit slice.
There is no way to do this at runtime, as the reflect package cannot be used for it. You could define a list:
const(
Created State = iota
Modified
Deleted
)
var allStates = []State{Created, Modified, Deleted}
You may go further and add in a string representation, or any number of other things.
You may be able to generate such a list from the source to make maintenance easier, but I generally don't think that saves enough time to be worth it. There are tools like stringer that can already do some of that.
Since you talking about a test-case I assume you have the type available as well as the file where the constants are defined in. I used for a similar problem the following approach (go playground):
package main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
"strconv"
"strings"
)
type InterestingType uint64
const const_go = `
package p
type InterestingType uint64
const (
A InterestingType = iota << 1
B
C
)
type UninterestingType int
const (
D UninterestingType = iota
E
)
`
func main() {
constantValues := []InterestingType{}
ConstantsOf("InterestingType", const_go, func(v string) {
value, err := strconv.ParseUint(v, 0, 64)
if err != nil {
log.Fatal(err)
}
constantValues = append(
constantValues, InterestingType(value))
})
fmt.Printf("%#v\n", constantValues)
}
func ConstantsOf(ctype string, file string, value func(string)) {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "const.go", file, 0)
if err != nil {
log.Fatal(err)
}
// Obtain type information.
conf := types.Config{Importer: importer.Default()}
info := &types.Info{
Defs: make(map[*ast.Ident]types.Object),
}
_, err = conf.Check("p", fset, []*ast.File{f}, info)
if err != nil {
log.Fatal(err)
}
for _, d := range f.Decls {
for _, s := range d.(*ast.GenDecl).Specs {
v, ok := s.(*ast.ValueSpec)
if !ok {
continue
}
for _, name := range v.Names {
c := info.ObjectOf(name).(*types.Const)
if strings.HasSuffix(c.Type().String(), ctype) {
value(c.Val().ExactString())
}
}
}
}
}
package main
import (
"fmt"
)
type State int
const (
Created State = iota
Modified
Deleted
)
func (s State) Name() (name string) {
switch s {
case Created:
name = "created"
case Modified:
name = "modified"
case Deleted:
name = "deleted"
}
return
}
func main() {
states := States()
fmt.Println(states)
}
func States() (states []State) {
state := State(0)
for {
name := state.Name()
if name == "" {
break
}
states = append(states, state)
state++
}
return
}

Resources