BastiaanJansen / otp-java

A small and easy-to-use one-time password generator library for Java implementing RFC 4226 (HOTP) and RFC 6238 (TOTP).
MIT License
186 stars 30 forks source link

HMAC SHA 256 for TOTP verification #78

Closed Kachopsticks closed 8 months ago

Kachopsticks commented 11 months ago

Hello, I was able to get the following code working.

TOTPGenerator totpGen = new TOTPGenerator.Builder(myKey) .withHOTPGenerator(builder -> { builder.withPasswordLength(6); builder.withAlgorithm(HMACAlgorithm.SHA1); }) .withPeriod(Duration.ofSeconds(30)) .build();

Since SHA1 is deprecated I wanted to switch to SHA256. I switched to use your SecretGenerator class for this like so...

byte[] secretKeyBytes = SecretGenerator.generate(256); Base32 base32 = new Base32(); String secretKey = base32.encodeAsString(secretKeyBytes);

This secret key is added to my otp string like so. I have set the algorithm to SHA256. I have tried keeping the secret as is, and removing the padding.

otpauth://totp/testCreator:user?secret=KJFVIRCKGRLVERRUI4ZUEMSUJQ2TIR2CJNITGMSQKI2FQR2JKNATMVKPGZDEOVSJG5LEENRWLJKFAWSUI5AT2PJ5HU&issuer=testCreator&algorithm=SHA256

otpauth://totp/testCreator:user?secret=LJEU4RJXIJMUWSSHINLDON2ZKRME2TKLJZCEKSSVLI2UYVKCI5LTOU2SKNMVISBSKBFVCT2IKBBEYM2FGRIT2PJ5HU======&issuer=testCreator&algorithm=SHA256

When I switch my validation code to use SHA256 as written below my codes never validate. I am guessing this is user error but if you have any ideas or an example it would be most appreciated.

TOTPGenerator totpGen = new TOTPGenerator.Builder(myKey) .withHOTPGenerator(builder -> { builder.withPasswordLength(6); builder.withAlgorithm(HMACAlgorithm.SHA256); }) .withPeriod(Duration.ofSeconds(30)) .build();

Thanks!

BastiaanJansen commented 10 months ago

Both your opthauth uri's work fine when i try to validate the generated codes.

However I am not sure what you are doing with your secret. You shouldn't Base32 encode your secret. You can directly use the generated secret bytes, or create your own secret like this:

byte[] secret = "this-is-my-secret".getBytes();
Kachopsticks commented 8 months ago

Apologies for the late reply. After further testing I believe it was the authenticator app I was using not being compatible with HMAC SHA 256. Your library worked fine with the google authenticator app. The Microsoft Authenticator does not seem to work with HMAC SHA 256.