예제 #1
0
func (d *Daemon) verifyAdminPwd(password string) bool {
	value, err := dbPasswordGet(d.db)

	if err != nil {
		shared.Debugf("verifyAdminPwd: %s", err)
		return false
	}

	buff, err := hex.DecodeString(value)
	if err != nil {
		shared.Debugf("hex decode failed")
		return false
	}

	salt := buff[0:PW_SALT_BYTES]
	hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, PW_HASH_BYTES)
	if err != nil {
		shared.Debugf("failed to create hash to check")
		return false
	}
	if !bytes.Equal(hash, buff[PW_SALT_BYTES:]) {
		shared.Debugf("Bad password received")
		return false
	}
	shared.Debugf("Verified the admin password")
	return true
}
예제 #2
0
파일: paperkey_gen.go 프로젝트: qbit/client
// Run starts the engine.
func (e *PaperKeyGen) Run(ctx *Context) error {
	// make the passphrase stream
	key, err := scrypt.Key(e.arg.Passphrase.Bytes(), nil,
		libkb.PaperKeyScryptCost, libkb.PaperKeyScryptR, libkb.PaperKeyScryptP, libkb.PaperKeyScryptKeylen)
	if err != nil {
		return err
	}

	ppStream := libkb.NewPassphraseStream(key)

	// make keys for the paper device
	if err := e.makeSigKey(ppStream.EdDSASeed()); err != nil {
		return err
	}
	if err := e.makeEncKey(ppStream.DHSeed()); err != nil {
		return err
	}

	// push everything to the server
	if err := e.push(ctx); err != nil {
		return err
	}

	// no need to notify if key wasn't pushed to server
	// (e.g. in the case of using this engine to verify a key)
	if e.arg.SkipPush {
		return nil
	}
	e.G().NotifyRouter.HandleKeyfamilyChanged(e.arg.Me.GetUID())
	// Remove this after kbfs notification change complete
	e.G().NotifyRouter.HandleUserChanged(e.arg.Me.GetUID())

	return nil
}
예제 #3
0
// PasswordSet sets the password to the new value.
func (d *Daemon) PasswordSet(password string) error {
	shared.Log.Info("Setting new https password")
	var value = password
	if password != "" {
		buf := make([]byte, pwSaltBytes)
		_, err := io.ReadFull(rand.Reader, buf)
		if err != nil {
			return err
		}

		hash, err := scrypt.Key([]byte(password), buf, 1<<14, 8, 1, pwHashBytes)
		if err != nil {
			return err
		}

		buf = append(buf, hash...)
		value = hex.EncodeToString(buf)
	}

	err := d.ConfigValueSet("core.trust_password", value)
	if err != nil {
		return err
	}

	return nil
}
예제 #4
0
// Decrypt decrypts an encrypted message and returns it (plaintext).
// If you have enabled compression, it wil detect it and decompress
// the msg after decrypting it.
func (c SaltSecret) Decrypt(msg []byte) ([]byte, error) {
	if len(msg) < nonceSize+secretbox.Overhead {
		return nil, errors.New("encrypted message length too short")
	}

	nonce := new([nonceSize]byte)
	copy(nonce[:], msg[:nonceSize])

	key, err := scrypt.Key(c.key, nonce[:], 2<<c.NPow, 8, 1, keySize)
	if err != nil {
		return nil, err
	}

	naclKey := new([keySize]byte)
	copy(naclKey[:], key)
	out, ok := secretbox.Open(nil, msg[nonceSize:], nonce, naclKey)
	if !ok {
		return nil, errors.New("could not decrypt message")
	}

	if nonce[23]&compressBit == compressBit {
		r, err := zlib.NewReader(bytes.NewReader(out))
		if err != nil {
			return nil, err
		}
		r.Close()
		out, err = ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}
	}
	return out, nil
}
예제 #5
0
파일: serverconfig.go 프로젝트: kostyll/lxd
func setTrustPassword(d *Daemon, password string) error {
	shared.Debugf("setting new password")
	var value = password
	if password != "" {
		buf := make([]byte, PW_SALT_BYTES)
		_, err := io.ReadFull(rand.Reader, buf)
		if err != nil {
			return err
		}

		hash, err := scrypt.Key([]byte(password), buf, 1<<14, 8, 1, PW_HASH_BYTES)
		if err != nil {
			return err
		}

		buf = append(buf, hash...)
		value = hex.EncodeToString(buf)
	}

	err := setServerConfig(d, "core.trust_password", value)
	if err != nil {
		return err
	}

	return nil
}
func DecryptKey(ks keyStorePassphrase, keyAddr []byte, auth string) (keyBytes []byte, keyId []byte, err error) {
	fileContent, err := GetKeyFile(ks.keysDirPath, keyAddr)
	if err != nil {
		return nil, nil, err
	}

	keyProtected := new(encryptedKeyJSON)
	err = json.Unmarshal(fileContent, keyProtected)

	keyId = keyProtected.Id
	salt := keyProtected.Crypto.Salt
	iv := keyProtected.Crypto.IV
	cipherText := keyProtected.Crypto.CipherText

	authArray := []byte(auth)
	derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen)
	if err != nil {
		return nil, nil, err
	}
	plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv)
	if err != nil {
		return nil, nil, err
	}
	keyBytes = plainText[:len(plainText)-32]
	keyBytesHash := plainText[len(plainText)-32:]
	if !bytes.Equal(Sha3(keyBytes), keyBytesHash) {
		err = errors.New("Decryption failed: checksum mismatch")
		return nil, nil, err
	}
	return keyBytes, keyId, err
}
예제 #7
0
func EncodePassword(rawPwd string, salt string) string {
	pwd, err := scrypt.Key([]byte(rawPwd), []byte(salt), 16384, 8, 1, 64)
	if err != nil {
		log.Println("EncodePassword error: %s", err)
	}
	return hex.EncodeToString(pwd)
}
예제 #8
0
// Calculate the password based on a key derived from the master password and the account name
// The key derivation is implemented by the popular "scrypt" algorithm.
func CalculatePassword(accountName string, masterPassword string, salt string) string {
	derivedKey, err := scrypt.Key([]byte(masterPassword), []byte(salt+accountName), 16384, 8, 1, 128)
	if err != nil {
		panic(err)
	}
	return ComputeHmac256(accountName, string(derivedKey))[:32]
}
예제 #9
0
/**
 * Creates an encoded sequence of bytes containing all of the parameters passed to
 * scrypt and the hash itself.  Presented with a very similar interface to that of
 * golang.org/x/crypto/bcrypt.
 */
func GenerateFromPassword(password []byte, parameters HashConfiguration) ([]byte, error) {
	// Do an extra check on the input to make sure it meets our standards.
	paramErr := verifyParameterValidity(parameters)
	if paramErr != nil {
		return nil, paramErr
	}
	// Pull some random bytes to use as a salt and make sure we got as much as expected.
	salt := make([]byte, parameters.SaltLen)
	bytesRead, randSrcErr := rand.Read(salt)
	if HashParameter(bytesRead) != parameters.SaltLen {
		return nil, ErrInsufficientRandomData
	}
	if randSrcErr != nil {
		return nil, randSrcErr
	}
	// Invoke the scrypt library and augment the hashed value with the hash parameters.
	hashedValue, hashErr := scrypt.Key(
		password,
		salt,
		int(parameters.N),
		int(parameters.R),
		int(parameters.P),
		int(parameters.KeyLen))
	if hashErr != nil {
		return nil, hashErr
	}
	return encodeParameters(hashedValue, salt, parameters), nil
}
예제 #10
0
func encryptToken(key []byte, j *JobToken) ([]byte, error) {

	jsonData := j.JSON()

	ciphertext := make([]byte, aes.BlockSize+len(jsonData))

	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}

	sKey, serr := scrypt.Key(key, iv, scrypt_n, scrypt_r, scrypt_p, scrypt_keyLen)

	if serr != nil {
		return nil, serr
	}

	block, berr := aes.NewCipher(sKey)
	if berr != nil {
		return nil, berr
	}

	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], jsonData)
	return ciphertext, nil
}
예제 #11
0
func decryptToken(key, ciphertext []byte) ([]byte, error) {

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	if len(ciphertext) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}

	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	sKey, serr := scrypt.Key(key, iv, scrypt_n, scrypt_r, scrypt_p, scrypt_keyLen)

	if serr != nil {
		return nil, serr
	}
	block, err := aes.NewCipher(sKey)
	if err != nil {
		return nil, err
	}

	stream := cipher.NewCFBDecrypter(block, iv)

	// XORKeyStream can work in-place if the two arguments are the same.
	stream.XORKeyStream(ciphertext, ciphertext)

	return ciphertext, nil
}
예제 #12
0
func handleLoginPass(world World, c net.Conn, playerName string) {
	playerName = strings.ToLower(playerName)
	c.Write([]byte("Please enter your password.\r\n"))
	pass, err := getBytesSecure(c)
	defer func() {
		for i := range pass {
			pass[i] = 0
		}
	}()
	if err != nil {
		return
	}
	player, exists := world.players.GetByName(playerName)
	if !exists {
		return // we just validated the player exists, so this shouldn't happen
	}

	hashedPass, err := scrypt.Key([]byte(pass), player.passthesalt, 16384, 8, 1, 32)
	if err != nil {
		fmt.Printf("Error creating hashed pass: %v\n", err)
		c.Close()
		return
	}

	if !bytes.Equal(hashedPass, player.pass) {
		c.Write([]byte("Invalid password.\r\n"))
		c.Close()
		return
	}
	world.players.ChangeById(player.Id(), func(p *Player) {
		p.connection = c
	})
	go handlePlayer(world, player.Id())
}
예제 #13
0
파일: users.go 프로젝트: SiroDiaz/csuf
// CreateUser creates a new user record
func CreateUser(ctx context.Context, email, password string) error {
	if email == "" {
		return fmt.Errorf("invalid email")
	}
	if password == "" {
		return fmt.Errorf("invalid password")
	}
	key := datastore.NewKey(ctx, "User", email, 0, nil)
	var user User
	err := datastore.Get(ctx, key, &user)
	if err == nil {
		return fmt.Errorf("user already exists")
	}

	salt := make([]byte, 16)
	rand.Read(salt)
	hash, err := scrypt.Key([]byte(password), salt, scryptN, scryptR, scryptP, scryptKeyLen)
	if err != nil {
		return err
	}

	user = User{
		Email:        email,
		PasswordSalt: salt,
		PasswordHash: hash,
	}

	_, err = datastore.Put(ctx, key, &user)
	return err
}
예제 #14
0
파일: kdf.go 프로젝트: rfjakob/gocryptfs
// DeriveKey returns a new key from a supplied password.
func (s *ScryptKDF) DeriveKey(pw string) []byte {
	k, err := scrypt.Key([]byte(pw), s.Salt, s.N, s.R, s.P, s.KeyLen)
	if err != nil {
		log.Panicf("DeriveKey failed: %v", err)
	}
	return k
}
예제 #15
0
파일: scrypto.go 프로젝트: codehack/scrypto
// Compare compares a plaintext password to a hashed password.
// password is a plaintext password.
// hpass is hashed password string in $s0$ format.
// returns true if passwords match, false otherwise.
func Compare(password, hpass string) bool {
	seg := strings.Split(hpass, "$")
	if len(seg) != 5 || seg[1] != "s0" {
		return false
	}

	values, _ := strconv.ParseInt(seg[2], 10, 64)
	salt, _ := base64.RawStdEncoding.DecodeString(seg[3])
	hashed1, _ := base64.RawStdEncoding.DecodeString(seg[4])

	N := int(math.Pow(2, float64(values>>16&0xffff)))
	r := int(values) >> 8 & 0xff
	p := int(values) & 0xff

	hashed2, _ := scrypt.Key([]byte(password), salt, N, r, p, KeyLen)

	len1 := len(hashed1)
	if len1 != len(hashed2) {
		return false
	}

	var comp int
	for i := 0; i < len1; i++ {
		comp |= int(hashed1[i] ^ hashed2[i])
	}

	return comp == 0
}
예제 #16
0
/**
 * Hash the provided password with the already hashed password using the same parameters
 * used to hash the latter.  A constant time comparison between the encoded result of the
 * hash operation and existing hashed value tells us if the passwords match.
 */
func CompareHashAndPassword(hashedPassword, password []byte) error {
	// Extract the parameters and salt encoded in the hashed value.
	parameters, salt, decodeErr := decodeParameters(hashedPassword)
	if decodeErr != nil {
		return decodeErr
	}
	// Hash the input password with the same parameters used for the already hashed value.
	hashedValue, hashErr := scrypt.Key(
		password,
		salt,
		int(parameters.N),
		int(parameters.R),
		int(parameters.P),
		int(parameters.KeyLen))
	if hashErr != nil {
		return hashErr
	}
	// Encode the newly hashed password the same way as the previously encoded one.
	encoded := encodeParameters(hashedValue, salt, parameters)
	// Use a constant time comparison from crypto/subtle to ensure the values match.
	areEqual := subtle.ConstantTimeCompare(hashedPassword, encoded) == 1
	if !areEqual {
		return ErrMismatchedHashAndPassword
	}
	return nil
}
예제 #17
0
파일: scrypt.go 프로젝트: bndw/pick
func (s *Scrypt) DeriveKeyWithSalt(password, salt []byte, keyLen int) ([]byte, error) {
	key, err := scrypt.Key(password, salt, s.N, s.R, s.P, keyLen)
	if err != nil {
		return nil, err
	}
	return key, nil
}
예제 #18
0
파일: password.go 프로젝트: heartsg/dasea
//According to benchmarking, scrypt.Key takes 60ms for i7 processor.
//Use encrypt only when necessary
func Encrypt(password string, salt []byte) ([]byte, error) {
	key, err := scrypt.Key([]byte(password), salt, 16384, 8, 1, passwordSize)
	if err != nil {
		return nil, err
	}
	return key, nil
}
예제 #19
0
파일: triplesec.go 프로젝트: qbit/client
func (c *Cipher) DeriveKey(extra int) ([]byte, []byte, error) {

	dkLen := DkLen + extra

	if c.derivedKey == nil || len(c.derivedKey) < dkLen {

		// XXX XXX XX XXX XX XX XX XXX
		//
		//    NOW SEE THIS
		//
		// We're giving a very insecure and degraded value of N here
		// at N=2; we typically run with N=2^15, but we want to make this
		// fork of Triplesec intentionally weak so our tests run faster.
		// So the second paramenter of scrypt.Key() is set to N=2
		//
		// XXX XXX XXX XXXX XXXX XXXXX
		insecureNValue := 2
		dk, err := scrypt.Key(c.passphrase, c.salt, insecureNValue, 8, 1, dkLen)
		if err != nil {
			return nil, nil, err
		}
		c.derivedKey = dk
	}
	return c.derivedKey[0:DkLen], c.derivedKey[DkLen:], nil
}
예제 #20
0
func (s *scryptKdf) DeriveKey(pw string) []byte {
	k, err := scrypt.Key([]byte(pw), s.Salt, s.N, s.R, s.P, s.KeyLen)
	if err != nil {
		panic(fmt.Sprintf("DeriveKey failed: %s", err.Error()))
	}
	return k
}
예제 #21
0
파일: daemon.go 프로젝트: akshaykarle/lxd
func (d *Daemon) PasswordCheck(password string) error {
	value := daemonConfig["core.trust_password"].Get()

	// No password set
	if value == "" {
		return fmt.Errorf("No password is set")
	}

	// Compare the password
	buff, err := hex.DecodeString(value)
	if err != nil {
		return err
	}

	salt := buff[0:32]
	hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, 64)
	if err != nil {
		return err
	}

	if !bytes.Equal(hash, buff[32:]) {
		return fmt.Errorf("Bad password provided")
	}

	return nil
}
예제 #22
0
파일: certificates.go 프로젝트: kostyll/lxd
func (d *Daemon) verifyAdminPwd(password string) bool {
	q := "SELECT value FROM config WHERE key=\"core.trust_password\""
	value := ""
	argIn := []interface{}{}
	argOut := []interface{}{&value}
	err := dbQueryRowScan(d.db, q, argIn, argOut)

	if err != nil || value == "" {
		shared.Debugf("verifyAdminPwd: no password is set")
		return false
	}

	buff, err := hex.DecodeString(value)
	if err != nil {
		shared.Debugf("hex decode failed")
		return false
	}

	salt := buff[0:PW_SALT_BYTES]
	hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, PW_HASH_BYTES)
	if err != nil {
		shared.Debugf("failed to create hash to check")
		return false
	}
	if !bytes.Equal(hash, buff[PW_SALT_BYTES:]) {
		shared.Debugf("Bad password received")
		return false
	}
	shared.Debugf("Verified the admin password")
	return true
}
예제 #23
0
// Encrypt encrypts a message and returns the encrypted msg (nonce + ciphertext).
// If you have enabled compression, it will compress the msg before encrypting it.
func (c SaltSecret) Encrypt(msg []byte) (out []byte, e error) {
	nonce := new([nonceSize]byte)
	_, err := io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		return nil, err
	}

	// We use the last bit of the nonce as a compression indicator.
	// This should still keep you safe (extremely rare collisions).
	nonce[23] &= ^compressBit
	if c.compress {
		nonce[23] |= compressBit
	}

	key, err := scrypt.Key(c.key, nonce[:], 2<<c.NPow, 8, 1, keySize)
	if err != nil {
		return nil, err
	}

	if c.compress {
		var b bytes.Buffer
		w := zlib.NewWriter(&b)
		w.Write(msg)
		w.Close()
		msg = b.Bytes()
	}

	out = make([]byte, nonceSize)
	copy(out, nonce[:])
	naclKey := new([keySize]byte)
	copy(naclKey[:], key)
	out = secretbox.Seal(out, msg, nonce, naclKey)
	return out, nil
}
예제 #24
0
// Run starts the engine.
func (e *PaperKeyGen) Run(ctx *Context) error {
	// make the passphrase stream
	key, err := scrypt.Key(e.arg.Passphrase.Bytes(), nil,
		libkb.PaperKeyScryptCost, libkb.PaperKeyScryptR, libkb.PaperKeyScryptP, libkb.PaperKeyScryptKeylen)
	if err != nil {
		return err
	}

	ppStream := libkb.NewPassphraseStream(key)

	// make keys for the paper device
	if err := e.makeSigKey(ppStream.EdDSASeed()); err != nil {
		return err
	}
	if err := e.makeEncKey(ppStream.DHSeed()); err != nil {
		return err
	}

	// push everything to the server
	if err := e.push(ctx); err != nil {
		return err
	}

	return nil
}
예제 #25
0
파일: main.go 프로젝트: disorganizer/brig
func derivateAesKey(pwd, salt []byte, keyLen int) []byte {
	key, err := scrypt.Key(pwd, salt, 16384, 8, 1, keyLen)
	if err != nil {
		panic("Bad scrypt parameters: " + err.Error())
	}
	return key
}
예제 #26
0
func register(ctx context, w http.ResponseWriter, r *http.Request) {

	email := r.PostFormValue("inputEmail")
	password := r.PostFormValue("inputPassword")

	salt := securecookie.GenerateRandomKey(32)
	// salt := "d61162e555f68c3151133351fc908d688aa2bb1e5bab958859290c443eeec0bc"
	dk, _ := scrypt.Key([]byte(password), salt, 16384, 8, 1, 32)

	password_hash := fmt.Sprintf("%x", dk)
	password_salt := fmt.Sprintf("%x", salt)

	user := models.User{
		Username:     email,
		PasswordHash: password_hash,
		PasswordSalt: password_salt,
	}

	fmt.Printf("%+v\n", user)

	if email == "*****@*****.**" && password == "password" {
		session, _ := ctx.SessionStore().Get(r, "login")

		session.Values["username"] = email
		session.Values["sessionKey"] = string(securecookie.GenerateRandomKey(16))
		session.Save(r, w)

		w.Write([]byte("success"))
	} else {
		http.Redirect(w, r, "index.html", 301)
	}
}
예제 #27
0
func getKDFKey(cryptoJSON cryptoJSON, auth string) ([]byte, error) {
	authArray := []byte(auth)
	salt, err := hex.DecodeString(cryptoJSON.KDFParams["salt"].(string))
	if err != nil {
		return nil, err
	}
	dkLen := ensureInt(cryptoJSON.KDFParams["dklen"])

	if cryptoJSON.KDF == "scrypt" {
		n := ensureInt(cryptoJSON.KDFParams["n"])
		r := ensureInt(cryptoJSON.KDFParams["r"])
		p := ensureInt(cryptoJSON.KDFParams["p"])
		return scrypt.Key(authArray, salt, n, r, p, dkLen)

	} else if cryptoJSON.KDF == "pbkdf2" {
		c := ensureInt(cryptoJSON.KDFParams["c"])
		prf := cryptoJSON.KDFParams["prf"].(string)
		if prf != "hmac-sha256" {
			return nil, fmt.Errorf("Unsupported PBKDF2 PRF: ", prf)
		}
		key := pbkdf2.Key(authArray, salt, c, dkLen, sha256.New)
		return key, nil
	}

	return nil, fmt.Errorf("Unsupported KDF: ", cryptoJSON.KDF)
}
예제 #28
0
파일: crypto.go 프로젝트: marete/restic
// KDF derives encryption and message authentication keys from the password
// using the supplied parameters N, R and P and the Salt.
func KDF(N, R, P int, salt []byte, password string) (*Key, error) {
	if len(salt) == 0 {
		return nil, fmt.Errorf("scrypt() called with empty salt")
	}

	derKeys := &Key{}

	keybytes := macKeySize + aesKeySize
	scryptKeys, err := scrypt.Key([]byte(password), salt, N, R, P, keybytes)
	if err != nil {
		return nil, fmt.Errorf("error deriving keys from password: %v", err)
	}

	if len(scryptKeys) != keybytes {
		return nil, fmt.Errorf("invalid numbers of bytes expanded from scrypt(): %d", len(scryptKeys))
	}

	// first 32 byte of scrypt output is the encryption key
	copy(derKeys.Encrypt[:], scryptKeys[:aesKeySize])

	// next 32 byte of scrypt output is the mac key, in the form k||r
	macKeyFromSlice(&derKeys.MAC, scryptKeys[aesKeySize:])

	return derKeys, nil
}
예제 #29
0
// PasswordCheck checks if the given password is the same
// as we have in the DB.
func (d *Daemon) PasswordCheck(password string) bool {
	value, err := d.ConfigValueGet("core.trust_password")
	if err != nil {
		shared.Log.Error("verifyAdminPwd", log.Ctx{"err": err})
		return false
	}

	// No password set
	if value == "" {
		return false
	}

	buff, err := hex.DecodeString(value)
	if err != nil {
		shared.Log.Error("hex decode failed", log.Ctx{"err": err})
		return false
	}

	salt := buff[0:pwSaltBytes]
	hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, pwHashBytes)
	if err != nil {
		shared.Log.Error("Failed to create hash to check", log.Ctx{"err": err})
		return false
	}
	if !bytes.Equal(hash, buff[pwSaltBytes:]) {
		shared.Log.Error("Bad password received", log.Ctx{"err": err})
		return false
	}
	shared.Log.Debug("Verified the admin password")
	return true
}
예제 #30
0
파일: login.go 프로젝트: kladd/keybase
// Login encrypts password using a salt created with GetSalt() and transmits it
// to keybase in exchange for a session.
func Login(username string, password string) (*LoginResponse, error) {
	if s := LoadSession(); s != "" {
		return new(LoginResponse), nil
	}

	gsp := getSaltParams{username}
	gspr, err := getSalt(gsp)

	l := loginParams{gsp, *gspr, ""}

	salt, err := hex.DecodeString(l.Salt.Salt)
	ls, err := base64.StdEncoding.DecodeString(l.Salt.LoginSession)

	pwh, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 224)
	hm := hmac.New(sha512.New, pwh[192:224])
	hm.Write(ls)

	l.hmacPwh = fmt.Sprintf("%x", hm.Sum(nil))

	r := new(LoginResponse)
	post("login", l, r)

	session = r.Session
	session.Save()

	return r, err
}