Manipulating Device Response¶
Extracting data¶
In the following example shows how to use the DeviceResponse class to extract the data from it.
MainActivity.java
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.scytales.mvalid.sdk.Received;
import com.scytales.mvalid.sdk.data.DeviceResponse;
import com.scytales.mvalid.sdk.retrieval.TransferReceiveCallback;
import com.scytales.mvalid.sdk.retrieval.TransferReceived;
import com.scytales.mvalid.sdk.session.SessionData;
import com.scytales.mvalid.sdk.session.SessionManager;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity
implements TransferReceiveCallback {
private SessionManager sessionManager;
// ... rest of class properties
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
}
@Override
public void onReceive(@NonNull Received<TransferReceived> received) {
try {
received.runOnSuccessCatching(transferReceived -> transferReceived
.runCatchingForDevice(bytes -> {
SessionData sessionData = sessionManager.decryptResponse(bytes);
sessionData.runOnDataCatching(decryptedBytes -> {
DeviceResponse deviceResponse = DeviceResponse.fromBytes(decryptedBytes);
deviceResponse.getDocuments().forEach(doc -> {
String docType = doc.getDocType();
Map<String, List<DeviceResponse.IssuerSignedItem>> nameSpaces = doc.getIssuerSigned().getNameSpaces();
nameSpaces.forEach((nameSpace, items) -> items.forEach(item -> {
String elementIdentifier = item.getElementIdentifier();
// element's value in CBOR format
byte[] elementValue = item.getElementValue();
Object decodedElementValue = item.getDecodedElementValue();
// decodedElementValue contains the decoded value of CBOR elementValue
// e.g. elementIdentifier = "firsName" and decodedElementValue = "Jane"
// if decoding elementValue fails, decodedElementValue will be "<DECODE_ERROR>"
}));
});
});
sessionData.runOnError(status -> {
// handle session decryption error
});
})
).runOnFailure(failure -> {
// handle transfer failure
});
} catch (Exception e) {
// handle exception
}
}
// ... rest of class methods
}
You can also see in the Device Response javadoc javadoc for more information about the structure of the Device Response.
Verifying data¶
The following example demonstrates how to verify the received data and use the verification information.
MainActivity.java
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.scytales.mvalid.sdk.Received;
import com.scytales.mvalid.sdk.retrieval.TransferReceiveCallback;
import com.scytales.mvalid.sdk.retrieval.TransferReceived;
import com.scytales.mvalid.sdk.session.SessionData;
import com.scytales.mvalid.sdk.session.SessionManager;
import com.scytales.mvalid.sdk.verify.DeviceVerifierResult;
import java.security.cert.X509Certificate;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity
implements TransferReceiveCallback {
private SessionManager sessionManager;
private List<X509Certificate> rootCertificates;
// ... rest of class properties
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
}
@Override
public void onReceive(@NonNull Received<TransferReceived> received) {
try {
received.runOnSuccessCatching(transferReceived -> transferReceived
.runCatchingForDevice(bytes -> {
SessionData sessionData = sessionManager.decryptResponse(bytes);
sessionData.runOnDataCatching(decryptedBytes -> {
List<DeviceVerifierResult> verifierResults = sessionManager.getVerifier(rootCertificates)
.verify(bytes);
verifierResults.forEach(result -> {
String docType = result.getDocType();
// the result of all verification checks
boolean isValid = result.isValid();
// MAC or Sign1Message signature
String authMethod = result.authenticationMethod();
// if MAC or Sign1Message is verified successfully
boolean authStatus = result.authenticationSucceed();
List<Map<String, String>> msoElements = result.getMSOElements();
msoElements.forEach(msoElement -> {
String nameSpace = msoElement.get("nameSpace");
String elementIdentifier = msoElement.get("identifier");
// if the element is missing from the MSO. Expected to be "true" or "false"
String msoIsMissing = msoElement.get("isMissing");
// if the element's hash is valid. Expected to be "true" or "false"
String msoIsValid = msoElement.get("isValid");
// if the element's algorithm is valid. Expected to be "true" or "false"
String msoAlgorithmIsValid = msoElement.get("invalidAlg");
});
Map<String, ZonedDateTime> msoValidity = result.getMSOValidity();
// the date when MSO was signed
ZonedDateTime msoSigned = msoValidity.get("signed");
// the start date of the MSO validity period
ZonedDateTime msoValidFrom = msoValidity.get("validFrom");
// the end date of the MSO validity period
ZonedDateTime msoValidUntil = msoValidity.get("validUntil");
// the date when the MSO is expected to be updated
ZonedDateTime msoExpectedUpdate = msoValidity.get("expectedUpdate");
});
});
sessionData.runOnError(status -> {
// handle session decryption error
});
})
).runOnFailure(failure -> {
// handle transfer failure
});
} catch (Exception e) {
// handle exception
}
}
// ... rest of class methods
}