title: Java - TOTP algorithm, from HMAC SHA1 to HMAC SHA256
body: <p>Small question regarding a TOTP generation algorithm please.</p>
  <p>I am building a TOTP generation algorithm. In order to do so, I am using HMAC SHA1.
  The result is correct, I used many time this HMAC SHA1 generated TOTP to authenticate myself to servers, I had confirmation the TOTP is correct, very happy.</p>
  <p>Now, knowing HMAC SHA1 is a bit less secure, I would like to migrate from HMAC SHA1 to HMAC SHA256.</p>
  <p>I thought I was as simple as changing the HMAC algorithm. Unfortunately, all TOTP generated with HMAC SHA256 were not accepted by the server.</p>
  <p>Just to emphasize, this question is about how to make it work with HMAC SHA256.</p>
  <p>This question is not about:</p>
  <ul>
  <li>how secure is HMAC SHA1</li>
  <li>if it is a good choice to migrate from HMAC SHA1 to HMAC256</li>
  <li>how to change the server to accept HMAC256 generated TOTP.</li>
  </ul>
  <p>This technical question is really about a technical algorithm of TOTP generation with HAMC SHA256.</p>
  <p>The code I use to generate HMAC SHA1 TOTP is:</p>
  <pre><code>String getTOTP() {
          try {
              long value = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / TimeUnit.SECONDS.toMillis(30);
              final byte[] key = new Base32().decode(&quot;the_password&quot;.toUpperCase(Locale.US));
              final var data = new byte[8];
              for (int i = 8; i-- &gt; 0; value &gt;&gt;&gt;= 8) {
                  data[i] = (byte) value;
              }
              final var signKey = new SecretKeySpec(key, &quot;HmacSHA1&quot;); // would like to change here to &quot;HmacSHA256&quot;
              final var mac = Mac.getInstance(&quot;HmacSHA1&quot;); // would like to change here to &quot;HmacSHA256&quot;
              mac.init(signKey);
              final String hashString = new String(new Hex().encode(mac.doFinal(data)));
              final var offset = Integer.parseInt(hashString.substring(hashString.length() - 1), 16);
              final var truncatedHash = hashString.substring(offset * 2, offset * 2 + 8);
              final var finalHash = String.valueOf(Integer.parseUnsignedInt(truncatedHash, 16) &amp; 0x7FFFFFFF);
              final var finalHashCut = finalHash.substring(finalHash.length() - 6);
              System.out.println(&quot;THE TOTP generated with HmacSHA1 is  &quot; + finalHashCut);
              System.out.println(&quot;THE TOTP generated with HmacSHA256 will not work though :'( &quot;);
              return finalHashCut;
          } catch (NoSuchAlgorithmException | InvalidKeyException e) {
              LOGGER.warn(&quot;&quot;, e);
              return &quot;&quot;;
          }
      }
  </code></pre>
  <p>Question: What element of the algorithm should I adjust in order to have the TOTP using HMAC SHA256, and still work please?</p>
  <p>Thank you.</p>