Skip to content

Commit 980357c

Browse files
committed
Fixed an issue with encryption certificate and key fingerprints recomputed at every request (when not provided in configuration)
1 parent 29ec616 commit 980357c

12 files changed

+140
-166
lines changed

src/main/java/com/mastercard/developer/encryption/FieldLevelEncryption.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ private static void encryptPayloadPath(DocumentContext payloadContext, String js
171171
payloadContext.put(jsonPathOut, config.encryptedKeyFieldName, params.getEncryptedKeyValue());
172172
}
173173
if (!isNullOrEmpty(config.encryptionCertificateFingerprintFieldName)) {
174-
payloadContext.put(jsonPathOut, config.encryptionCertificateFingerprintFieldName, params.getEncryptionCertificateFingerprintValue());
174+
payloadContext.put(jsonPathOut, config.encryptionCertificateFingerprintFieldName, config.encryptionCertificateFingerprint);
175175
}
176176
if (!isNullOrEmpty(config.encryptionKeyFingerprintFieldName)) {
177-
payloadContext.put(jsonPathOut, config.encryptionKeyFingerprintFieldName, params.getEncryptionKeyFingerprintValue());
177+
payloadContext.put(jsonPathOut, config.encryptionKeyFingerprintFieldName, config.encryptionKeyFingerprint);
178178
}
179179
if (!isNullOrEmpty(config.oaepPaddingDigestAlgorithmFieldName)) {
180180
payloadContext.put(jsonPathOut, config.oaepPaddingDigestAlgorithmFieldName, params.getOaepPaddingDigestAlgorithmValue());
@@ -210,8 +210,7 @@ private static void decryptPayloadPath(DocumentContext payloadContext, String js
210210
Object ivJsonElement = readAndDeleteJsonKey(payloadContext, jsonPathIn, inJsonObject, config.ivFieldName);
211211
readAndDeleteJsonKey(payloadContext, jsonPathIn, inJsonObject, config.encryptionCertificateFingerprintFieldName);
212212
readAndDeleteJsonKey(payloadContext, jsonPathIn, inJsonObject, config.encryptionKeyFingerprintFieldName);
213-
params = new FieldLevelEncryptionParams(jsonEngine.toJsonString(ivJsonElement), jsonEngine.toJsonString(encryptedKeyJsonElement),
214-
oaepDigestAlgorithm, null, null, config);
213+
params = new FieldLevelEncryptionParams(jsonEngine.toJsonString(ivJsonElement), jsonEngine.toJsonString(encryptedKeyJsonElement), oaepDigestAlgorithm, config);
215214
}
216215

217216
// Decrypt data

src/main/java/com/mastercard/developer/encryption/FieldLevelEncryptionConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,12 @@ public String getEncryptionCertificateFingerprintHeaderName() {
175175
public String getEncryptionKeyFingerprintHeaderName() {
176176
return encryptionKeyFingerprintHeaderName;
177177
}
178+
179+
public String getEncryptionCertificateFingerprint() {
180+
return encryptionCertificateFingerprint;
181+
}
182+
183+
public String getEncryptionKeyFingerprint() {
184+
return encryptionKeyFingerprint;
185+
}
178186
}

src/main/java/com/mastercard/developer/encryption/FieldLevelEncryptionConfigBuilder.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
import com.jayway.jsonpath.JsonPath;
44

5+
import java.security.MessageDigest;
6+
import java.security.NoSuchAlgorithmException;
57
import java.security.PrivateKey;
68
import java.security.cert.Certificate;
79
import java.util.HashMap;
810
import java.util.Map;
911
import java.util.Map.Entry;
1012

1113
import static com.mastercard.developer.encryption.FieldLevelEncryptionConfig.FieldValueEncoding;
14+
import static com.mastercard.developer.utils.EncodingUtils.encodeBytes;
15+
import static com.mastercard.developer.utils.StringUtils.isNullOrEmpty;
1216
import static java.security.spec.MGF1ParameterSpec.SHA256;
1317
import static java.security.spec.MGF1ParameterSpec.SHA512;
1418

@@ -201,13 +205,17 @@ public FieldLevelEncryptionConfigBuilder withEncryptionKeyFingerprintHeaderName(
201205

202206
/**
203207
* Build a {@link com.mastercard.developer.encryption.FieldLevelEncryptionConfig}.
208+
* @throws EncryptionException
204209
*/
205-
public FieldLevelEncryptionConfig build() {
210+
public FieldLevelEncryptionConfig build() throws EncryptionException {
206211

207212
checkJsonPathParameterValues();
208213
checkParameterValues();
209214
checkParameterConsistency();
210215

216+
computeEncryptionCertificateFingerprintWhenNeeded();
217+
computeEncryptionKeyFingerprintWhenNeeded();
218+
211219
FieldLevelEncryptionConfig config = new FieldLevelEncryptionConfig();
212220
config.encryptionCertificateFingerprintFieldName = this.encryptionCertificateFingerprintFieldName;
213221
config.encryptionKeyFingerprintFieldName = this.encryptionKeyFingerprintFieldName;
@@ -291,4 +299,36 @@ private void checkParameterConsistency () {
291299
throw new IllegalArgumentException("IV field name and encrypted key field name must be both set or both unset!");
292300
}
293301
}
302+
303+
private void computeEncryptionCertificateFingerprintWhenNeeded() throws EncryptionException {
304+
try {
305+
if (encryptionCertificate == null || !isNullOrEmpty(encryptionCertificateFingerprint)) {
306+
// No encryption certificate set or certificate fingerprint already provided
307+
return;
308+
}
309+
byte[] certificateFingerprintBytes = sha256digestBytes(encryptionCertificate.getEncoded());
310+
encryptionCertificateFingerprint = encodeBytes(certificateFingerprintBytes, FieldValueEncoding.HEX);
311+
} catch (Exception e) {
312+
throw new EncryptionException("Failed to compute encryption certificate fingerprint!", e);
313+
}
314+
}
315+
316+
private void computeEncryptionKeyFingerprintWhenNeeded() throws EncryptionException {
317+
try {
318+
if (encryptionCertificate == null || !isNullOrEmpty(encryptionKeyFingerprint)) {
319+
// No encryption certificate set or key fingerprint already provided
320+
return;
321+
}
322+
byte[] keyFingerprintBytes = sha256digestBytes(encryptionCertificate.getPublicKey().getEncoded());
323+
encryptionKeyFingerprint = encodeBytes(keyFingerprintBytes, FieldValueEncoding.HEX);
324+
} catch (Exception e) {
325+
throw new EncryptionException("Failed to compute encryption key fingerprint!", e);
326+
}
327+
}
328+
329+
private static byte[] sha256digestBytes(byte[] bytes) throws NoSuchAlgorithmException {
330+
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
331+
messageDigest.update(bytes);
332+
return messageDigest.digest();
333+
}
294334
}

src/main/java/com/mastercard/developer/encryption/FieldLevelEncryptionParams.java

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,11 @@
88
import javax.crypto.spec.PSource;
99
import java.security.GeneralSecurityException;
1010
import java.security.Key;
11-
import java.security.MessageDigest;
1211
import java.security.SecureRandom;
1312
import java.security.spec.MGF1ParameterSpec;
1413

15-
import static com.mastercard.developer.encryption.FieldLevelEncryptionConfig.FieldValueEncoding;
1614
import static com.mastercard.developer.utils.EncodingUtils.decodeValue;
1715
import static com.mastercard.developer.utils.EncodingUtils.encodeBytes;
18-
import static com.mastercard.developer.utils.StringUtils.isNullOrEmpty;
1916

2017
/**
2118
* Encryption parameters for computing field level encryption/decryption.
@@ -30,20 +27,14 @@ public final class FieldLevelEncryptionParams {
3027
private final String ivValue;
3128
private final String encryptedKeyValue;
3229
private final String oaepPaddingDigestAlgorithmValue;
33-
private final String encryptionCertificateFingerprintValue;
34-
private final String encryptionKeyFingerprintValue;
3530
private final FieldLevelEncryptionConfig config;
3631
private Key secretKey;
3732
private IvParameterSpec ivParameterSpec;
3833

39-
public FieldLevelEncryptionParams(String ivValue, String encryptedKeyValue,
40-
String oaepPaddingDigestAlgorithmValue, String encryptionCertificateFingerprintValue,
41-
String encryptionKeyFingerprintValue, FieldLevelEncryptionConfig config) {
34+
public FieldLevelEncryptionParams(String ivValue, String encryptedKeyValue, String oaepPaddingDigestAlgorithmValue, FieldLevelEncryptionConfig config) {
4235
this.ivValue = ivValue;
4336
this.encryptedKeyValue = encryptedKeyValue;
4437
this.oaepPaddingDigestAlgorithmValue = oaepPaddingDigestAlgorithmValue;
45-
this.encryptionCertificateFingerprintValue = encryptionCertificateFingerprintValue;
46-
this.encryptionKeyFingerprintValue = encryptionKeyFingerprintValue;
4738
this.config = config;
4839
}
4940

@@ -66,14 +57,12 @@ public static FieldLevelEncryptionParams generate(FieldLevelEncryptionConfig con
6657
byte[] encryptedSecretKeyBytes = wrapSecretKey(config, secretKey);
6758
String encryptedKeyValue = encodeBytes(encryptedSecretKeyBytes, config.fieldValueEncoding);
6859

69-
// Compute fingerprints and OAEP padding digest algorithm
70-
String encryptionCertificateFingerprint = getOrComputeEncryptionCertificateFingerprint(config);
71-
String encryptionKeyFingerprint = getOrComputeEncryptionKeyFingerprint(config);
60+
// Compute the OAEP padding digest algorithm
7261
String oaepPaddingDigestAlgorithmValue = config.oaepPaddingDigestAlgorithm.replace("-", "");
7362

7463
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivSpecValue, encryptedKeyValue,
75-
oaepPaddingDigestAlgorithmValue, encryptionCertificateFingerprint,
76-
encryptionKeyFingerprint, config);
64+
oaepPaddingDigestAlgorithmValue,
65+
config);
7766
params.secretKey = secretKey;
7867
params.ivParameterSpec = ivParameterSpec;
7968
return params;
@@ -87,14 +76,6 @@ public String getEncryptedKeyValue() {
8776
return encryptedKeyValue;
8877
}
8978

90-
public String getEncryptionCertificateFingerprintValue() {
91-
return encryptionCertificateFingerprintValue;
92-
}
93-
94-
public String getEncryptionKeyFingerprintValue() {
95-
return encryptionKeyFingerprintValue;
96-
}
97-
9879
public String getOaepPaddingDigestAlgorithmValue() {
9980
return oaepPaddingDigestAlgorithmValue;
10081
}
@@ -182,38 +163,4 @@ protected static Key unwrapSecretKey(FieldLevelEncryptionConfig config, byte[] k
182163
private static OAEPParameterSpec getOaepParameterSpec(MGF1ParameterSpec mgf1ParameterSpec) {
183164
return new OAEPParameterSpec(mgf1ParameterSpec.getDigestAlgorithm(), "MGF1", mgf1ParameterSpec, PSource.PSpecified.DEFAULT);
184165
}
185-
186-
private static String getOrComputeEncryptionCertificateFingerprint(FieldLevelEncryptionConfig config) throws EncryptionException {
187-
try {
188-
String providedCertificateFingerprintValue = config.encryptionCertificateFingerprint;
189-
if (!isNullOrEmpty(providedCertificateFingerprintValue)) {
190-
return providedCertificateFingerprintValue;
191-
} else {
192-
byte[] certificateFingerprintBytes = sha256digestBytes(config.encryptionCertificate.getEncoded());
193-
return encodeBytes(certificateFingerprintBytes, FieldValueEncoding.HEX);
194-
}
195-
} catch (GeneralSecurityException e) {
196-
throw new EncryptionException("Failed to compute encryption certificate fingerprint!", e);
197-
}
198-
}
199-
200-
private static String getOrComputeEncryptionKeyFingerprint(FieldLevelEncryptionConfig config) throws EncryptionException {
201-
String providedKeyFingerprintValue = config.encryptionKeyFingerprint;
202-
if (!isNullOrEmpty(providedKeyFingerprintValue)) {
203-
return providedKeyFingerprintValue;
204-
} else {
205-
byte[] keyFingerprintBytes = sha256digestBytes(config.encryptionCertificate.getPublicKey().getEncoded());
206-
return encodeBytes(keyFingerprintBytes, FieldValueEncoding.HEX);
207-
}
208-
}
209-
210-
private static byte[] sha256digestBytes(byte[] bytes) throws EncryptionException {
211-
try {
212-
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
213-
messageDigest.update(bytes);
214-
return messageDigest.digest();
215-
} catch (GeneralSecurityException e) {
216-
throw new EncryptionException("Failed to digest bytes!", e);
217-
}
218-
}
219166
}

src/main/java/com/mastercard/developer/interceptors/HttpExecuteFieldLevelEncryptionInterceptor.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public void intercept(HttpRequest request) throws IOException {
5050
FieldLevelEncryptionParams params = FieldLevelEncryptionParams.generate(config);
5151
updateHeader(headers, config.getIvHeaderName(), params.getIvValue());
5252
updateHeader(headers, config.getEncryptedKeyHeaderName(), params.getEncryptedKeyValue());
53-
updateHeader(headers, config.getEncryptionCertificateFingerprintHeaderName(), params.getEncryptionCertificateFingerprintValue());
54-
updateHeader(headers, config.getEncryptionKeyFingerprintHeaderName(), params.getEncryptionKeyFingerprintValue());
53+
updateHeader(headers, config.getEncryptionCertificateFingerprintHeaderName(), config.getEncryptionCertificateFingerprint());
54+
updateHeader(headers, config.getEncryptionKeyFingerprintHeaderName(), config.getEncryptionKeyFingerprint());
5555
updateHeader(headers, config.getOaepPaddingDigestAlgorithmHeaderName(), params.getOaepPaddingDigestAlgorithmValue());
5656
encryptedPayload = FieldLevelEncryption.encryptPayload(requestPayload, config, params);
5757
} else {
@@ -91,8 +91,7 @@ public void interceptResponse(HttpResponse response) throws IOException {
9191
removeHeader(headers, config.getOaepPaddingDigestAlgorithmHeaderName());
9292
removeHeader(headers, config.getEncryptionCertificateFingerprintHeaderName());
9393
removeHeader(headers, config.getEncryptionKeyFingerprintHeaderName());
94-
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue,
95-
null, null, config);
94+
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue, config);
9695
decryptedPayload = FieldLevelEncryption.decryptPayload(responsePayload, config, params);
9796
} else {
9897
// Encryption params are stored in the payload

src/main/java/com/mastercard/developer/interceptors/OkHttp2FieldLevelEncryptionInterceptor.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ private static Request handleRequest(Request request, FieldLevelEncryptionConfig
5454
FieldLevelEncryptionParams params = FieldLevelEncryptionParams.generate(config);
5555
updateHeader(requestBuilder, config.getIvHeaderName(), params.getIvValue());
5656
updateHeader(requestBuilder, config.getEncryptedKeyHeaderName(), params.getEncryptedKeyValue());
57-
updateHeader(requestBuilder, config.getEncryptionCertificateFingerprintHeaderName(), params.getEncryptionCertificateFingerprintValue());
58-
updateHeader(requestBuilder, config.getEncryptionKeyFingerprintHeaderName(), params.getEncryptionKeyFingerprintValue());
57+
updateHeader(requestBuilder, config.getEncryptionCertificateFingerprintHeaderName(), config.getEncryptionCertificateFingerprint());
58+
updateHeader(requestBuilder, config.getEncryptionKeyFingerprintHeaderName(), config.getEncryptionKeyFingerprint());
5959
updateHeader(requestBuilder, config.getOaepPaddingDigestAlgorithmHeaderName(), params.getOaepPaddingDigestAlgorithmValue());
6060
encryptedPayload = FieldLevelEncryption.encryptPayload(requestPayload, config, params);
6161
} else {
@@ -103,8 +103,7 @@ private static Response handleResponse(Response response, FieldLevelEncryptionCo
103103
removeHeader(responseBuilder, config.getOaepPaddingDigestAlgorithmHeaderName());
104104
removeHeader(responseBuilder, config.getEncryptionCertificateFingerprintHeaderName());
105105
removeHeader(responseBuilder, config.getEncryptionKeyFingerprintHeaderName());
106-
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue,
107-
null, null, config);
106+
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue, config);
108107
decryptedPayload = FieldLevelEncryption.decryptPayload(responsePayload, config, params);
109108
} else {
110109
// Encryption params are stored in the payload

src/main/java/com/mastercard/developer/interceptors/OkHttpFieldLevelEncryptionInterceptor.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ private static Request handleRequest(Request request, FieldLevelEncryptionConfig
5454
FieldLevelEncryptionParams params = FieldLevelEncryptionParams.generate(config);
5555
updateHeader(requestBuilder, config.getIvHeaderName(), params.getIvValue());
5656
updateHeader(requestBuilder, config.getEncryptedKeyHeaderName(), params.getEncryptedKeyValue());
57-
updateHeader(requestBuilder, config.getEncryptionCertificateFingerprintHeaderName(), params.getEncryptionCertificateFingerprintValue());
58-
updateHeader(requestBuilder, config.getEncryptionKeyFingerprintHeaderName(), params.getEncryptionKeyFingerprintValue());
57+
updateHeader(requestBuilder, config.getEncryptionCertificateFingerprintHeaderName(), config.getEncryptionCertificateFingerprint());
58+
updateHeader(requestBuilder, config.getEncryptionKeyFingerprintHeaderName(), config.getEncryptionKeyFingerprint());
5959
updateHeader(requestBuilder, config.getOaepPaddingDigestAlgorithmHeaderName(), params.getOaepPaddingDigestAlgorithmValue());
6060
encryptedPayload = FieldLevelEncryption.encryptPayload(requestPayload, config, params);
6161
} else {
@@ -103,8 +103,7 @@ private static Response handleResponse(Response response, FieldLevelEncryptionCo
103103
removeHeader(responseBuilder, config.getOaepPaddingDigestAlgorithmHeaderName());
104104
removeHeader(responseBuilder, config.getEncryptionCertificateFingerprintHeaderName());
105105
removeHeader(responseBuilder, config.getEncryptionKeyFingerprintHeaderName());
106-
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue,
107-
null, null, config);
106+
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue, config);
108107
decryptedPayload = FieldLevelEncryption.decryptPayload(responsePayload, config, params);
109108
} else {
110109
// Encryption params are stored in the payload

src/main/java/com/mastercard/developer/interceptors/OpenFeignFieldLevelEncryptionDecoder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public Object decode(Response response, Type type) throws IOException {
5353
response = removeHeader(response, config.getEncryptedKeyHeaderName());
5454
response = removeHeader(response, config.getEncryptionCertificateFingerprintHeaderName());
5555
response = removeHeader(response, config.getEncryptionKeyFingerprintHeaderName());
56-
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue,
57-
null, null, config);
56+
FieldLevelEncryptionParams params = new FieldLevelEncryptionParams(ivValue, encryptedKeyValue, oaepPaddingDigestAlgorithmValue, config);
5857
decryptedPayload = FieldLevelEncryption.decryptPayload(responsePayload, config, params);
5958
} else {
6059
// Encryption params are stored in the payload

0 commit comments

Comments
 (0)