code: public static String generateAes128KeyWithSeed(String seed) {
      String returnKey = null;
  
      try {
        SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[16];
        rand.nextBytes(salt);
        PBEKeySpec password = new PBEKeySpec(seed.toCharArray(), salt, 1000, 128);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKey key = (PBEKey) factory.generateSecret(password);
        SecretKey secretKey = new SecretKeySpec(key.getEncoded(), "AES");
  
        StringBuffer keyBuffer = new StringBuffer();
        for (byte b : secretKey.getEncoded()) {
          int i = Integer.parseInt(String.format("%d", b));
          int j = (Math.abs(i) % 54) + 40; // A chunk of the ASCII table.
  
          // Clean up a few characters that could be problematic in JSON
          // or a query parameter. Others should be URL encoded by the user.
          switch (j) {
            case 47:
              // Replace '/' with '!'.
              j = 33;
              break;
            case 61:
              // Replace '=' with 'z'.
              j = 122;
            case 92:
              // Replace '\' with '#'.
              j = 35;
              break;
          }
  
          keyBuffer.append((char) j);
        }
        returnKey = keyBuffer.toString();
      } catch (InvalidKeySpecException e) {
        log.error("Could not find desired key specificatio.");
        log.debug(e.toString());
      } catch (NoSuchAlgorithmException e) {
        log.error("Could not find encryption algorithm.");
        log.debug(e.toString());
      }
  
      return returnKey;
    }
docs: Returns an ASCII string that can be used for encrypting/decrypting
  data with the AES-128 algorithm. The given seed <strong>does not</strong>
  guarantee the same result for subsequent invocations.
  
  @param seed A string to seed the generator with.
  @return A unique ASCII string that can be used as an AES-128 key, or null.