public static byte[] generateEncryptedMPPEPassword(byte[] input, int room, byte[] secret, byte[] vector) {
		final int authVectorLength = 16;
		final int authPasswordLength = authVectorLength;
		final int maxStringLength = 254;

		// NOTE This could be dodgy!
		int saltOffset = 0;

		// byte digest[] = new byte[authVectorLength];
		byte passwd[] = new byte[maxStringLength + authVectorLength];
		int len;

		/*
		 * Be paranoid.
		 */
		if (room > 253)
			room = 253;

		/*
		 * Account for 2 bytes of the salt, and round the room available down to
		 * the nearest multiple of 16. Then, subtract one from that to account
		 * for the length byte, and the resulting number is the upper bound on
		 * the data to copy.
		 * 
		 * We could short-cut this calculation just be forcing inlen to be no
		 * more than 239. It would work for all VSA's, as we don't pack multiple
		 * VSA's into one attribute.
		 * 
		 * However, this calculation is more general, if a little complex. And
		 * it will work in the future for all possible kinds of weird attribute
		 * packing.
		 */
		room -= 2;
		room -= (room & 0x0f);
		room--;

		int inlen = input.length;
		
		if (inlen > room)
			inlen = room;

		/*
		 * Length of the encrypted data is password length plus one byte for the
		 * length of the password.
		 */
		len = inlen + 1;
		if ((len & 0x0f) != 0) {
			len += 0x0f;
			len &= ~0x0f;
		}

		/*
		 * Copy the password over.
		 */
		System.arraycopy(input, 0, passwd, 3, inlen);
		// memcpy(passwd + 3, input, inlen);
		for (int i = 3 + inlen; i < passwd.length - 3 - inlen; i++) {
			passwd[i] = 0;
		}
		// memset(passwd + 3 + inlen, 0, passwd.length - 3 - inlen);

		/*
		 * Generate salt. The RFC's say:
		 * 
		 * The high bit of salt[0] must be set, each salt in a packet should be
		 * unique, and they should be random
		 * 
		 * So, we set the high bit, add in a counter, and then add in some
		 * CSPRNG data. should be OK..
		 */
		passwd[0] = (byte) (0x80 | (((saltOffset++) & 0x0f) << 3) | (random.generateSeed(1)[0] & 0x07));
		passwd[1] = random.generateSeed(1)[0];
		passwd[2] = (byte) inlen; /* length of the password string */

		MessageDigest md5Digest = null;
		MessageDigest originalDigest = null;
		
		MessageDigest currentDigest = null;

		try {
			md5Digest = MessageDigest.getInstance("MD5");
			originalDigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException nsae) {
			throw new RuntimeException("md5 digest not available", nsae);
		}

		md5Digest.update(secret);
		originalDigest.update(secret);

		currentDigest = md5Digest;

		md5Digest.update(vector, 0, authVectorLength);
		md5Digest.update(passwd, 0, 2);

		for (int n = 0; n < len; n += authPasswordLength) {
			if (n > 0) {
				currentDigest = originalDigest;

				currentDigest.update(passwd, 2 + n - authPasswordLength, authPasswordLength);
			}

			byte digest[] = currentDigest.digest();

			for (int i = 0; i < authPasswordLength; i++) {
				passwd[i + 2 + n] ^= digest[i];
			}
		}
		byte output[] = new byte[len + 2];
		System.arraycopy(passwd, 0, output, 0, len + 2);

		return output;
	}