Do I really weaken the password?
To some degree, yes.
The function is considered public, and the attacker can test random passwords with it and check the output and compare it to your key. Then he finds the correct password, even if he actually just guessed one of those permutations you defined. In your example:
- Actual password is carphagen
- The key is: key is $Key = Key1 + Key2 + . . . + KeyN$
- The attacker tries the password ncarphage, which is the passwords permutation to generate $Key2$.
- The attacker gets as output: $Key2+\dots$.
- He still can easily detect that the partial key is the same as in the given output, even if it's not at the same location.
One more thing to consider: Your idea takes $N$ times the computation time of a single BCrypt call. But an attacker can actually check one password with a single call to BCrypt (if he's not interested in checking the permutated passwords). And that's quite bad - testing a password for the attacker surely should not be less than regular usage.
Here's an alternative idea:
- Use BCrypt to generate $k_0$ from your password - with enough iterations that it fits your requirements.
- Use a different key derivation function to generate values $k_1,k_2,k_3,\dots$, by using $k_0$ and a counter as input. If the function utilizes iterations, just use one.
- If you want to increase the computation time, increase the number of iterations to generate $k_0$, don't apply them to the computation of $k_1,k_2,\dots$ .
For the second step, there are various possibilities for a KDF. For example you could use a keyed hash function (also called MAC), a CSPRNG seeded with $k_0$, a PRF, ...
A second alternative: Use another password-based KDF, which supports variable length output. BCrypt is quite old and there are more recent alternatives, two examples would be Argon2 or scrypt.