I'm trying to generate a random token that I can use while implementing reset password functionality. This (http://play.golang.org/p/mmAzXLIZML) is the dazzling and non-functional :( code that I came up with for a first try. It doesn't work as I'd hope because it produces the same token over and over again (which I assume is a function of the time not changing). How do I generate a random token with md5 that will change every time?
package main
import "fmt"
import "strconv"
import "time"
import "crypto/md5"
import "io"
func main() {
time := strconv.FormatInt(time.Now().Unix(), 10)
fmt.Println(time)
h := md5.New()
io.WriteString(h, time)
fmt.Printf("%x", h.Sum(nil))
}
http://play.golang.org/p/mmAzXLIZML
It generates the same result each time only because it's in the playground, where time is frozen and pages are cached.
This isn't a great idea though, since a reset password could be guessed based on the time the request was made.
Why does it have to be an md5? Here's a random token generator:
http://play.golang.org/p/3weHBU6YZr
func randToken() string {
b := make([]byte, 8)
rand.Read(b)
return fmt.Sprintf("%x", b)
}
uuid is annother chooice. see
go get "code.google.com/p/go-uuid/uuid"
and the func uuid.New() is what you wanted.
Related
Imagine I want to use strconv.Atoi, but I am lazy, and want to import it automatically.
package main
import (
"fmt"
)
func main() {
i, _ := Atoi|("123")
fmt.Println(i)
}
The pipe sign (|) shows where my cursor is
In PyCharm I was able to automatically import the matching function via alt+ENTER.
Is there a way that vscode changes above code to this one:
package main
import (
"fmt"
"strconv"
)
func main() {
i, _ := strconv.Atoi("123")
fmt.Println(i)
}
VSCode won't guess which package Atoi() is from, but if you tell it, the import will be added automatically.
So just type
i, _ := strconv.Atoi("123")
And hit CTRL+S to save, and the import will be added automatically.
You may also press CTRL+ALT+O which is a shortcut to Organize Imports.
This is a reasonable compromise in Go. As part of API design, exported identifiers are created that read well with the package name. For example the constructor function that creates an MD5 hasher is md5.New() (and not for example md5.NewMD5()), the one that creates an SHA1 hasher is sha1.New(). Just entering New() it's often too verbose, and giving the package name is required to give context to what you refer to.
I'm new to Go and not sure why it prints the same number for rand.Intn(n int) int for every run:
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Intn(10))
}
The docs says :
Intn returns, as an int, a non-negative pseudo-random number in [0,n) from the default Source. It panics if n <= 0.
And how do I properly seed the random number generation?
By calling the rand.Seed() function, passing it a (random) seed (typically the current unix timestamp). Quoting from math/rand package doc:
Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.
Example:
rand.Seed(time.Now().UnixNano())
If rand.Seed() is not called, the generator behaves as if seeded by 1:
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
package main
import
(
"fmt"
"math/rand"
"time"
)
func randomGen(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max - min) + min
}
func main() {
randNum := randomGen(1, 10)
fmt.Println(randNum)
}
Under the package, math/rand, you can find a type Rand.
func New(src Source) *Rand - New returns a new Rand that uses random
values from src to generate other random values.
It actually needs a seed to generate it.
step 1: create a seed as a source using new Source.
time.Now().UnixNano() is used for the accuracy.
step 2: create a
type Rand from the seed
step 3: generate a random number.
Example:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
source := rand.NewSource(time.Now().UnixNano())
r := rand.New(source)
fmt.Println(r.Intn(100))
}
This is the code I'm working with:
package main
import "fmt"
import "math/rand"
func main() {
code := rand.Intn(900000)
fmt.Println(code)
}
It always returns 698081. I don't understand, what the is problem?
https://play.golang.org/p/XisNbqCZls
Edit:
I tried rand.Seed
package main
import "fmt"
import "time"
import "math/rand"
func main() {
rand.Seed(time.Now().UnixNano())
code := rand.Intn(900000)
fmt.Println(code)
}
There is no change. Now it always returns 452000
https://play.golang.org/p/E_Wfm5tOdH
https://play.golang.org/p/aVWIN1Eb84
A couple of reasons why you'll see the same result in the playground
Golang playground will cache the results
The time in the playground always starts at the same time to make the playground deterministic.
Last but not least, the rand package default seed is 1 which will make the result deterministic. If you place a rand.Seed(time.Now().UnixNano()) you'll receive different results at each execution. Note that this won't work on the playground for the second reason above.
I'm going through the Golang tutorial, and I am on this part
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Seed)
}
This returns My favorite number is 0xb1c20
I have been reading on https://golang.org/pkg/math/rand/#Seed but I'm still a bit confused as to how have it instead of show the hex show a string
math/rand.Seed is a function; you are printing the function's location in memory. You probably meant to do something like the following:
package main
import (
"fmt"
"math/rand"
)
func main() {
rand.Seed(234) // replace with your seed value, or set the seed based off
// of the current time
fmt.Println("My favorite number is", rand.Int())
}
I am writing a program that needs to use Dropbox's webhooks. I haven't been able to find any Go implementation already in place, so I've decided to write mine. Unfortunately, it doesn't seem to work.
I think the issue here is with hmac, as I am most probably doing something wrong, but I just can't seem to understand where exactly the issue here. Any idea?
The following is what I have:
package dboxwebhook
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"errors"
"io"
"io/ioutil"
"log"
)
type Signature struct {
AppSecret []byte
Signature []byte
}
func (w *Signature) Check(reqBody io.ReadCloser) error {
if bytes.Compare(w.Signature, nil) == 0 {
return errors.New("DropBox signature doesnt exist")
}
// building HMAC key (https://golang.org/pkg/crypto/hmac/)
mac := hmac.New(sha256.New, w.AppSecret)
requestBody, err := ioutil.ReadAll(reqBody)
if err != nil {
return err
}
mac.Write(requestBody)
expectedMac := mac.Sum(nil)
log.Println(w.AppSecret)
log.Println(expectedMac)
log.Println(w.Signature)
// compare if it corresponds with the signature sent by DropBox
comparison := hmac.Equal(w.Signature, expectedMac)
if !comparison {
return errors.New("Signature Check unsuccessful")
}
return nil
}
To test this, the only way I know is to use this Python script from Dropbox.
The Dropbox signature is sent as string in the HTTP header X-Dropbox-Signature.
So as to use it with hmac.Equal, you need to decode the hex string representation to a slice of byte first using package encoding/hex.
import "encoding/hex"
[...]
hexSignature, err := hex.DecodeString(w.Signature)
[...]
Then you can use the hex bytes in the comparison
[...]
// compare if it corresponds with the signature sent by DropBox
comparison := hmac.Equal(hexSignature, expectedMac)
[...]