Copyright 2014 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. See https://flak.tedunangst.com/post/bcrypt-pbkdf and https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c.
package bcrypt_pbkdf

import (
	
	
	
)

const blockSize = 32
Key derives a key from the password, salt and rounds count, returning a []byte of length keyLen that can be used as cryptographic key.
func (,  []byte, ,  int) ([]byte, error) {
	if  < 1 {
		return nil, errors.New("bcrypt_pbkdf: number of rounds is too small")
	}
	if len() == 0 {
		return nil, errors.New("bcrypt_pbkdf: empty password")
	}
	if len() == 0 || len() > 1<<20 {
		return nil, errors.New("bcrypt_pbkdf: bad salt length")
	}
	if  > 1024 {
		return nil, errors.New("bcrypt_pbkdf: keyLen is too large")
	}

	 := ( + blockSize - 1) / blockSize
	 := make([]byte, *blockSize)

	 := sha512.New()
	.Write()
	 := .Sum(nil)

	 := make([]byte, 0, sha512.Size)
	,  := make([]byte, 4), make([]byte, blockSize)
	for  := 1;  <= ; ++ {
		.Reset()
		.Write()
		[0] = byte( >> 24)
		[1] = byte( >> 16)
		[2] = byte( >> 8)
		[3] = byte()
		.Write()
		bcryptHash(, , .Sum())

		 := make([]byte, blockSize)
		copy(, )
		for  := 2;  <= ; ++ {
			.Reset()
			.Write()
			bcryptHash(, , .Sum())
			for  := 0;  < len(); ++ {
				[] ^= []
			}
		}

		for ,  := range  {
			[*+(-1)] = 
		}
	}
	return [:], nil
}

var magic = []byte("OxychromaticBlowfishSwatDynamite")

func (, ,  []byte) {
	,  := blowfish.NewSaltedCipher(, )
	if  != nil {
		panic()
	}
	for  := 0;  < 64; ++ {
		blowfish.ExpandKey(, )
		blowfish.ExpandKey(, )
	}
	copy(, magic)
	for  := 0;  < 32;  += 8 {
		for  := 0;  < 64; ++ {
			.Encrypt([:+8], [:+8])
		}
Swap bytes due to different endianness.
	for  := 0;  < 32;  += 4 {
		[+3], [+2], [+1], [] = [], [+1], [+2], [+3]
	}