Created
September 23, 2021 16:27
-
-
Save markscottwright/06957001e4e772c8db0ff21834e23d8d to your computer and use it in GitHub Desktop.
How to do a totp in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.security.InvalidKeyException; | |
import java.security.NoSuchAlgorithmException; | |
import java.time.Instant; | |
import javax.crypto.Mac; | |
import javax.crypto.spec.SecretKeySpec; | |
import org.apache.commons.codec.binary.Base32; | |
/** | |
* Needs: | |
* <pre> {@code | |
* <dependency> | |
* <groupId>commons-codec</groupId> | |
* <artifactId>commons-codec</artifactId> | |
* <version>1.15</version> | |
* </dependency> | |
* } </pre> | |
*/ | |
public class Totp { | |
private int timeStepSizeSeconds = 30; | |
private int numberOfDigits = 6; | |
public String totp(String code) throws NoSuchAlgorithmException, InvalidKeyException { | |
return hotp(code, Math.floorDiv(Instant.now().getEpochSecond(), timeStepSizeSeconds), numberOfDigits); | |
} | |
public static String hotp(String keyString, long counter, int digits) throws NoSuchAlgorithmException, InvalidKeyException { | |
byte[] key = new Base32().decode(keyString); | |
byte[] counterBytes = ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putLong(counter).array(); | |
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA1"); | |
Mac mac = Mac.getInstance("HmacSHA1"); | |
mac.init(keySpec); | |
byte[] macValue = mac.doFinal(counterBytes); | |
int offset = macValue[macValue.length - 1] & 0x0f; | |
int binary = ByteBuffer.wrap(macValue, offset, 4).order(ByteOrder.BIG_ENDIAN).getInt() & 0x7fffffff; | |
String otp = Integer.toString(binary); | |
return otp.substring(otp.length() - digits); | |
} | |
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException { | |
String base32Secret = args[0]; | |
System.out.println(new Totp().totp(base32Secret)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment