예제 #1
0
// VerifyPassword checks if password is valid and upgrades it if its encrypting scheme was outdated
// Returns isValid, wasUpdated, error
func (a *Account) VerifyPassword(password string) (bool, bool, error) {
	isValid, err := mcf.Verify(password, a.Password)
	if err != nil {
		return false, false, err
	}

	if !isValid {
		return false, false, nil
	}

	isCurrent, err := mcf.IsCurrent(a.Password)
	if err != nil {
		return false, false, err
	}

	if !isCurrent {
		err := a.SetPassword(password)
		if err != nil {
			return true, false, err
		}

		a.Touch()
		return true, true, nil
	}

	return true, false, nil
}
예제 #2
0
func TestVectors(t *testing.T) {
	for i, v := range testVectors {

		key, err := hex.DecodeString(v.key)
		if err != nil {
			t.Errorf("%d: could not decode key: %s: %s", i, v.key, err)
			continue
		}

		config, err := setConfig(len(key), v.iterations, len(v.salt))
		if err != nil {
			t.Errorf("%d: unexpected error setting config: %s", i, err)
		}

		setSalt(v.salt)

		encoded, err := mcf.Create(v.plain)
		if err != nil {
			t.Errorf("%d: got unexpected error: %s", i, err)
		}

		passwd := password.New([]byte("pbkdf2"))
		err = passwd.Parse([]byte(encoded))
		if err != nil {
			t.Errorf("%d: unexpected error creating password instance: %s", i, err)
		}

		if p, q := []byte(config.Params()), passwd.Params; !bytes.Equal(p, q) {
			t.Errorf("%d: params: expected %s, got %s", i, string(p), string(q))
		}

		if p, q := []byte(v.salt), passwd.Salt; !bytes.Equal(p, q) {
			t.Errorf("%d: salt: expected %s, got %s", i, string(p), string(q))
		}

		if p, q := key, passwd.Key; !bytes.Equal(p, q) {
			t.Errorf("%d: key: expected %x, got %x", i, p, q)
		}

		isValid, err := mcf.Verify(v.plain, encoded)
		if err != nil {
			t.Errorf("%d: verify: unexpected failure on %q: %s", i, encoded, err)
			continue
		}
		if !isValid {
			t.Errorf("%d: verify - unexpectedly returned false", i)
			continue
		}

		// perturb configuration...
		newConfig := *config
		newConfig.KeyLen += 1

		for j, c := range []*Config{config, &newConfig} {
			setConfig(c.KeyLen, c.Iterations, c.SaltLen)
			isCurrent, err := mcf.IsCurrent(encoded)
			if err != nil {
				t.Errorf("%d-%d: IsCurrent: unexpected failure: %", i, j, err)
				continue
			}
			//old configuration says yes, new configuration says no
			if answer := c == config; isCurrent != answer {
				t.Errorf("%d-%d: IsCurrent: expecting %t got %t", i, j, answer, isCurrent)
				continue
			}
		}
	}
}
예제 #3
0
func TestVectors(t *testing.T) {
	for i, v := range testVectors {

		x := strings.Split(v.salt[1:], "$")
		if len(x) != 3 {
			t.Fatalf("%d: invalid field structure: %s", i, v.salt)
		}
		costIn, saltIn := x[1], x[2] //index 0 is not interesting.

		salt, err := base64Decode([]byte(saltIn))

		if err != nil {
			t.Fatalf("%d: error decoding salt: %s", i, err)
		}
		var cost int
		if _, err := fmt.Sscanf(costIn, "%02d", &cost); err != nil {
			t.Fatalf("%d: error decoding param [%+v]: %s", i, costIn, err)
		}

		// Hijack rand.Reader to feed salt to crypto/bcrypt.
		// Need extra salt because SetCost generates a digest
		// to test the new cost, and each of the 3 calls to it uses
		// up one portion of salt.
		rand.Reader = bytes.NewReader(bytes.Repeat(salt, 4))

		err = SetCost(cost)
		if err != nil {
			t.Errorf("%d: SetCost: unexpected error: %s", i, err)
		}

		encoded, err := mcf.Create(v.plain)
		if err != nil {
			// password must be at least 2 bytes otherwise crypto/blowfish complains.
			// This really should be handled in crypto/bcrypt
			if len(v.plain) < 3 {
				continue
			}
			t.Errorf("%d: unexpected error: %s", i, err)
			continue
		}

		if want, got := v.passwd, encoded; want != got {
			t.Errorf("%d: output mismatch. want: %s, got %s", i, want, got)
			continue
		}

		isValid, err := mcf.Verify(v.plain, encoded)
		if err != nil {
			t.Errorf("%d: verify: unexpected failure on %q: %s", i, encoded, err)
			continue
		}
		if !isValid {
			t.Errorf("%d: IsValid: expecting true got false", i)
			continue
		}

		for j, pair := range []struct {
			cost   int
			answer bool
		}{{cost, true}, {cost + 1, false}} {

			err := SetCost(pair.cost)
			if err != nil {
				t.Errorf("%d-%d: SetCost: unexpected error: %s", i, j, err)
			}

			isCurrent, err := mcf.IsCurrent(encoded)
			if err != nil {
				t.Errorf("%d-%d: IsCurrent: unexpected failure: %", i, j, err)
				continue
			}
			if isCurrent != pair.answer {
				t.Errorf("%d-%d: IsCurrent: expecting %t got %t", i, j, pair.answer, isCurrent)
				continue
			}
		}
	}
}