Skip to content

Commit 01c4135

Browse files
committed
Use ByteBuffer again for improved clarity
1 parent 33f2208 commit 01c4135

File tree

2 files changed

+20
-22
lines changed

2 files changed

+20
-22
lines changed

src/main/java/com/eatthepath/otp/HmacOneTimePasswordGenerator.java

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import javax.crypto.Mac;
2424
import javax.crypto.ShortBufferException;
25+
import java.nio.ByteBuffer;
2526
import java.security.InvalidKeyException;
2627
import java.security.Key;
2728
import java.security.NoSuchAlgorithmException;
@@ -39,7 +40,7 @@ public class HmacOneTimePasswordGenerator {
3940
private final Mac mac;
4041
private final int passwordLength;
4142

42-
private final byte[] buffer;
43+
private final ByteBuffer buffer;
4344
private final int modDivisor;
4445

4546
private final String formatString;
@@ -121,7 +122,7 @@ protected HmacOneTimePasswordGenerator(final int passwordLength, final String al
121122
}
122123

123124
this.passwordLength = passwordLength;
124-
this.buffer = new byte[this.mac.getMacLength()];
125+
this.buffer = ByteBuffer.allocate(this.mac.getMacLength());
125126
}
126127

127128
/**
@@ -136,34 +137,23 @@ protected HmacOneTimePasswordGenerator(final int passwordLength, final String al
136137
* @throws InvalidKeyException if the given key is inappropriate for initializing the {@link Mac} for this generator
137138
*/
138139
public synchronized int generateOneTimePassword(final Key key, final long counter) throws InvalidKeyException {
139-
this.mac.init(key);
140-
141-
this.buffer[0] = (byte) ((counter & 0xff00000000000000L) >>> 56);
142-
this.buffer[1] = (byte) ((counter & 0x00ff000000000000L) >>> 48);
143-
this.buffer[2] = (byte) ((counter & 0x0000ff0000000000L) >>> 40);
144-
this.buffer[3] = (byte) ((counter & 0x000000ff00000000L) >>> 32);
145-
this.buffer[4] = (byte) ((counter & 0x00000000ff000000L) >>> 24);
146-
this.buffer[5] = (byte) ((counter & 0x0000000000ff0000L) >>> 16);
147-
this.buffer[6] = (byte) ((counter & 0x000000000000ff00L) >>> 8);
148-
this.buffer[7] = (byte) (counter & 0x00000000000000ffL);
149-
150-
this.mac.update(this.buffer, 0, 8);
140+
this.buffer.clear();
141+
this.buffer.putLong(0, counter);
151142

152143
try {
153-
this.mac.doFinal(this.buffer, 0);
144+
final byte[] array = this.buffer.array();
145+
146+
this.mac.init(key);
147+
this.mac.update(array, 0, 8);
148+
this.mac.doFinal(array, 0);
154149
} catch (final ShortBufferException e) {
155150
// We allocated the buffer to (at least) match the size of the MAC length at construction time, so this
156151
// should never happen.
157152
throw new RuntimeException(e);
158153
}
159154

160-
final int offset = this.buffer[this.buffer.length - 1] & 0x0f;
161-
162-
return ((this.buffer[offset] & 0x7f) << 24 |
163-
(this.buffer[offset + 1] & 0xff) << 16 |
164-
(this.buffer[offset + 2] & 0xff) << 8 |
165-
(this.buffer[offset + 3] & 0xff)) %
166-
this.modDivisor;
155+
final int offset = this.buffer.get(this.buffer.capacity() - 1) & 0x0f;
156+
return (this.buffer.getInt(offset) & 0x7fffffff) % this.modDivisor;
167157
}
168158

169159
/**

src/test/java/com/eatthepath/otp/HmacOneTimePasswordGeneratorTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ void testGenerateOneTimePassword(final int counter, final int expectedOneTimePas
7979
assertEquals(expectedOneTimePassword, this.getDefaultGenerator().generateOneTimePassword(HOTP_KEY, counter));
8080
}
8181

82+
@Test
83+
void testGenerateOneTimePasswordRepeated() throws Exception {
84+
final HmacOneTimePasswordGenerator hotpGenerator = new HmacOneTimePasswordGenerator();
85+
86+
assertEquals(755224, hotpGenerator.generateOneTimePassword(HOTP_KEY, 0));
87+
assertEquals(287082, hotpGenerator.generateOneTimePassword(HOTP_KEY, 1));
88+
}
89+
8290
private static Stream<Arguments> argumentsForTestGenerateOneTimePasswordHotp() {
8391
return Stream.of(
8492
arguments(0, 755224),

0 commit comments

Comments
 (0)