func decryptKey(masterPwd []byte, encryptedKey []byte, salt []byte, iterCount int, validation []byte) ([]byte, error) { const keyLen = 32 derivedKey := pbkdf2.Key(masterPwd, salt, iterCount, keyLen, sha1.New) aesKey := derivedKey[0:16] iv := derivedKey[16:32] decryptedKey, err := aesCbcDecrypt(aesKey, encryptedKey, iv) if err != nil { return nil, err } validationSalt, validationCipherText, err := extractSaltAndCipherText(validation) if err != nil { return nil, fmt.Errorf("Invalid validation: %v", err) } validationAesKey, validationIv := openSslKey(decryptedKey, validationSalt) decryptedValidation, err := aesCbcDecrypt(validationAesKey, validationCipherText, validationIv) if err != nil { return nil, fmt.Errorf("Failed to decrypt validation: %v", err) } if string(decryptedValidation) != string(decryptedKey) { return nil, errors.New("Validation decryption failed") } return decryptedKey, nil }
// Generates a shared secret key between us and the given public key. func (p *Peer) Secret(pubKey []byte, size int) ([]byte, error) { // Verify and unpack node's public key. curveSize := p.curve.Params().BitSize if len(pubKey) != (curveSize / 2) { return nil, errors.New("Malformed public key.") } bound := (curveSize / 8) x := big.NewInt(0) y := big.NewInt(0) x.SetBytes(pubKey[0:bound]) y.SetBytes(pubKey[bound : bound*2]) if !p.curve.IsOnCurve(x, y) { return nil, errors.New("Invalid public key.") } // Generate shared secret. secret, _ := p.curve.ScalarMult(x, y, p.hellman) // Use PDKDF2 to make uniform in 2^256. dk := pbkdf2.Key(secret.Bytes(), salt, 4096, size, sha256.New) return dk, nil }
// Generates a derived key based on a salt. rails default key size is 64. func (g *KeyGenerator) Generate(salt []byte, keySize int) []byte { // set a default if g.Iterations == 0 { g.Iterations = 1000 // rails 4 default when setting the session. } return pbkdf2.Key([]byte(g.Secret), salt, g.Iterations, keySize, sha1.New) }
// Create a new encryption key and encrypt it using the user-provided // passphrase. Prints output to stdout that gives text to add to the // ~/.skicka.config file to store the encryption key. func generateKey() { passphrase := os.Getenv(passphraseEnvironmentVariable) if passphrase == "" { printErrorAndExit(fmt.Errorf(passphraseEnvironmentVariable + " environment variable not set.")) } // Derive a 64-byte hash from the passphrase using PBKDF2 with 65536 // rounds of SHA256. salt := getRandomBytes(32) hash := pbkdf2.Key([]byte(passphrase), salt, 65536, 64, sha256.New) if len(hash) != 64 { printErrorAndExit(fmt.Errorf("incorrect key size returned by pbkdf2 %d", len(hash))) } // We'll store the first 32 bytes of the hash to use to confirm the // correct passphrase is given on subsequent runs. passHash := hash[:32] // And we'll use the remaining 32 bytes as a key to encrypt the actual // encryption key. (These bytes are *not* stored). keyEncryptKey := hash[32:] // Generate a random encryption key and encrypt it using the key // derived from the passphrase. key := getRandomBytes(32) iv := getRandomBytes(16) encryptedKey := encryptBytes(keyEncryptKey, iv, key) fmt.Printf("; Add the following lines to the [encryption] section\n") fmt.Printf("; of your ~/.skicka.config file.\n") fmt.Printf("\tsalt=%s\n", hex.EncodeToString(salt)) fmt.Printf("\tpassphrase-hash=%s\n", hex.EncodeToString(passHash)) fmt.Printf("\tencrypted-key=%s\n", hex.EncodeToString(encryptedKey)) fmt.Printf("\tencrypted-key-iv=%s\n", hex.EncodeToString(iv)) }
// Decrypts the encrypted encryption key using values from the config file // and the user's passphrase. func decryptEncryptionKey() []byte { if key != nil { panic("key aready decrypted!") } salt := decodeHexString(config.Encryption.Salt) passphraseHash := decodeHexString(config.Encryption.Passphrase_hash) encryptedKey := decodeHexString(config.Encryption.Encrypted_key) encryptedKeyIv := decodeHexString(config.Encryption.Encrypted_key_iv) passphrase := os.Getenv(passphraseEnvironmentVariable) if passphrase == "" { fmt.Fprintf(os.Stderr, "skicka: "+passphraseEnvironmentVariable+ " environment variable not set") os.Exit(1) } derivedKey := pbkdf2.Key([]byte(passphrase), salt, 65536, 64, sha256.New) // Make sure the first 32 bytes of the derived key match the bytes stored // when we first generated the key; if they don't, the user gave us // the wrong passphrase. if !bytes.Equal(derivedKey[:32], passphraseHash) { fmt.Fprintf(os.Stderr, "skicka: incorrect passphrase") os.Exit(1) } // Use the last 32 bytes of the derived key to decrypt the actual // encryption key. keyEncryptKey := derivedKey[32:] return decryptBytes(keyEncryptKey, encryptedKeyIv, encryptedKey) }
// NewSession generates and saves a new session for the specified user, with the specified // client name. This function also randomly generates public and private keys. func NewSession(userID int, password string, client string) (*Session, error) { // Generate session session := &Session{ UserID: userID, Client: client, } // Make session expire in one week, without use session.Expire = time.Now().Add(time.Duration(7 * 24 * time.Hour)).Unix() // Generate salts for use with PBKDF2 saltBuf := make([]byte, 16) if _, err := rand.Read(saltBuf); err != nil { return nil, err } salt1 := saltBuf // Use PBKDF2 to generate a session key based off the user's password session.Key = fmt.Sprintf("%x", pbkdf2.Key([]byte(password), salt1, 4096, 16, sha1.New)) // Save session if err := session.Save(); err != nil { return nil, err } return session, nil }
func add(name string, password []byte) error { clipboard.WriteAll(string(password)) p := Password{} p.Salt = randBytes(8) key = pbkdf2.Key(key, p.Salt, 4096, 32, sha1.New) session, err := aes.NewCipher(key) if err != nil { return err } password = pad(password) pass_ciphered := make([]byte, aes.BlockSize+len(password)) iv := pass_ciphered[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return err } mode := cipher.NewCBCEncrypter(session, iv) mode.CryptBlocks(pass_ciphered[aes.BlockSize:], password) p.Pass = pass_ciphered logins[name] = p return nil }
// hashPassword hashes a password using the old method (PBKDF2 + SHA512). // // BUG(fss): this function is deprecated, it's here for the migration phase // (whenever a user login with the old hash, the new hash will be generated). func hashPassword(password string) string { err := loadConfig() if err != nil { panic(err) } salt := []byte(salt) return fmt.Sprintf("%x", pbkdf2.Key([]byte(password), salt, 4096, len(salt)*8, sha512.New)) }
//example hash function func H(to_hash, salt []byte) big.Int { var x big.Int dk := pbkdf2.Key(to_hash, salt, 10000, 128, sha512.New) x.SetBytes(dk) return x }
func CalcHash(pass, salt []byte) *BitBuf { password := pass fmt.Printf("Calculating hash (iters: %v, size: %v)...\n", HashIts, HashLen) d := pbkdf2.Key(password, salt, HashIts, HashLen, sha256.New) //fmt.Println(len(d)) hbuf := bbuf(d) return &BitBuf{src: hbuf.Read} }
// Key derives a key from the password, salt, and cost parameters, returning // a byte slice of length keyLen that can be used as cryptographic key. // // N is a CPU/memory cost parameter, which must be a power of two greater than 1. // r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the // limits, the function returns a nil byte slice and an error. // // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // // dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) // // The recommended parameters for interactive logins as of 2009 are N=16384, // r=8, p=1. They should be increased as memory latency and CPU parallelism // increases. Remember to get a good random salt. func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { if N <= 1 || N&(N-1) != 0 { return nil, errors.New("scrypt: N must be > 1 and a power of 2") } if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { return nil, errors.New("scrypt: parameters are too large") } xy := make([]uint32, 64*r) v := make([]uint32, 32*N*r) b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) for i := 0; i < p; i++ { smix(b[i*128*r:], r, N, v, xy) } return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil }
// creates the master AES key for the user based on their password. func createUserAES(password string) ([]byte, []byte) { salt := make([]byte, 10) // TODO: make 10 a constant variable _, err := rand.Read(salt) if err != nil { fmt.Println("ERROR:", err) } key := pbkdf2.Key([]byte(password), salt, 5000, 32, sha256.New) // TODO: make 5000 a const var return key, salt }
// deriveKey returns the AES key, HMAC-SHA1 key, and key hash for // the given password, salt combination. func deriveKey(password string, salt []byte) (aesKey, hmacKey, keyHash []byte) { const keySize = 16 key := pbkdf2.Key([]byte(password), salt, 4096, 2*keySize, sha1.New) aesKey = key[:keySize] hmacKey = key[keySize:] h := sha1.New() h.Write(key) keyHash = h.Sum(nil)[:4] return }
func (s *S) TestCreateUserHashesThePasswordUsingPBKDF2SHA512AndSalt(c *C) { salt := []byte(salt) expectedPassword := fmt.Sprintf("%x", pbkdf2.Key([]byte("123456"), salt, 4096, len(salt)*8, sha512.New)) u := User{Email: "*****@*****.**", Password: "******"} err := u.Create() c.Assert(err, IsNil) var result User collection := db.Session.Users() err = collection.Find(bson.M{"email": u.Email}).One(&result) c.Assert(err, IsNil) c.Assert(result.Password, Equals, expectedPassword) }
func VerifyCredentials(username, password string) (user_id int64, authenticated bool) { row := db.QueryRow("SELECT id, pwhash, salt FROM users WHERE login = ? LIMIT 1", username) var db_hash []byte var salt []byte if err := row.Scan(&user_id, &db_hash, &salt); err != nil { log.Printf("VerifyCredentials: %v", err) return 0, false } password_hash := pbkdf2.Key([]byte(password), salt, PBKDF2_ROUNDS, PBKDF2_SIZE, sha256.New) return user_id, bytes.Equal(password_hash, db_hash) }
func RegisterUser(username, password string) error { salt, err := GenerateSalt() if err != nil { return err } password_hash := pbkdf2.Key([]byte(password), salt, PBKDF2_ROUNDS, PBKDF2_SIZE, sha256.New) _, err = db.Exec("INSERT INTO users (login, pwhash, salt) VALUES (?, ?, ?)", username, password_hash, salt) if err != nil { log.Printf("RegisterUser: %v", err) } return err }
// UserPasswordHash returns base64-encoded one-way hash password that is // computationally hard to crack by iterating through possible passwords. func UserPasswordHash(password string, salt string) string { if salt == "" { panic("salt is not allowed to be empty") } iter := 8192 if FastInsecureHash { iter = 1 } // Generate 18 byte passwords because we know that MongoDB // uses the MD5 sum of the password anyway, so there's // no point in using more bytes. (18 so we don't get base 64 // padding characters). h := pbkdf2.Key([]byte(password), []byte(salt), iter, 18, sha512.New) return base64.StdEncoding.EncodeToString(h) }
func (s *AuthSuite) TestChangePasswordHandler(c *gocheck.C) { body := bytes.NewBufferString(`{"old":"123","new":"123456"}`) request, err := http.NewRequest("PUT", "/users/password", body) c.Assert(err, gocheck.IsNil) recorder := httptest.NewRecorder() err = ChangePassword(recorder, request, s.user) c.Assert(err, gocheck.IsNil) otherUser := *s.user err = otherUser.Get() c.Assert(err, gocheck.IsNil) hashPassword := func(password string) string { salt := []byte("tsuru-salt") return fmt.Sprintf("%x", pbkdf2.Key([]byte(password), salt, 4096, len(salt)*8, sha512.New)) } expectedPassword := hashPassword("123456") c.Assert(otherUser.Password, gocheck.Equals, expectedPassword) }
// CalibratePBKDF2 returns the estimated number of PBKDF2 iterations required // to derive key of length keyLen with hash function h in the given time. func CalibratePBKDF2(dur time.Duration, h func() hash.Hash, keyLen int) int { // XXX uses block size as input, maybe provide password and salt len? block := make([]byte, h().BlockSize()) start := time.Now() var ns int64 iter := 0 for { pbkdf2.Key(block, block, 1000, keyLen, h) iter += 1000 ns = time.Since(start).Nanoseconds() if ns > 0 { break } } if dur.Nanoseconds()/ns > int64(maxInt/iter) { return maxInt } return iter * int(dur.Nanoseconds()/ns) }
func encryptKey(masterPwd []byte, decryptedKey []byte, salt []byte, iterCount int) ([]byte, []byte, error) { const keyLen = 32 derivedKey := pbkdf2.Key(masterPwd, salt, iterCount, keyLen, sha1.New) aesKey := derivedKey[0:16] iv := derivedKey[16:32] encryptedKey, err := aesCbcEncrypt(aesKey, decryptedKey, iv) if err != nil { return nil, nil, err } validationSalt := randomBytes(8) validationAesKey, validationIv := openSslKey(decryptedKey, validationSalt) validationCipherText, err := aesCbcEncrypt(validationAesKey, decryptedKey, validationIv) if err != nil { return nil, nil, fmt.Errorf("Failed to encrypt validation: %v", err) } validation := []byte("Salted__" + string(validationSalt) + string(validationCipherText)) return encryptedKey, validation, nil }
func main() { pass := fmt.Sprint("ER8FT+HFjk0", "\x01") salt := fmt.Sprint("7DpniYifN6c", "\x01") key, _ := scrypt.Key([]byte(pass), []byte(salt), 262144, 8, 1, 32) pass = fmt.Sprint("ER8FT+HFjk0", "\x02") salt = fmt.Sprint("7DpniYifN6c", "\x02") key2 := pbkdf2.Key([]byte(pass), []byte(salt), 65536, 32, sha256.New) var result bytes.Buffer for i := 0; i < len(key); i++ { result.WriteByte(key[i] ^ key2[i]) } fmt.Printf(hex.EncodeToString(key)) fmt.Printf("\n") fmt.Printf(hex.EncodeToString(key2)) fmt.Printf("\n") fmt.Printf(hex.EncodeToString(result.Bytes())) fmt.Printf("\n") }
func read(name string) error { p, ok := logins[name] if !ok { return fmt.Errorf("no such key") } key = pbkdf2.Key(key, p.Salt, 4096, 32, sha1.New) session, err := aes.NewCipher(key) if err != nil { return err } pass_ciphered := p.Pass iv := pass_ciphered[:aes.BlockSize] pass_ciphered = pass_ciphered[aes.BlockSize:] pass_plain := make([]byte, len(pass_ciphered)) mode := cipher.NewCBCDecrypter(session, iv) mode.CryptBlocks(pass_plain, pass_ciphered) clipboard.WriteAll(string(pass_plain)) return nil }
/* Computes a derived cryptographic key from a password according to PBKDF2 http://en.wikipedia.org/wiki/PBKDF2. The function will only return a derived key if at least 'salt' is present in the 'extra' dictionary. The complete set of attributesthat can be set in 'extra': salt: The salt value to be used. iterations: Number of iterations of derivation algorithm to run. keylen: Key length to derive. returns the derived key or the original secret. */ func deriveKey(secret string, extra map[string]interface{}) string { //Salt needed to derive key if salt, ok := extra["salt"]; ok { iter := 10000 keyLen := 32 //Check for custom values if cIter, ok := extra["iterations"]; ok { iter = cIter.(int) } if cKeylen, ok := extra["keylen"]; ok { keyLen = cKeylen.(int) } dk := pbkdf2.Key([]byte(secret), []byte(salt.(string)), iter, keyLen, sha256.New) key := base64.StdEncoding.EncodeToString(dk) return key } else { //just return secret return secret } }
// Generate a PBKDF password hash. Use 4096 iterations and a 64 byte key. func (t *KitchenUserServlet) generate_password_hash(password, salt []byte) []byte { return pbkdf2.Key(password, salt, 4096, 64, sha256.New) }
func IdentitiesConfirm(identity map[string]interface{}) (map[string]interface{}, *handshakejserrors.LogicError) { app_name, logic_error := checkAppNamePresent(identity) if logic_error != nil { return identity, logic_error } identity["app_name"] = app_name email, logic_error := checkEmailPresent(identity) if logic_error != nil { return identity, logic_error } identity["email"] = email authcode, logic_error := checkAuthcodePresent(identity) if logic_error != nil { return identity, logic_error } identity["authcode"] = authcode app_name_key := "apps/" + identity["app_name"].(string) key := app_name_key + "/identities/" + identity["email"].(string) err := validateAppExists(app_name_key) if err != nil { logic_error := &handshakejserrors.LogicError{"not_found", "app_name", "app_name could not be found"} return identity, logic_error } err = validateIdentityExists(key) if err != nil { logic_error := &handshakejserrors.LogicError{"not_found", "email", "email could not be found"} return identity, logic_error } var r struct { Email string `redis:"email"` AppName string `redis:"app_name"` Authcode string `redis:"authcode"` AuthcodeExpiredAt string `redis:"authcode_expired_at"` } conn := Conn() defer conn.Close() values, err := redis.Values(conn.Do("HGETALL", key)) if err != nil { logic_error := &handshakejserrors.LogicError{"unknown", "", err.Error()} return identity, logic_error } err = redis.ScanStruct(values, &r) if err != nil { logic_error := &handshakejserrors.LogicError{"unknown", "", err.Error()} return identity, logic_error } email = r.Email res_authcode := r.Authcode res_authcode_expired_at := r.AuthcodeExpiredAt current_ms_epoch_time := (time.Now().Unix() * 1000) res_authcode_expired_at_int64, err := strconv.ParseInt(res_authcode_expired_at, 10, 64) if err != nil { logic_error := &handshakejserrors.LogicError{"unknown", "", err.Error()} return identity, logic_error } if len(res_authcode) > 0 && res_authcode == authcode { if res_authcode_expired_at_int64 < current_ms_epoch_time { logic_error := &handshakejserrors.LogicError{"expired", "authcode", "authcode has expired. request another one."} return identity, logic_error } app_salt, err := redis.String(conn.Do("HGET", app_name_key, "salt")) if err != nil { logic_error := &handshakejserrors.LogicError{"unknown", "", err.Error()} return identity, logic_error } app_salt = decrypt(app_salt) hash := pbkdf2.Key([]byte(email), []byte(app_salt), PBKDF2_HASH_ITERATIONS, PBKDF2_HASH_BITES, sha1.New) identity["hash"] = hex.EncodeToString(hash) return identity, nil } else { logic_error := &handshakejserrors.LogicError{"incorrect", "authcode", "the authcode was incorrect"} return identity, logic_error } }
func generateSecret(base, salt string) []byte { return pbkdf2.Key([]byte(base), []byte(salt), key_iter_num, key_size, sha1.New) }
// Key generates a PBKDF2 digest from the password, salt and iteration count, // using the Hash as a pseudorandom function. func (c *Config) Key(password, salt []byte) ([]byte, error) { return pbkdf2.Key(password, salt, c.Iterations, c.KeyLen, hashes[c.Hash]), nil }
// DeriveKeyWithSalt hashes the password with the specified salt. func DeriveKeyWithSalt(password string, salt []byte) (ph *PasswordKey) { key := pbkdf2.Key([]byte(password), salt, IterationCount, KeySize, sha512.New) return &PasswordKey{salt, key} }
func HashPassword(password []byte) ([]byte, error) { // Do not need to provide a salt here, bcrypt will generate one key := pbkdf2.Key(password, []byte(""), 1024, 64, sha512.New) return bcrypt.GenerateFromPassword(key, bcrypt.DefaultCost) }
func NewSeed(mnemonic string, password string) []byte { return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New) }