code: func decodeHash(hash []byte) (Params, []byte, []byte, error) {
  	vals := strings.Split(string(hash), "$")
  
  	// P, N, R, salt, scrypt derived key
  	if len(vals) != 5 {
  		return Params{}, nil, nil, ErrInvalidHash
  	}
  
  	var params Params
  	var err error
  
  	params.N, err = strconv.Atoi(vals[0])
  	if err != nil {
  		return params, nil, nil, ErrInvalidHash
  	}
  
  	params.R, err = strconv.Atoi(vals[1])
  	if err != nil {
  		return params, nil, nil, ErrInvalidHash
  	}
  
  	params.P, err = strconv.Atoi(vals[2])
  	if err != nil {
  		return params, nil, nil, ErrInvalidHash
  	}
  
  	salt, err := hex.DecodeString(vals[3])
  	if err != nil {
  		return params, nil, nil, ErrInvalidHash
  	}
  	params.SaltLen = len(salt)
  
  	dk, err := hex.DecodeString(vals[4])
  	if err != nil {
  		return params, nil, nil, ErrInvalidHash
  	}
  	params.DKLen = len(dk)
  
  	if err := params.Check(); err != nil {
  		return params, nil, nil, err
  	}
  
  	return params, salt, dk, nil
  }
docs: // decodeHash extracts the parameters, salt and derived key from the
  // provided hash. It returns an error if the hash format is invalid and/or
  // the parameters are invalid.