func TestEncoderInteraction(t *testing.T) { var list []string // Test that SetDefault works for i, r := range encodings { err := mcf.SetDefault(r.encoding) if err != nil { t.Errorf("%d-1: SetDefault %s: unexpected error: %s", i, r.encoding, err) continue } encoded, err := mcf.Create(plain) if err != nil { t.Errorf("%d-1: Create: unexpected error: %s", i, err) continue } isValid, err := mcf.Verify(plain, encoded) if err != nil { t.Errorf("%d-1: Verify: unexpected error: %s", i, err) continue } if !isValid { t.Errorf("%d-1: Verify: unexpected failure on plain=%q encoded=%q, encoding=%q", i, plain, encoded, r.encoding) continue } if s := encoded; !strings.HasPrefix(s, r.id) { t.Errorf("%d-1: Create: encoding prefix mismatch: s=%s, prefix=%s", i, s, r.id) continue } list = append(list, encoded) } // Verification is independent of default setting // and should work as long as the encoder exists. for i, r := range encodings { err := mcf.SetDefault(r.encoding) if err != nil { t.Errorf("%d-2: SetDefault %s: unexpected error: %s", i, r.encoding, err) continue } for _, encoded := range list { isValid, err := mcf.Verify(plain, encoded) if err != nil { t.Errorf("%d-2: Verify: unexpected error: %s", i, err) continue } if !isValid { t.Errorf("%d-2: Verify: unexpected failure on plain=%q encoded=%q, encoding=%q", i, plain, encoded, r.encoding) continue } } } }
func TestKey(t *testing.T) { for i, v := range good { err := setConfig(len(v.output), len(v.salt), v.N, v.r, v.p) if err != nil { t.Errorf("%d: unexpected error setting config: %s", i, err) } setSalt(v.salt) encoded, err := mcf.Create(v.password) if err != nil { t.Errorf("%d: got unexpected error: %s", i, err) } passwd := password.New([]byte("scrypt")) err = passwd.Parse([]byte(encoded)) if err != nil { t.Errorf("%d: unexpected error creating password instance: %s", err) } if !bytes.Equal(passwd.Salt, []byte(v.salt)) { t.Errorf("%d: salt: expected %s, got %s", i, v.salt, string(passwd.Salt)) } if !bytes.Equal(passwd.Key, v.output) { t.Errorf("%d: expected %x, got %x", i, v.output, passwd.Key) } } for i, v := range bad { err := setConfig(32, len(v.salt), v.N, v.r, v.p) if err == nil { t.Errorf("%d: expected error, got nil", i) } setSalt(v.salt) _, err = mcf.Create(v.password) if err == nil { t.Errorf("%d: expected error, got nil", i) } } }
func roundTrip(t *testing.T, plaintext string) { encoded, err := mcf.Create(plaintext) if err != nil { t.Fatal(err) } ok, err := mcf.Verify(plaintext, encoded) if err != nil { t.Fatal(err) } if !ok { t.Fatalf("Verify(%q, %q) failed", plaintext, encoded) } }
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 } } } }
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 } } } }