Skip to content

Latest commit

 

History

History
254 lines (219 loc) · 11.8 KB

2.Storage.md

File metadata and controls

254 lines (219 loc) · 11.8 KB

2. Storage

Mobile devices are known for their limited resources and aggressive freeing of memory in case of low RAM or application suspension.

As discussed in the Base Concepts document, inside the Mobile SDK library all entities (connections, credentials, etc.) are represented as state machines. Most of the Mobile SDK operations will be performed with these state machines.

How to work with state machines

The Mobile SDK separates state machine transitions and their persistence, because it gives us some benefits:

  • flexibility regarding what storage will be used to store the data.
  • flexibility regarding what information objects will be stored.
  • reduction of the chance of data loss as the application stores data exactly once.

The state machines are pointed by an integer handle. You will be passing a handle to perform some operations with a state machine. Every mutating operation, e.g. accepting or rejecting, changes the internal state of the state machine referenced by the passed handle moving it into the next state.

Once the state of the state machine changes it's better to save it into the application storage.

The state machines can be serialized into a JSON string representation.

The next time you want to perform some operation with a state machine, its string representation should be taken from the application storage and deserialized by the SDK to the entity state machine. The deserialization process returns a new handle integer value pointing to the recreated state machine object.

Most of the operations with entities have the following flow:

  • Create Credential state machine based on Credential Offer and perform some operations.
  • Serialize state machine and save resulting string into application storage for future use.
  • Later when you need to do something with Credential state machine (e.g. you received a next message related to protocol) - deserialize the credential state machine from string and receive a new handle.
  • With the usage of received handle perform a necessary operation (e.g. handle next message from the protocol).
  • Serialize new credential state machine state into string.
  • Save resulting string for future use.

In the following documents, we will highlight which operations mutate state machines and when you need save their serialized representation into application storage.

Information stored by Mobile SDK

Despite the fact that Mobile SDK does not persist state machines it still has its own secure Wallet storage where it automatically securely save some pieces of secret information in encrypted form which cannot be read.

  • private key which will be used to encrypt messages sent to your Cloud Agent. It will be created and sored during Cloud Agent provisioning step.
  • private keys which will be used to encrypt messages sent to another User. It will be created and sored during Connection establishing step.
  • credential master secret which will be used for credentials blinding during the issuance process. It will be created and sored once on the first SDK initialization.
  • credential signatures which will be created by unblinding of a credential signature received from an issuer during the issuance process. It will be created and stored every time you receive a new credential.
  • credentials will be stored in the wallet by default whenever a credential is accepted by the app's user. However, only the credential attributes along with their values are stored, not the credential metadata. If you need to be able to refer to a credential at any point (e.g. so that the app user can see the credentials in the wallet), you will need to store the credential ID in your app's database, along with any metadata you need. Metadata can be the time the credential was received, the name of the connection, etc. If your use case is just for the fulfillment of proof request, and you don't need to render credentials in the UI, you don't need to additionally save anything to your app's database.

In the following documents, we will explain the meaning of these secrets in more details.

Storage

As we mentioned before, applications have to care about persisting of state machines and other data. There are two options where to store your data:

  • Mobile SDK Wallet - as we mentioned at Information stored by Mobile SDK section, Mobile SDK has its own secure Wallet storage to store secrets. These secrets cannot be read but Mobile SDK also provides a set of functions to write/read any data into the Wallet.

    The information is written into the Wallet in encrypted form. That encryption slightly affects storage performance.

    In order to use Mobile SDK Wallet to store application data, you don't need any additional configuration or steps. It will be available after SDK initialization.

  • Platform-specific storage - you also can configure and use any storage available on your application platform.

    The work of some platform-specific storage can be faster than Mobile SDK Wallet.

    You have to implement storage configuration and integration by yourself in the application.

Mobile SDK Wallet API

Mobile SDK Wallet is built on top of SQLite database applying additional encryption to the records. There is a single table containing the following columns:

  • type - entity type
  • id - id of the record
  • value - record value
  • tags - record tags used for search and storing meta information as json { "tagName1": <str>, ...}

The combination of type and id values must be unique.

  • Add a record to the Wallet

    • iOS
      (void)addRecordWallet:(NSString *)recordType
                   recordId:(NSString *)recordId
                recordValue:(NSString *)recordValue
                 completion:(void (^)(NSError *error))completion) {
                // ...
            }];
    • Android
          WalletApi.addRecordWallet(recordType, recordId, recordValue).get();
  • Update the value of a record in the Wallet

    • iOS
      (void)updateRecordWallet:(NSString *)recordType
                  withRecordId:(NSString *)recordId
               withRecordValue:(NSString *)recordValue
                withCompletion:(void (^)(NSError *error))completion {
                    // ...
                }];
    • Android
          WalletApi.updateRecordWallet(recordType, recordId, recordValue).get();
  • Get record from the Wallet

    • iOS
      (void)getRecordWallet:(NSString *)recordType
                   recordId:(NSString *)recordId
                 completion:(void (^)(NSError *error, NSString* walletValue))completion {
                    // ...
                }];
    • Android
          WalletApi.getRecordWallet(recordType, recordId, optionsJson).get();
  • Delete a record from the Wallet

    • iOS
      (void)deleteRecordWallet:(NSString *)recordType
                      recordId:(NSString *)recordId
                   completion:(void (^)(NSError *error))completion {
                       // ...
                  }];
    • Android
          WalletApi.deleteRecordWallet(recordType, recordId).get();
  • Add tags to a record in the Wallet

    • recordTags - Tags to add for the record associated with the id and type {"Tag1": "value1", "Tag2": "value2"}.
    • iOS
      (void)walletAddRecordTags:(NSString *)recordType
                       recordId:(NSString *)recordId
                     recordTags:(NSString *)recordTags
                     completion:(void (^)(NSError *error))completion {
                    // ...
                }];
    • Android
          WalletApi.addRecordTags(recordType, recordId, recordTags).get();
  • Update tags of a record in the Wallet

    • recordTags - New tags for the record associated with the id and type {"Tag1": "value1", "Tag2": "value2"}.
    • iOS
      (void)walletUpdateRecordTags:(NSString *)recordType
                          recordId:(NSString *)recordId
                        recordTags:(NSString *)recordTags
                        completion:(void (^)(NSError *error))completion {
                    // ...
                }];
    • Android
          WalletApi.addRecordTags(recordType, recordId, recordTags).get();
  • Delete tags from a record in the Wallet

    • recordTags - Tags names as JSON array to remove from the record associated with the id and type ["Tag1", "Tag2"].
    • iOS
      (void)walletDeleteRecordTags:(NSString *)recordType
                          recordId:(NSString *)recordId
                        recordTags:(NSString *)recordTags
                        completion:(void (^)(NSError *error))completion {
                    // ...
                }];
    • Android
          WalletApi.deleteRecordTags(recordType, recordId, recordTags).get();
  • Open search iterator for records in the Wallet

    • query - MongoDB style query to wallet record tags:

        {
          "tagName": "tagValue",
          $or: {
            "tagName2": { $regex: 'pattern' },
            "tagName3": { $gte: 123 },
          },
        }
      
    • options

        {
           retrieveRecords: (optional, true by default) If false only "counts" will be calculated,
           retrieveTotalCount: (optional, false by default) Calculate total count,
           retrieveType: (optional, false by default) Retrieve record type,
           retrieveValue: (optional, true by default) Retrieve record value,
           retrieveTags: (optional, true by default) Retrieve record tags,
        }
      
    • iOS
      (void)walletOpenSearch:(NSString *)type
                       query:(NSString *)query
                     options:(NSString *)options
                  completion:(void (^)(NSError *error, NSInteger searchHandle)) completion {
                       // ...
                  }];
    • Android
          int handle = WalletApi.openSearch(recordType, query, options).get();
  • Fetch next records for a wallet search

    • iOS
      (void) walletSearchNextRecords:(NSInteger)searchHandle
                               count:(NSInteger)count
                          completion:(void (^)(NSError *error, NSString *records))completion {
                          // ...
                          }];
    • Android
          String records = WalletApi.searchNextRecords(searchHandle, count).get();
    • records
         {
           totalCount: <int>, // present only if retrieveTotalCount set to true
           records: [{ // present only if retrieveRecords set to true
               id: "Some id",
               type: "Some type", // present only if retrieveType set to true
               value: "Some value", // present only if retrieveValue set to true
               tags: <tags json>, // present only if retrieveTags set to true
           }],
         }
      
  • Close a search

    • iOS
      (void) walletCloseSearch:(NSInteger)searchHandle
                    completion:(void (^)(NSError *error))completion {
                          // ...
                    }];
    • Android
          WalletApi.closeSearch(searchHandle).get();