Skip to content

Commit

Permalink
Fix #980: Crypto 3.2: Adjust time window for timestamp validation (#1006
Browse files Browse the repository at this point in the history
)
  • Loading branch information
romanstrobl authored Sep 7, 2023
1 parent e301198 commit b180298
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,19 @@ public class PowerAuthServiceConfiguration {
private int offlineSignatureComponentLength;

/**
* Expiration of timestamps for ECIES and MAC token requests.
* Expiration of timestamps for ECIES and MAC token requests for protocol version 3.2+.
*/
@Value("${powerauth.service.crypto.requestExpirationInMilliseconds}")
@Min(0)
private int requestExpirationInMilliseconds;

/**
* Expiration of timestamps for ECIES and MAC token requests for protocol version 3.1 or older.
*/
@Value("${powerauth.service.crypto.requestExpirationInMillisecondsExtended}")
@Min(0)
private int requestExpirationInMillisecondsExtended;

/**
* Whether HTTP proxy is enabled for outgoing HTTP requests.
*/
Expand Down Expand Up @@ -510,21 +517,37 @@ public void setOfflineSignatureComponentLength(int offlineSignatureComponentLeng
}

/**
* Get ECIES request expiration in milliseconds.
* @return ECIES request expiration in milliseconds.
* Get expiration for ECIES and MAC token requests in milliseconds.
* @return Expiration for ECIES and MAC token requests in milliseconds.
*/
public int getRequestExpirationInMilliseconds() {
return requestExpirationInMilliseconds;
}

/**
* Set ECIES request expiration in milliseconds.
* @param requestExpirationInMilliseconds ECIES request expiration in milliseconds.
* Set expiration for ECIES and MAC token requests in milliseconds.
* @param requestExpirationInMilliseconds Expiration for ECIES and MAC token requests in milliseconds.
*/
public void setRequestExpirationInMilliseconds(int requestExpirationInMilliseconds) {
this.requestExpirationInMilliseconds = requestExpirationInMilliseconds;
}

/**
* Get expiration for ECIES and MAC token requests in milliseconds for protocol versions 3.1 and older.
* @return Expiration for ECIES and MAC token requests in milliseconds for protocol versions 3.1 and older.
*/
public int getRequestExpirationInMillisecondsExtended() {
return requestExpirationInMillisecondsExtended;
}

/**
* Set expiration for ECIES and MAC token requests in milliseconds for protocol versions 3.1 and older.
* @param requestExpirationInMillisecondsExtended Expiration for ECIES and MAC token requests in milliseconds for protocol versions 3.1 and older.
*/
public void setRequestExpirationInMillisecondsExtended(int requestExpirationInMillisecondsExtended) {
this.requestExpirationInMillisecondsExtended = requestExpirationInMillisecondsExtended;
}

/**
* Get whether HTTP proxy is enabled.
* @return Whether HTTP proxy is enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,8 @@ public PrepareActivationResponse prepareActivation(String activationCode, String
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
null);
null,
version);
}

final String masterPrivateKeyBase64 = masterKeyPairEntity.getMasterKeyPrivateBase64();
Expand Down Expand Up @@ -1132,7 +1133,8 @@ public CreateActivationResponse createActivation(
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
null);
null,
version);
}

final String masterPrivateKeyBase64 = masterKeyPairEntity.getMasterKeyPrivateBase64();
Expand Down Expand Up @@ -1679,7 +1681,8 @@ public RecoveryCodeActivationResponse createActivationUsingRecoveryCode(Recovery
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
null);
null,
version);
}

final String masterPrivateKeyBase64 = masterKeyPairEntity.getMasterKeyPrivateBase64();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ private GetEciesDecryptorResponse getEciesDecryptorParametersForApplication(GetE
new Date(request.getTimestamp()),
request.getEphemeralPublicKey(),
request.getNonce(),
null);
null,
request.getProtocolVersion());
}

// Get master private key
Expand Down Expand Up @@ -223,7 +224,8 @@ private GetEciesDecryptorResponse getEciesDecryptorParametersForActivation(GetEc
new Date(request.getTimestamp()),
request.getEphemeralPublicKey(),
request.getNonce(),
activation.getActivationId());
activation.getActivationId(),
request.getProtocolVersion());
}

// Check if the activation is in correct state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ public ConfirmRecoveryCodeResponse confirmRecoveryCode(ConfirmRecoveryCodeReques
new Date(request.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
activationId);
activationId,
request.getProtocolVersion());
}

// Get server decryptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ private EncryptedResponse createToken(String activationId, String applicationKey
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
activationId);
activationId,
version);
}

// Get the server private key, decrypt it if required
Expand Down Expand Up @@ -312,7 +313,8 @@ public ValidateTokenResponse validateToken(ValidateTokenRequest request) throws
new Date(request.getTimestamp()),
null,
request.getNonce(),
token.getTokenId());
token.getTokenId(),
activation.getVersion().toString());
// Validate MAC token
isTokenValid = tokenVerifier.validateTokenDigest(nonce, timestamp, tokenSecret, tokenDigest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ public StartUpgradeResponse startUpgrade(StartUpgradeRequest request) throws Gen
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
activationId);
activationId,
request.getProtocolVersion());
}

// Lookup the activation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ public VaultUnlockResponse unlockVault(String activationId, String applicationKe
new Date(encryptedRequest.getTimestamp()),
encryptedRequest.getEphemeralPublicKey(),
encryptedRequest.getNonce(),
activationId);
activationId,
signatureVersion);
}

// Get application secret and transport key used in sharedInfo2 parameter of ECIES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,15 @@ class DefaultReplayVerificationService implements ReplayVerificationService {
private final PowerAuthServiceConfiguration powerAuthServiceConfiguration;

@Override
public void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier) throws GenericServiceException {
public void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier, String version) throws GenericServiceException {
logger.debug("Checking and persisting unique value, request type: {}, identifier: {}", type, identifier);
final Date expiration = Date.from(Instant.now().plus(powerAuthServiceConfiguration.getRequestExpirationInMilliseconds(), ChronoUnit.MILLIS));
final int requestExpiration;
if ("3.0".equals(version) || "3.1".equals(version)) {
requestExpiration = config.getRequestExpirationInMillisecondsExtended();
} else {
requestExpiration = config.getRequestExpirationInMilliseconds();
}
final Date expiration = Date.from(Instant.now().plus(requestExpiration, ChronoUnit.MILLIS));
if (requestTimestamp.after(expiration)) {
// Rollback is not required, error occurs before writing to database
logger.warn("Expired ECIES request received, timestamp: {}", requestTimestamp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
public class NoOpVerificationService implements ReplayVerificationService {

@Override
public void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier) {
public void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier, String version) {
// No-op implementation is empty
logger.debug("Checking and persisting unique value skipped, request type: {}, identifier: {}", type, identifier);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ public interface ReplayVerificationService {
* @param ephemeralPublicKey Ephemeral public key bytes encoded in Base64.
* @param nonce Nonce bytes encoded in Base64.
* @param identifier Identifier for the record.
* @param version Protocol version.
* @throws GenericServiceException Thrown in case unique value exists.
*/
void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier) throws GenericServiceException;
void checkAndPersistUniqueValue(UniqueValueType type, Date requestTimestamp, String ephemeralPublicKey, String nonce, String identifier, String version) throws GenericServiceException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ powerauth.service.crypto.activationValidityInMilliseconds=300000
powerauth.service.crypto.signatureMaxFailedAttempts=5
powerauth.service.crypto.signatureValidationLookahead=20
powerauth.service.crypto.offlineSignatureComponentLength=8
powerauth.service.crypto.requestExpirationInMilliseconds=7200000
powerauth.service.crypto.requestExpirationInMilliseconds=60000
powerauth.service.crypto.requestExpirationInMillisecondsExtended=7200000
powerauth.service.crypto.replayVerificationService=default

# HTTP Proxy Settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ powerauth.service.crypto.activationValidityInMilliseconds=120000
powerauth.service.crypto.signatureMaxFailedAttempts=5
powerauth.service.crypto.signatureValidationLookahead=20
powerauth.service.crypto.offlineSignatureComponentLength=8
powerauth.service.crypto.requestExpirationInMilliseconds=7200000
powerauth.service.crypto.requestExpirationInMilliseconds=60000
powerauth.service.crypto.requestExpirationInMillisecondsExtended=7200000
powerauth.service.crypto.replayVerificationService=default

# HTTP Proxy Settings
Expand Down

0 comments on commit b180298

Please sign in to comment.