Closed OlivierJaquemet closed 4 years ago
I think their are 2 problems here.
App makers are not clear on whether they support SHA-256/512 and I personally I think the getDigitsFromHash function in the DefaultCodeGenerator has an error for SHA-256/512.
I used oathtool to verify the results, and I also couldn't make it work. (SHA-1 matched, SHA-256/512 did not) I eventually replaced it with the below which I took from the similiar aerogear function, this then matched the oathttool for all hash types.
private String getDigitsFromHash(byte[] hash) {
// put selected bytes into result int
int offset = hash[hash.length - 1] & 0xf;
int binary = ((hash[offset] & 0x7f) << 24) |
((hash[offset + 1] & 0xff) << 16) |
((hash[offset + 2] & 0xff) << 8) |
(hash[offset + 3] & 0xff);
return String.format("%0" + digits + "d", binary % (int) Math.pow(10, digits));
}
Back to your first question, apps that I have verified working with at SHA-256 after this change are
Android
iOS
And apps that appear to not support SHA-256
And what I found most annoying is that these apps fail silently back to SHA-1, without erroring. So we've had to put a warning on our setup pages to not use them.
Thanks for raising the issue @OlivierJaquemet and for your investigation/fix @Stexxen !
Will try and get some unit tests in place for all the different hash types and make a fix if needed as soon as I can.
I have this small test for SHA-256 if its any help? oathtool result
~ % oathtool --totp=sha256 --now="2019-09-04 21:12:16 UTC" --digits=6 --base32 W3C5B3WKR4AUKFVWYU2WNMYB756OAKWY
272978
~ % oathtool --totp=sha256 --now="2019-09-04 21:12:16 UTC" --digits=8 --base32 W3C5B3WKR4AUKFVWYU2WNMYB756OAKWY
76272978
and the Test Case
@Test
public void testSHA256Result() {
// 2019-09-04 21:12:16 UTC
int time = 1567631536;
long currentBucket = Math.floorDiv(time, 30);
CodeGenerator g = new DefaultCodeGenerator(HashingAlgorithm.SHA256);
String code = g.generate("W3C5B3WKR4AUKFVWYU2WNMYB756OAKWY", currentBucket);
assertEquals("272978", code);
g = new DefaultCodeGenerator(HashingAlgorithm.SHA256, 8);
code = g.generate("W3C5B3WKR4AUKFVWYU2WNMYB756OAKWY", currentBucket);
assertEquals("76272978", code);
}
Awesome work @Stexxen, thank you !
Thank you @samdjstevens for taking the time to maintain your project. If I can help, do not hesitate to ask.
I've just pushed a fix for this to master with some unit tests that should hopefuly ensure it's working for all hashing algorithms. Please do have a look over if you can, and if all good I will publish v1.7 shortly.
Thanks!
Ahhh that's the problem was it. My binary maths was just not up to the challenge of working out what was wrong...
Thanks for fixing 👍
Just released v1.6.1 to maven central with this fix
Great work. Version 1.6.1 tested and approved. :) Other hashing algorithm are working perfectly fine with FreeOTP, andOTP and KeePassXC 👍🏻 Thanks again.
Were you able to successfully use hashing algorithm other than SHA-1 with any application ? I could not...
I have tested the following application and I could not make it work :
On Android :
On Windows :
Do you known any application supporting hashing algorithm other than SHA-1 ?