Skip to content

x/crypto/bcrypt: bcrypt.expensiveBlowfishSetup changes slice's underlying array #20425

Closed
@magisterquis

Description

@magisterquis

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.8.1 openbsd/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="openbsd"
GOOS="openbsd"
GOPATH="/home/stuart/go"
GORACE=""
GOROOT="/home/stuart/.go/1.8.1"
GOTOOLDIR="/home/stuart/.go/1.8.1/pkg/tool/openbsd_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -fmessage-length=0"
CXX="g++"
CGO_ENABLED="0"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

package main

import (
        "log"

        "golang.org/x/crypto/bcrypt"
)

const HASH = "$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa"

func main() {
        a := []byte("passw0rd123456")
        password := a[:len(a)-6]
        token := a[len(a)-6:]

        log.Printf("Before: A:%q T:%q P:%q", a, token, password)
        if err := bcrypt.CompareHashAndPassword([]byte(HASH), password); nil != err {
                log.Fatalf("Hash mismatch")
        }

        log.Printf("After: A:%q T:%q P:%q", a, token, password)
}

Output:

2017/05/19 11:58:43 Before: A:"passw0rd123456" T:"123456" P:"passw0rd"
2017/05/19 11:58:43 After: A:"passw0rd\x0023456" T:"\x0023456" P:"passw0rd"

What did you expect to see?

I expected the value of token to be unchanged after the call to bcrypt.CompareAndHashPassword.

What did you see instead?

The first byte of token was changed. This seems to happen in the call to bcrypt.expensiveBlowfishSetup when it appends a null byte to password to be compatible with C implementations.

https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go#L216

Unfortunately this changes the slice's underlying array, which can have knock-on effects if other slices refer to the same array (as in my 2FA-derived example).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions