import java.util.*; // Design an experiment to demonstrate the timing attack. Test if the // bad version of the password-check method takes less time if the password // doesn't match, and more time if the password does match. Also test if // the good version eliminates this bug. Use strings of length 10 or longer. public class TimingAttack { public static void main(String[] args) { // Put your code here. } // Pre: password and userInput are not null. // Checks the given userInput and password with the bad password-check // method, returning the time (in nanoseconds) that it took the method // to run. public static long timeBadCheckPassword(String password, String userInput) { long start = System.nanoTime(); boolean match = badCheckPassword(password, userInput); long end = System.nanoTime(); return end - start; } // Pre: password and userInput are not null. // Checks the given userInput and password with the good password-check // method, returning the time (in nanoseconds) that it took the method // to run. public static long timeGoodCheckPassword(String password, String userInput) { long start = System.nanoTime(); boolean match = goodCheckPassword(password, userInput); long end = System.nanoTime(); return end - start; } // Pre: password and userInput are not null. // Checks whether the user-given string userInput matches the actual // password. BAD VERSION. Vulnerable to a timing attack. public static boolean badCheckPassword(String password, String userInput) { if (password.length() != userInput.length()) { return false; } for (int i = 0; i < userInput.length(); i++) { if (password.charAt(i) != userInput.charAt(i)) { return false; } } return true; } // Pre: password and userInput are not null. // Checks whether the user-given string userInput matches the actual // password. GOOD VERSION. public static boolean goodCheckPassword(String password, String userInput) { boolean result = true; if (password.length() != userInput.length()) { result = false; } for (int i = 0; i < userInput.length(); i++) { boolean noMatch = password.charAt(Math.min(i, password.length())) != userInput.charAt(i); if (i < userInput.length() && noMatch) { result = false; } } return result; } }