Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Dan_vL
Product and Topic Expert
Product and Topic Expert
0 Kudos
Previous   Home   Next


The Encrypted Storage plugin provides an asynchronous API to store key value pairs securely. The API is based on the web storage interface but is asynchronous in nature. The Logon plugin also provides get and set methods that can be used to store user names, password, keys and certificates while the Encrypted Storage plugin is better suited to storing application data.

For additional details see C:\SAP\MobileSDK3\KapselSDK\docs\api\sap.EncryptedStorage.html or Using the Encrypted Storage Plugin.

The following steps will demonstrate this plugin.

  • In the folder C:\Kapsel_Projects\KapselGSDemo add the encrypted storage plugin.
    cordova plugin add kapsel-plugin-encryptedstorage --searchpath %KAPSEL_HOME%/plugins
    or
    cordova plugin add kapsel-plugin-encryptedstorage --searchpath $KAPSEL_HOME/plugins


  • Replace www\index.html with with the following content.
    <html>
    <head>
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" charset="utf-8" src="serverContext.js"></script>

    <script>
    window.onerror = onError;
    keyTextField = "";
    valueTextField = "";
    resultsTextArea = "";
    storeName = "testStore";
    store = null;

    function onError(msg, url, line) {
    var idx = url.lastIndexOf("/");
    var file = "unknown";
    if (idx > -1) {
    file = url.substring(idx + 1);
    }
    alert("An error occurred in " + file + " (at line # " + line + "): " + msg);
    return false; //suppressErrorAlert;
    }

    function init() {
    if (sap.Logger) {
    sap.Logger.setLogLevel(sap.Logger.DEBUG); //enables the display of debug log messages from the Kapsel plugins.
    sap.Logger.debug("Log level set to DEBUG");
    }
    if (navigator.notification) { // Override default HTML alert with native dialog. alert is not supported on Windows
    window.alert = navigator.notification.alert;
    }
    keyTextField = document.getElementById("keyTextField");
    valueTextField = document.getElementById("valueTextField");
    resultsTextArea = document.getElementById("resultsTextArea");

    var passcodePolicy = {
    "expirationDays":"0",
    "hasDigits":"false",
    "hasLowerCaseLetters":"false",
    "hasSpecialLetters":"false",
    "hasUpperCaseLetters":"false",
    "defaultAllowed":"true",
    "lockTimeout":"5",
    "minLength":"6",
    "minUniqueChars":"0",
    "retryLimit":"5"
    };

    //Used if the application is not registering with the SMP 3.0 server. New to SP03.
    sap.Logon.initPasscodeManager(successCallback, errorCallback, appId, null, passcodePolicy, context);

    //Used if the application registers with the SMP 3.0 server
    //sap.Logon.init(successCallback, errorCallback, appId, context);

    createStore();
    }

    function createStore() {
    store = new sap.EncryptedStorage(storeName); //SP03 the Encrypted Storage plugin requires logon. API changed no password required.
    //store = new sap.EncryptedStorage(storeName, "securePassword123"); //SP02
    }

    function deleteStore() {
    store.deleteStore(successCallback, errorCallback);
    }

    function successCallback(info) {
    console.log("Success: " + JSON.stringify(info));
    }

    function errorCallback(errorInfo) {
    alert("Error: " + JSON.stringify(errorInfo));
    }

    function setItem(key, value) {
    store.setItem(key, value, successCallback, errorCallback);
    }

    function getItem(key) {
    store.getItem(key, function(value) {
    console.log(value);
    resultsTextArea.value = resultsTextArea.value + key + ":" + value + "\n";
    }, errorCallback);
    }

    function setItemLogon(key, value) {
    sap.Logon.set(successCallback, errorCallback, key, value);
    }

    function getItemLogon(key) {
    sap.Logon.get(function(value) {
    console.log(value);
    resultsTextArea.value = resultsTextArea.value + key + ":" + value + "\n";
    }, errorCallback, key);
    }

    function removeItem(key) {
    store.removeItem(key, successCallback, errorCallback);
    }

    function clearAll() {
    store.clear(successCallback, errorCallback);
    }

    function showAll() {
    resultsTextArea.value = "";
    store.length(function(length) {
    for (var i = 0; i < length; i++) {
    store.key(i, function(key) {
    getItem(key);
    }, errorCallback);
    }
    }, errorCallback);
    }

    document.addEventListener("deviceready", init, false);
    </script>
    </head>
    <body>
    <h1>EncryptedStorage Sample</h1>
    <button id="setItem" onclick="setItem(keyTextField.value, valueTextField.value)">Set Item</button>
    <button id="getItem" onclick="resultsTextArea.value='';getItem(keyTextField.value)">Get Item</button>
    <button id="removeItem" onclick="removeItem(keyTextField.value)">Remove Item</button>
    <button id="clearAll" onclick="clearAll()">Clear All Items</button>
    <button id="showAll" onclick="showAll()">Show All Items</button>
    <button id="deleteStore" onclick="deleteStore()">Delete Store</button>
    <button id="createStore" onclick="createStore()">Create Store</button><br><br>
    <button id="setItemLogon" onclick="setItemLogon(keyTextField.value, valueTextField.value)">Set Item from Logon</button>
    <button id="getItemLogon" onclick="resultsTextArea.value='';getItemLogon(keyTextField.value)">Get Item from Logon</button>
    <button id="lockDV" onclick="sap.Logon.lock(successCallback, errorCallback)">Lock Data Vault</button>
    <button id="unlockDV" onclick="sap.Logon.unlock(successCallback, errorCallback)">Unlock Data Vault</button>
    <button id="deletePCM" onclick="sap.Logon.deletePasscodeManager(successCallback, errorCallback)">Delete PasscodeManager</button>
    <button id="initPCM" onclick="init()">Init PasscodeManager</button>
    <button id="dataVaultState" onclick="sap.Logon.core.getState(function(value) {alert(JSON.stringify(value))}, errorCallback)">Show Data Vault state</button><br>
    Key:<input type="text" id="keyTextField"><br>
    Value:<input type="text" id="valueTextField"><br>
    <textarea rows="10" cols="30" id="resultsTextArea"></textarea><br>
    </body>
    </html>​


  • Notice that the API is asynchronous. This can make it a bit more challenging to work with. The article Asynchronous JS: Callbacks, Listeners, Control Flow Libs and Promises provides some suggestions on how to work with asynchronous methods.

  • Prepare, build and deploy the app with the following command.
    cordova run android
    or
    cordova run windows -- --archs=x64
    or
    cordova run windows --device -- --archs=arm --phone
    or
    cordova run ios


  • If the Logging plugin is added and the log level set to debug, the messages logged by the Encrypted Storage plugin can be viewed. The log tag it uses is SMP_ENCRYPTED_STORAGE.

  • The data vault of the Logon plugin is required by the Encrypted Storage plugin. The Logon plugin can be initialized using the method sap.Logon.initPasscodeManager. This is to be used instead of sap.Logon.init if the application is not registering against an SAP Mobile Platform. Note that in the case where a registration is not being performed, the passcode policy must be supplied as it is not provided by a SAP Mobile Platform or SAP Cloud Platform Mobile Services server.If the Logon plugin's data vault is deleted, the EncryptedStorage plugin will also delete all storage as well. This can occur when the user clicks the Forgot Application Passcode button on the unlock screen of the Logon plugin, if the user enters too many incorrect passcodes or if the method sap.Logon.core.deleteRegistration is called.

  • The following are some technical details of where the data is stored on Android.
    Key value pairs are stored in a SQLLite Database.
    The database is created using local storage which can only be accessed by the application that created it. The file is stored under /data/data/packageName and can be seen and accessed when using an emulator but not a device.The values and the keys stored in this SQLLite database are encrypted. See Encrypted Storage Plugin for additional technical details on the encryption used to store the data.


Previous   Home   Next
7 Comments