Skip to content

Commit f057eaf

Browse files
authored
Merge pull request #11 from MobileID-Strong-Authentication/dev-validate-sign-rsp
Introduced get-mid-sn operation, exposed getMIDSerialNumber method
2 parents 6dfaa4e + e66aa5f commit f057eaf

File tree

7 files changed

+189
-47
lines changed

7 files changed

+189
-47
lines changed

docs/use-the-client-programmatically.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,38 @@ receiptRequest.addReceiptRequestExtension();
141141
ReceiptResponse receiptResponse = client.requestSyncReceipt(signatureResponse.getTracking(), receiptRequest);
142142
System.out.println(receiptResponse.toString());
143143
```
144+
In order to obtain Mobile ID serial number for particular MSISDN one could do as it follows:
145+
```java
146+
SignatureRequest request = new SignatureRequest();
147+
request.setUserLanguage(UserLanguage.ENGLISH);
148+
request.getDataToBeSigned().setData("Test: Do you want to login?");
149+
request.getMobileUser().setMsisdn("41790000000");
150+
request.setSignatureProfile(SignatureProfiles.DEFAULT_PROFILE);
151+
152+
SignatureResponse response = client.requestAsyncSignature(request);
153+
154+
// poll for signature status
155+
while (response.getStatus().getStatusCode() == StatusCode.REQUEST_OK ||
156+
response.getStatus().getStatusCode() == StatusCode.OUTSTANDING_TRANSACTION) {
157+
Thread.sleep(5000);
158+
System.out.println("Pending: " + response);
159+
response = client.pollForSignatureStatus(response.getTracking());
160+
}
161+
System.out.println(response.toString());
162+
163+
if (response.getStatus().getStatusCode() == StatusCode.SIGNATURE) {
164+
// create validation configuration
165+
SignatureValidationConfiguration svConfig = new SignatureValidationConfiguration();
166+
svConfig.setTrustStoreFile(properties.getProperty("client.signatureValidation.trustStore.file"));
167+
svConfig.setTrustStoreType(properties.getProperty("client.signatureValidation.trustStore.type"));
168+
svConfig.setTrustStorePassword(getThisOrNull(properties.getProperty("client.signatureValidation.trustStore.password")));
169+
170+
SignatureValidator validator = new SignatureValidatorImpl(svConfig);
171+
// invoke getMIDSerialNumber method
172+
String midSN = validator.getMIDSerialNumber(response.getBase64Signature(), null);
173+
System.out.println("Received Mobile ID serial number=[" + midSN + "]");
174+
}
175+
```
144176

145177
## Custom AP ID and AP password per request
146178

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,17 @@ Arguments:
3131
-sign - Request a digital signature to the target MSISDN. Arguments such as -lang, -dtbs
3232
can customize what is displayed to the user and what is the signed content.
3333
Cannot be used together with -profile-query
34+
35+
-get-mid-sn - Request to receive Mobile ID serial number for specified MSISDN from digital signature
36+
Cannot be used together with -profile-query or -sign
3437
3538
-sync - For sign operation. Run the signature in synchronous mode (default is async)
3639
3740
-async - For sign operation. Run the signature in asynchronous (polling) mode (this is the default)
3841
3942
-receipt - For sign operation. Send a receipt after the signature is acquired successfully
43+
44+
-geofencing - For sign operation. Request additional geofencing data
4045
4146
-validate - For sign operation. Validate the signature once it is successfully acquired
4247
@@ -75,10 +80,12 @@ Use cases:
7580
- ./bin/mid-client.sh -sign -sync -receipt -msisdn=41790000000 -lang=en -dtbs="Do you want to login?" -soap -vv
7681
- ./bin/mid-client.sh \
7782
-config=my-config.properties \
78-
-sign -sync -receipt \
83+
-sign -sync -receipt -geofencing \
7984
-msisdn=41790000000 \
8085
-lang=en -dtbs="Do you want to login?" \
8186
-soap -vv
87+
- ./bin/mid-client.sh -get-mid-sn -msisdn=41790000000 -rest
88+
8289
```
8390

8491
Use the _-init_ parameter to create a set of initial configuration files in the local directory. This files can then be customized/replaced
@@ -105,14 +112,19 @@ Get the same profile information using a particular configuration file and the S
105112

106113
Request a digital signature to a particular phone number (MSISDN), in sync mode:
107114
```shell
108-
./bin/mid-client.sh -sign -msisdn=41790000000 -lang=en -dtbs "Do you want to login?" -sync
115+
./bin/mid-client.sh -sign -msisdn=41790000000 -geofencing -lang=en -dtbs "Do you want to login?" -sync
109116
```
110117

111118
Request a digital signature to a particular phone number (MSISDN), in async mode (this is the default mode) and with signature receipt:
112119
```shell
113120
./bin/mid-client.sh -sign -msisdn=41790000000 -lang=en -dtbs "Do you want to login?" -receipt -req-timeout 120
114121
```
115122

123+
Request a Mobile ID Serial number based on particular phone number (MSISDN), in async mode:
124+
```shell
125+
./bin/mid-client.sh -get-mid-sn -msisdn=41790000000 -rest
126+
```
127+
116128
Note: when working with arguments that have values (such as _-msisdn_) you can pass the value either as the next argument:
117129
```shell
118130
./bin/mid-client.sh -sign -msisdn 41790000000

docs/version-history.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Version history
22

3+
# v1.5.5
4+
Add support for sslContext configuration for mid-java-client-rest via sslContext property in TlsConfiguration instance.
5+
Introduced "geofencing" parameter to be used with SignatureRequest via cli. The change ensures geofencing data is returned
6+
only when the geofencing parameter in the cli is explicitly set.
7+
Introduced get-mid-sn query/param for cli interface to retrieve Mobile ID serial number, exposed getMIDSerialNumber method
8+
via SignatureValidator interface for programmatically retrieving mentioned property.
9+
10+
# v1.5.4
11+
Update the httpclient5 to the latest version 5.2.1
12+
313
# v1.5.3
414
Add support for sslContext configuration for mid-java-client-soap via sslContext property in TlsConfiguration instance.
515

mid-java-client-core/src/main/java/ch/swisscom/mid/client/SignatureValidator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,11 @@ public interface SignatureValidator {
3131
*/
3232
SignatureValidationResult validateSignature(String base64SignatureContent, String requestedDtbs, Traceable trace);
3333

34+
/**
35+
* Retrieves mobile id serial number from Signature Response base64 SignatureContent element
36+
*
37+
* @param base64SignatureContent the Base64 encoded digital signature data from signature response
38+
* @return mobile id serial number extracted from digital signature data from signature response
39+
*/
40+
String getMIDSerialNumber(String base64SignatureContent, Traceable trace);
3441
}

mid-java-client-core/src/main/java/ch/swisscom/mid/client/impl/SignatureValidatorImpl.java

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package ch.swisscom.mid.client.impl;
22

3+
import ch.swisscom.mid.client.SignatureValidator;
4+
import ch.swisscom.mid.client.config.ConfigurationException;
5+
import ch.swisscom.mid.client.config.SignatureValidationConfiguration;
6+
import ch.swisscom.mid.client.model.SignatureValidationFailureReason;
7+
import ch.swisscom.mid.client.model.SignatureValidationResult;
8+
import ch.swisscom.mid.client.model.Traceable;
39
import org.bouncycastle.cert.X509CertificateHolder;
410
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
511
import org.bouncycastle.cms.CMSException;
@@ -18,27 +24,14 @@
1824
import java.nio.charset.StandardCharsets;
1925
import java.security.KeyStore;
2026
import java.security.Security;
21-
import java.security.cert.CertPathValidator;
22-
import java.security.cert.CertificateExpiredException;
23-
import java.security.cert.CertificateFactory;
24-
import java.security.cert.CertificateNotYetValidException;
25-
import java.security.cert.PKIXParameters;
26-
import java.security.cert.X509Certificate;
27+
import java.security.cert.*;
2728
import java.util.Base64;
2829
import java.util.LinkedList;
2930
import java.util.List;
3031
import java.util.regex.Matcher;
3132
import java.util.regex.Pattern;
3233

33-
import ch.swisscom.mid.client.SignatureValidator;
34-
import ch.swisscom.mid.client.config.ConfigurationException;
35-
import ch.swisscom.mid.client.config.SignatureValidationConfiguration;
36-
import ch.swisscom.mid.client.model.SignatureValidationFailureReason;
37-
import ch.swisscom.mid.client.model.SignatureValidationResult;
38-
import ch.swisscom.mid.client.model.Traceable;
39-
40-
import static ch.swisscom.mid.client.utils.Utils.assertNotEmpty;
41-
import static ch.swisscom.mid.client.utils.Utils.printTrace;
34+
import static ch.swisscom.mid.client.utils.Utils.*;
4235

4336
/**
4437
* Default implementation of {@link SignatureValidator}.
@@ -67,6 +60,7 @@ public SignatureValidationResult validateSignature(String base64SignatureContent
6760
assertNotEmpty(requestedDtbs, "The requestedDtbs parameter cannot be NULL" + printTrace(trace));
6861

6962
SignatureValidationResult result = new SignatureValidationResult();
63+
// 4 criteria to be met in parallel to mark digital signature as valid
7064
result.setSignatureValid(false);
7165
result.setSignerCertificateValid(false);
7266
result.setSignerCertificatePathValid(false);
@@ -107,7 +101,7 @@ public SignatureValidationResult validateSignature(String base64SignatureContent
107101
}
108102

109103
// extract data from the signature
110-
result.setMobileIdSerialNumber(getMIDSerialNumber(signerCert));
104+
result.setMobileIdSerialNumber(extractMIDSerialNumber(signerCert));
111105
result.setSignedDtbs(getSignedDtbs(cmsSignedData));
112106

113107
// check that the certificate is valid. It is if the current date and time are within the validity period
@@ -166,16 +160,48 @@ public SignatureValidationResult validateSignature(String base64SignatureContent
166160
return result;
167161
}
168162

163+
@Override
164+
public String getMIDSerialNumber(String base64SignatureContent, Traceable trace) {
165+
assertNotEmpty(base64SignatureContent, "The base64SignatureContent parameter cannot be NULL" + printTrace(trace));
166+
CMSSignedData cmsSignedData;
167+
X509Certificate signerCert = null;
168+
List<X509Certificate> signerCertChain;
169+
SignerInformation signerInfo;
170+
try {
171+
final JcaX509CertificateConverter x509CertificateConverter = new JcaX509CertificateConverter();
172+
cmsSignedData = new CMSSignedData(Base64.getDecoder().decode(base64SignatureContent));
173+
174+
// Find the signer certificate and the entire certificate chain from the CMS content
175+
final SignerInformationStore signerInfoStore = cmsSignedData.getSignerInfos();
176+
signerInfo = signerInfoStore.getSigners().iterator().next();
177+
signerCertChain = new LinkedList<>();
178+
179+
for (final X509CertificateHolder currentCertHolder : cmsSignedData.getCertificates().getMatches(null)) {
180+
X509Certificate currentCert = x509CertificateConverter.getCertificate(currentCertHolder);
181+
signerCertChain.add(currentCert);
182+
if (signerInfo.getSID().match(currentCertHolder)) {
183+
signerCert = currentCert;
184+
}
185+
}
186+
} catch (Exception e) {
187+
log.warn("Failed to extract the signing certificate from the Base64 CMS content{}", printTrace(trace), e);
188+
return null;
189+
}
190+
return extractMIDSerialNumber(signerCert);
191+
192+
}
193+
169194
// ----------------------------------------------------------------------------------------------------
170195

171196
private static final Pattern SERIAL_NUMBER_PATTERN = Pattern.compile(".*SERIALNUMBER=(.{16}).*");
172197

173198
/**
174-
* Get the user's unique Mobile ID SerialNumber from the signer certificate's SubjectDN
199+
* Get the user's unique Mobile ID serial number from the signer certificate's SubjectDN
175200
*
176201
* @return the user's unique Mobile ID serial number.
177202
*/
178-
private String getMIDSerialNumber(X509Certificate signerCert) {
203+
private String extractMIDSerialNumber(X509Certificate signerCert) {
204+
assertNotNull(signerCert, "The signerCert param for Mobile ID serial number extraction cannot be NULL");
179205
Matcher matcher = SERIAL_NUMBER_PATTERN.matcher(signerCert.getSubjectX500Principal().toString().toUpperCase());
180206
if (matcher.find()) {
181207
return matcher.group(1);

0 commit comments

Comments
 (0)