Skip to content

Commit

Permalink
Merge pull request #79 from vargusz/master
Browse files Browse the repository at this point in the history
Make the number of secret bits configurable
  • Loading branch information
emcrisostomo authored Oct 23, 2019
2 parents 54685db + 49c99db commit 895efb9
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,6 @@ public final class GoogleAuthenticator implements IGoogleAuthenticator
*/
private static final Logger LOGGER = Logger.getLogger(GoogleAuthenticator.class.getName());

/**
* The number of bits of a secret key in binary form. Since the Base32
* encoding with 8 bit characters introduces an 160% overhead, we just need
* 80 bits (10 bytes) to generate a 16 bytes Base32-encoded secret key.
*/
private static final int SECRET_BITS = 80;

/**
* Number of digits of a scratch code represented as a decimal integer.
*/
Expand Down Expand Up @@ -340,13 +333,14 @@ private byte[] decodeSecret(String secret)
public GoogleAuthenticatorKey createCredentials()
{
// Allocating a buffer sufficiently large to hold the bytes required by
// the secret key and the scratch codes.
byte[] buffer = new byte[SECRET_BITS / 8];
// the secret key.
int bufferSize = config.getSecretBits() / 8;
byte[] buffer = new byte[bufferSize];

secureRandom.nextBytes(buffer);

// Extracting the bytes making up the secret key.
byte[] secretKey = Arrays.copyOf(buffer, SECRET_BITS / 8);
byte[] secretKey = Arrays.copyOf(buffer, bufferSize);
String generatedKey = calculateSecretKey(secretKey);

// Generating the verification code at time = 0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class GoogleAuthenticatorConfig
private int codeDigits = 6;
private int numberOfScratchCodes = 5;
private int keyModulus = (int) Math.pow(10, codeDigits);
private int secretBits = 80;
private KeyRepresentation keyRepresentation = KeyRepresentation.BASE32;
private HmacHashFunction hmacHashFunction = HmacHashFunction.HmacSHA1;

Expand Down Expand Up @@ -113,6 +114,17 @@ public int getWindowSize()
return windowSize;
}

/**
* Returns the number of bits of the secret keys to generate. The length should always be a
* multiple of 8. The default value is 80 bits for historical reasons and backwards
* compatibility. RFC 4226 §4 requires 128 bits and recommends 160 bits.
*
* @return the secret size in bits.
*/
public int getSecretBits() {
return secretBits;
}

/**
* Returns the cryptographic hash function used to calculate the HMAC (Hash-based
* Message Authentication Code). This implementation uses the SHA1 hash
Expand Down Expand Up @@ -195,6 +207,21 @@ public GoogleAuthenticatorConfigBuilder setWindowSize(int windowSize)
return this;
}

public GoogleAuthenticatorConfigBuilder setSecretBits(int secretBits)
{
if (secretBits <= 0)
{
throw new IllegalArgumentException("Secret bits must be positive.");
}
if (secretBits % 8 != 0)
{
throw new IllegalArgumentException("Secret bits must be a multiple of 8.");
}

config.secretBits = secretBits;
return this;
}

public GoogleAuthenticatorConfigBuilder setKeyRepresentation(KeyRepresentation keyRepresentation)
{
if (keyRepresentation == null)
Expand Down

0 comments on commit 895efb9

Please sign in to comment.