Skip to content

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
}