title: Should I use == for string comparison?
body: <p>sorry if this is a weird question.</p>
  <p>I was actually curious about timing attacks, so I have done a little research and understood the concept. I understood that, code like:</p>
  <pre><code>if token == password:
      print('Welcome')
  else:
      print('Wrong password')
  </code></pre>
  <p>is equivalent to:</p>
  <pre><code>def equal(s1, s2):
      if len(s1) != len(s2):
          return False
  
      for i in range(len(s1)):
          if s1[i] != s2[i]:
              return False
      return True
  </code></pre>
  <p><strong>PS - I am using python 3.9.2</strong></p>
  <p>So I have crafted a vulnerable code which looks like this:-</p>
  <pre><code>f = open('pass.txt', 'r')
  password = f.read()
  f.close()
  
  def equal(s1, s2):
      if len(s1) != len(s2):
          return False
  
      for i in range(len(s1)):
          if s1[i] != s2[i]:
              return False
      return True
  
  def login(upass):
      if equal(upass, password):
          print('Login successful')
      else:
          print('Login failed')
  
  login()
  </code></pre>
  <p>This simple program will compare the user's given password (via the <code>upass</code> parameter) with the password stored in the file <em>pass.txt</em> in the same directory. If the password matches then it will greet the user with a welcome message, otherwise, it will alert the user that the login has failed.</p>
  <p>Assumptions:-</p>
  <ol>
  <li>Password is 4 characters long.</li>
  <li>It is ONLY uppercase alphabets (no numeric values or special characters).</li>
  </ol>
  <p>I was able to exploit the password by using the below method:-</p>
  <pre><code>def attack():
  
      leaked = ''
  
      for i in range(4):
  
          result = { letter : 0 for letter in ascii_uppercase }
  
          for _ in range(50000):
              for letter in ascii_uppercase:
                  string = leaked + letter + '.' * ( 4 - len(leaked) - len(letter) )
                  start = time_ns()
                  login(string)
                  end = time_ns()
                  result[letter] += end - start
  
          leaked += sorted(result.items(), key = lambda item : item[1], reverse=True)[0][0]
          print(leaked)
  
  </code></pre>
  <p>I got the output as <code>TEST</code> which is correct. However, you can clearly see that I am not using <code>==</code> for string comparasion, in fact I am using its equivalent method. So I decided to switch back to <code>==</code> and check if my exploit is working. So I modified the <code>equal()</code> method to this:-</p>
  <pre><code>def equal(s1, s2):
      # if len(s1) != len(s2):
      #   return False
  
      # for i in range(len(s1)):
      #   if s1[i] != s2[i]:
      #       return False
      # return True
  
      if s1 == s2:
          return True
      else:
          return False
  </code></pre>
  <p>So using this code, when I called the <code>attack</code> method, to my surprise it gave me pretty weird results. I was given the following output when I ran it multiple times: <code>AOAD</code>, <code>BVCB</code> &amp; <code>LGAZ</code>. This is clearly NOT the password stored in the <em>pass.txt</em> file.</p>
  <p>So my question is, is <code>==</code> not vulnerable to timing attacks?</p>