Skip to content

Commit 5a954c8

Browse files
author
Bogdan Mocanu
committed
Issue-1 - Signature response validation
Small updates in the documentation. Add support for signature validation in the CLI mode
1 parent db82737 commit 5a954c8

File tree

9 files changed

+102
-21
lines changed

9 files changed

+102
-21
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mobileid-client-samples/src/main/java/ch/swisscom/mid/client/samples/TestSoap.ja
1515
local-*.*
1616
api-docs
1717

18-
# Local files that might be creating during testing
18+
# Local files that might be created during testing
1919
/truststore.jks
2020
/keystore.jks
2121
/config.properties

docs/configure-the-client.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ client.proxy.username=
4545
# The optional password to use during proxy authentication
4646
client.proxy.password=
4747

48+
# ---
49+
# The Java truststore file with the CA certificates used for validating the signer's certificate path
50+
client.signatureValidation.trustStore.file=signature-validation-truststore.jks
51+
# The type of the truststore
52+
client.signatureValidation.trustStore.type=jks
53+
# The password that protects the truststore (optional)
54+
client.signatureValidation.trustStore.password=secret
55+
4856
# --
4957
# The Java truststore file with the server certificates (e.g. CA certificates) to trust
5058
server.trustStore.file=truststore.jks

docs/use-the-client-via-cli.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Arguments:
3838
3939
-receipt - For sign operation. Send a receipt after the signature is acquired successfully
4040
41+
-validate - For sign operation. Validate the signature once it is successfully acquired
42+
4143
-msisdn=41790000000 - The target MSISDN for the chosen operation
4244
4345
-lang=en|de|it|fr - The language to use during the talk with the mobile user. Choose from "en", "de", "it", "fr"

docs/validate-signatures.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Validate signature after a successful authentication/authorization process
22

3+
## In code
4+
35
After successfully performing a mobile signature process, it is a good idea to validate the obtained signature, to ensure it is correct from the
46
following point of views:
57
* the signing certificate (user certificate) is still valid
@@ -40,7 +42,7 @@ if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
4042

4143
// now, with the config, let's create the signature validator and use it
4244
SignatureValidator validator = new SignatureValidatorImpl(svConfig);
43-
SignatureValidationResult result = validator.validateSignature(response.getBase64Signature(), request.getDataToBeSigned(), null);
45+
SignatureValidationResult result = validator.validateSignature(response.getBase64Signature(), request.getDataToBeSigned().getData(), null);
4446

4547
if (result.isValidationSuccessful()) {
4648
// all is good, the signature is perfectly valid
@@ -50,7 +52,7 @@ if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
5052

5153
} else {
5254
// something failed
53-
System.out.println("Signature validation failure = " + result.getValidationFailureReason());
55+
System.out.println("Validation failure reason = " + result.getValidationFailureReason());
5456
System.out.println("Signing certificate path validation = " + result.isSignerCertificatePathValid());
5557
System.out.println("Signing certificate validation = " + result.isSignerCertificateValid());
5658
System.out.println("Signature validation = " + result.isSignatureValid());
@@ -62,3 +64,22 @@ if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
6264

6365
}
6466
```
67+
68+
## In CLI mode
69+
70+
If you are using the Mobile ID Client in CLI mode, you can use the "-validate" flag to ask the client to validate the signature once it is
71+
successfully acquired.
72+
73+
First you need to configure the signature validation truststore in your "config.properties" file:
74+
75+
```properties
76+
client.signatureValidation.trustStore.file=signature-validation-truststore.jks
77+
client.signatureValidation.trustStore.type=jks
78+
client.signatureValidation.trustStore.password=secret
79+
```
80+
81+
Then request a digital signature and ask for the validation of it at the end:
82+
83+
```shell
84+
./bin/mid-client.sh -sign -msisdn=41790000000 -lang=en -dtbs "Do you want to login?" -validate
85+
```

mid-java-client-core/src/main/java/ch/swisscom/mid/client/utils/Utils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ public static String joinListOfStrings(List<String> theList, String separator) {
107107
return String.join(separator, theList);
108108
}
109109

110+
public static String getThisOrNull(String value) {
111+
if (value == null || value.trim().length() == 0) {
112+
return null;
113+
}
114+
return value;
115+
}
116+
110117
public static void assertNotNull(Object object, String messageForException) {
111118
if (object == null) {
112119
throw new IllegalArgumentException(messageForException);

mid-java-client-usage/src/main/java/ch/swisscom/mid/client/cli/Cli.java

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import com.fasterxml.jackson.databind.SerializationFeature;
55

6+
import org.apache.commons.codec.binary.StringUtils;
67
import org.slf4j.Logger;
78
import org.slf4j.LoggerFactory;
89

@@ -14,17 +15,15 @@
1415
import ch.qos.logback.classic.LoggerContext;
1516
import ch.swisscom.mid.client.MIDClient;
1617
import ch.swisscom.mid.client.MIDClientException;
17-
import ch.swisscom.mid.client.config.ClientConfiguration;
18-
import ch.swisscom.mid.client.config.DefaultConfiguration;
19-
import ch.swisscom.mid.client.config.HttpConfiguration;
20-
import ch.swisscom.mid.client.config.ProxyConfiguration;
21-
import ch.swisscom.mid.client.config.TlsConfiguration;
22-
import ch.swisscom.mid.client.config.UrlsConfiguration;
18+
import ch.swisscom.mid.client.SignatureValidator;
19+
import ch.swisscom.mid.client.config.*;
2320
import ch.swisscom.mid.client.impl.Loggers;
2421
import ch.swisscom.mid.client.impl.MIDClientImpl;
22+
import ch.swisscom.mid.client.impl.SignatureValidatorImpl;
2523
import ch.swisscom.mid.client.model.*;
2624

2725
import static ch.swisscom.mid.client.samples.Utils.prettyPrintTheException;
26+
import static ch.swisscom.mid.client.utils.Utils.getThisOrNull;
2827

2928
/**
3029
* Command line interface for the Mobile ID client. Allows the running of the MID Client from the command line, with most of
@@ -55,6 +54,7 @@ public class Cli {
5554
private static final String PARAM_REQUEST_TIMEOUT = "req-timeout";
5655
private static final String PARAM_REST = "rest";
5756
private static final String PARAM_SOAP = "soap";
57+
private static final String PARAM_VALIDATE_SIGNATURE = "validate";
5858
private static final String PARAM_HELP = "help";
5959

6060
private static final String PARAM_VERBOSE1 = "v";
@@ -83,6 +83,7 @@ public class Cli {
8383
private static final String receiptDtbd = "Login completed successfully";
8484
private static boolean syncSignature = false;
8585
private static boolean sendReceipt = false;
86+
private static boolean validateSignature = false;
8687
private static String interfaceType;
8788
private static int verboseLevel;
8889

@@ -183,17 +184,48 @@ public static void main(String[] args) {
183184
}
184185
System.out.println(response.toString());
185186

186-
if (sendReceipt && response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
187-
ReceiptRequest receiptRequest = new ReceiptRequest();
188-
receiptRequest.setStatusCode(StatusCode.REQUEST_OK);
189-
receiptRequest.getMessageToBeDisplayed().setData(receiptDtbd);
190-
receiptRequest.getRequestExtension().getReceiptProfile().setLanguage(lang);
191-
receiptRequest.setTrafficObserver(prettyPrinterTrafficObserver);
192-
193-
ReceiptResponse receiptResponse = midClient.requestSyncReceipt(response.getTracking(), receiptRequest);
194-
finalResult = "Receipt response:\n" + jacksonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(receiptResponse);
195-
} else {
196-
finalResult = "Signature response:\n" + jacksonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(response);
187+
if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
188+
boolean signatureIsValid = false;
189+
if (validateSignature) {
190+
SignatureValidationConfiguration svConfig = new SignatureValidationConfiguration();
191+
svConfig.setTrustStoreFile(properties.getProperty("client.signatureValidation.trustStore.file"));
192+
svConfig.setTrustStoreType(properties.getProperty("client.signatureValidation.trustStore.type"));
193+
svConfig.setTrustStorePassword(getThisOrNull(properties.getProperty("client.signatureValidation.trustStore.password")));
194+
195+
SignatureValidator validator = new SignatureValidatorImpl(svConfig);
196+
SignatureValidationResult result =
197+
validator.validateSignature(response.getBase64Signature(), request.getDataToBeSigned().getData(), null);
198+
if (result.isValidationSuccessful()) {
199+
signatureIsValid = true;
200+
System.out.println("Signature is valid!");
201+
System.out.println("Mobile ID serial number = " + result.getMobileIdSerialNumber());
202+
System.out.println("Signed DTBS = " + result.getSignedDtbs());
203+
} else {
204+
// something failed
205+
System.out.println("Validation failure reason = " + result.getValidationFailureReason());
206+
System.out.println("Signing certificate path validation = " + result.isSignerCertificatePathValid());
207+
System.out.println("Signing certificate validation = " + result.isSignerCertificateValid());
208+
System.out.println("Signature validation = " + result.isSignatureValid());
209+
System.out.println("DTBS matching = " + result.isDtbsMatching());
210+
if (result.getValidationException() != null) {
211+
result.getValidationException().printStackTrace();
212+
}
213+
}
214+
}
215+
if (sendReceipt) {
216+
if (!validateSignature || signatureIsValid) {
217+
ReceiptRequest receiptRequest = new ReceiptRequest();
218+
receiptRequest.setStatusCode(StatusCode.REQUEST_OK);
219+
receiptRequest.getMessageToBeDisplayed().setData(receiptDtbd);
220+
receiptRequest.getRequestExtension().getReceiptProfile().setLanguage(lang);
221+
receiptRequest.setTrafficObserver(prettyPrinterTrafficObserver);
222+
223+
ReceiptResponse receiptResponse = midClient.requestSyncReceipt(response.getTracking(), receiptRequest);
224+
finalResult = "Receipt response:\n" + jacksonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(receiptResponse);
225+
} else {
226+
System.out.println("Signature was NOT valid so sending receipt was skipped");
227+
}
228+
}
197229
}
198230
}
199231
} catch (Exception e) {
@@ -318,6 +350,10 @@ private static void parseArguments(String[] args) {
318350
sendReceipt = true;
319351
break;
320352
}
353+
case PARAM_VALIDATE_SIGNATURE: {
354+
validateSignature = true;
355+
break;
356+
}
321357
case PARAM_MSISDN: {
322358
if (argValue == null) {
323359
if (argIndex + 1 < args.length) {
@@ -410,7 +446,8 @@ private static void runInit() {
410446
String[][] configPairs = new String[][]{
411447
new String[]{"/cli-files/config-sample.properties", "config.properties"},
412448
new String[]{"/cli-files/keystore.jks", "keystore.jks"},
413-
new String[]{"/cli-files/truststore.jks", "truststore.jks"}
449+
new String[]{"/cli-files/truststore.jks", "truststore.jks"},
450+
new String[]{"/cli-files/signature-validation-truststore.jks", "signature-validation-truststore.jks"}
414451
};
415452
for (String[] configPair : configPairs) {
416453
String inputFile = configPair[0];

mid-java-client-usage/src/main/resources/cli-files/config-sample.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ client.proxy.port=
1515
client.proxy.username=
1616
client.proxy.password=
1717
# --
18+
client.signatureValidation.trustStore.file=signature-validation-truststore.jks
19+
client.signatureValidation.trustStore.type=jks
20+
client.signatureValidation.trustStore.password=secret
21+
# --
1822
server.trustStore.file=truststore.jks
1923
server.trustStore.password=secret
2024
server.hostnameVerification=true
Binary file not shown.

mid-java-client-usage/src/main/resources/cli-files/usage.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Arguments:
2222

2323
-receipt - For sign operation. Send a receipt after the signature is acquired successfully
2424

25+
-validate - For sign operation. Validate the signature once it is successfully acquired
26+
2527
-msisdn=41790000000 - The target MSISDN for the chosen operation
2628

2729
-lang=en|de|it|fr - The language to use during the talk with the mobile user. Choose from "en", "de", "it", "fr"

0 commit comments

Comments
 (0)