Skip to content

Commit

Permalink
Fix #1656: Enable parameterisation of TOTP (#1676)
Browse files Browse the repository at this point in the history
  • Loading branch information
jnpsk authored Sep 19, 2024
1 parent f2f3484 commit 96208b7
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/Configuration-Properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ The PowerAuth Server uses the following public configuration properties:
| `powerauth.service.secureVault.enableBiometricAuthentication` | `false` | Whether biometric authentication is enabled when accessing Secure Vault |
| `powerauth.server.db.master.encryption.key` | `_empty_` | Master DB encryption key for decryption of server private key in database |
| `powerauth.service.proximity-check.otp.length` | `8` | Length of OTP generated for proximity check |
| `powerauth.service.proximity-check.otp.step-duration` | `30s` | Time-step duration used for generating and validating TOTP for the proximity check. |
| `powerauth.service.proximity-check.otp.step-count` | `1` | Number of past time-steps used for validating TOTP for the proximity check. |
| `powerauth.service.pagination.default-page-size` | `500` | The default number of records per page when paginated results are requested |
| `powerauth.service.pagination.default-page-number` | `0` | The default page number when paginated results are requested. Page numbers start from 0 |

Expand Down
11 changes: 11 additions & 0 deletions docs/PowerAuth-Server-1.9.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,14 @@ for further details.

Callback URL Events now include an `Idempotency-Key` in the HTTP request header. It is a unique UUIDv4 key to recognize
retries of the same request.

### New Configuration Options For the Proximity Check

Two new configuration properties have been introduced to adjust parameters for the TOTP generation and validation
algorithm in the proximity check process.

- `powerauth.service.proximity-check.otp.step-duration` defines the time-step duration used for generating and
validating TOTP during the proximity check. Defaults to 30 seconds.
- `powerauth.service.proximity-check.otp.step-count` defines the acceptable TOTP transmission delay by setting the
number of past time-steps that will be validated for the proximity check. Defaults to 1, which means proximity otp
value from the current time-step or the previous time-step is acceptable.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ public class PowerAuthServiceConfiguration {
@Value("${powerauth.service.proximity-check.otp.length:8}")
private int proximityCheckOtpLength;

/**
* Step duration used for generating and validating TOTP for the proximity check.
*/
@Value("${powerauth.service.proximity-check.otp.step-duration:30s}")
private Duration proximityCheckStepDuration;

/**
* Acceptable TOTP transmission delay as the number of past time-steps used for validating TOTP for the proximity check.
*/
@Value("${powerauth.service.proximity-check.otp.step-count:1}")
private int proximityCheckStepCount;

/**
* Number of operation that will be set expired in the single scheduled job run.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -1071,13 +1072,15 @@ private Map<String, Object> mapMerge(Map<String, Object> m1, Map<String, Object>
*/
@SneakyThrows(GenericServiceException.class)
private OperationDetailResponse convertFromEntityAndFillOtp(final OperationEntity source) {
final String totp = generateTotp(source, powerAuthServiceConfiguration.getProximityCheckOtpLength());
final int otpLength = powerAuthServiceConfiguration.getProximityCheckOtpLength();
final Duration otpStepDuration = powerAuthServiceConfiguration.getProximityCheckStepDuration();
final String totp = generateTotp(source, otpLength, otpStepDuration);
final OperationDetailResponse target = convertFromEntity(source);
target.setProximityOtp(totp);
return target;
}

private String generateTotp(final OperationEntity operation, final int otpLength) throws GenericServiceException {
private String generateTotp(final OperationEntity operation, final int otpLength, final Duration otpStepDuration) throws GenericServiceException {
final String seed = operation.getTotpSeed();
final String operationId = operation.getId();

Expand All @@ -1089,7 +1092,7 @@ private String generateTotp(final OperationEntity operation, final int otpLength
try {
final byte[] seedBytes = Base64.getDecoder().decode(seed);
final Instant now = Instant.now();
final byte[] totp = Totp.generateTotpSha256(seedBytes, now, otpLength);
final byte[] totp = Totp.generateTotpSha256(seedBytes, now, otpStepDuration, otpLength);

return new String(totp, StandardCharsets.UTF_8);
} catch (CryptoProviderException | IllegalArgumentException e) {
Expand Down Expand Up @@ -1139,7 +1142,9 @@ private ProximityCheckResult fetchProximityCheckResult(final OperationEntity ope
try {
final String otp = otpObject.toString();
final int otpLength = powerAuthServiceConfiguration.getProximityCheckOtpLength();
final boolean result = Totp.validateTotpSha256(otp.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(seed), now, otpLength);
final Duration otpStepDuration = powerAuthServiceConfiguration.getProximityCheckStepDuration();
final int otpStepCount = powerAuthServiceConfiguration.getProximityCheckStepCount();
final boolean result = Totp.validateTotpSha256(otp.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(seed), now, otpLength, otpStepCount, otpStepDuration);
logger.debug("OTP validation result: {} for operation ID: {}", result, operation.getId());
return result ? ProximityCheckResult.SUCCESS : ProximityCheckResult.FAILED;
} catch (CryptoProviderException | IllegalArgumentException e) {
Expand Down

0 comments on commit 96208b7

Please sign in to comment.