public final byte[] deriveRawKey(int cost, byte[] salt, byte[] psw) {
//        if (salt.length != 16) {
//            throw new DataLengthException("Invalid salt size: 16 bytes expected.");
//        }
        if (cost < 4 || cost > 31) {
            throw new IllegalArgumentException("Illegal cost factor: 4 - 31 expected.");
        }

        if (psw.length == 0) {
            psw = new byte[4];
        }

        // state <- InitState()
        initState();

        int[] salt32Bit = new int[4]; // holds 16 byte salt
        Pack.bigEndianToInt(salt, 0, salt32Bit);

        int[] salt32Bit2 = new int[SALT_SIZE_BYTES]; // swapped values
        salt32Bit2[0] = salt32Bit[2];
        salt32Bit2[1] = salt32Bit[3];
        salt32Bit2[2] = salt32Bit[0];
        salt32Bit2[3] = salt32Bit[1];

        // ExpandKey( state, salt, key):
        cyclicXorKey(psw, psw.length);
        processTableWithSalt(P, salt32Bit, 0, 0);
        Arrays.fill(salt32Bit, 0);
        processTableWithSalt(S, salt32Bit2, P[P.length - 2], P[P.length - 1]);
        Arrays.fill(salt32Bit2, 0);

        int rounds = 1 << cost;
        for (int i = 0; i != rounds; i++) // rounds may be negative if cost is 31
        {
            // state <- ExpandKey(state, 0, key);
            cyclicXorKey(psw, psw.length);
            processTable(0, 0, P);
            processTable(P[P_SZ - 2], P[P_SZ - 1], S);

            // state <- ExpandKey(state, 0, salt);
            cyclicXorKey(salt, SALT_SIZE_BYTES);
            processTable(0, 0, P);
            processTable(P[P_SZ - 2], P[P_SZ - 1], S);
        }

        // encrypt magicString 64 times
        return encryptMagicString();
    }
Derives a raw 192 bit Bcrypt key

@param cost the cost factor, treated as an exponent of 2
@param salt a 16 byte salt
@param psw  the password
@return a 192 bit key
turms-server-common/src/main/java/org/bouncycastle/crypto/generators/BCrypt.java