Android SDK
Overview
The ZeroKit Android SDK brings ZeroKit to Android devices. Use it to authenticate users, encrypt, decrypt and securely share data.
Requirements
Android SDK: The Zerokit SDK library is compatible from API 21 (Android 5.0 - Lollipop)
Download
Add the dependency to build.gradle
dependencies {
compile 'com.tresorit.zerokit:zerokit:4.1.0'
}
Usage
Initializing ZeroKit
To initialize the SDK you will need your API URL: In AndroidManifest.xml, add the following element as a child of the <application> element, by inserting it just before the closing </application> tag: AndroidManifest.xml
<meta-data
android:name="com.tresorit.zerokitsdk.API_ROOT"
android:value="YOUR API ROOT HERE (eg. https://{tenantid}.api.tresorit.io)"/>
Permissions
The following permissions are defined in the Zerokit SDK manifest, and are automatically merged into your app's manifest at build time. You don't need to add them explicitly to your manifest:
- android.permission.INTERNET - Used by the API to communicate with the service.
- android.permission.ACCESS_NETWORK_STATE - Allows the API to check the connection status in order to determine connection errors
Proguard
If you are using ProGuard you might need to add the following option:
-dontwarn com.tresorit.zerokit.**
Using ZeroKit SDK
The API provides 2 possible ways to use the Zerokit SDK:
Asynchron
Zerokit.getInstance().encrypt(tresorId, "apple").execute(
cipherText -> Log.d("Zerokit", String.format("Encrypted text: %s", cipherText)),
error -> Log.d("Zerokit", String.format("Encrypting failed: %s", error.getMessage())));
Synchron
Response<String, ResponseZerokitError> response = Zerokit.getInstance().encrypt(tresorId, "apple").execute();
if (response.isError()) Log.d("Zerokit", String.format("Encrypting failed: %s", response.getError().getMessage()));
else Log.d("Zerokit", String.format("Encrypted text: %s", response.getResult()));
Password handling
A core concept of ZeroKit is that your application should not access and pass around the users' passwords. All password handling should be done by ZeroKit. For this we provide a PasswordEditText UI component that you should present to users to enter their passwords. If you are implementing data-binding solutions in your application and you do not want to use view ids, you can utilize PasswordHandler to achieve the same result.
With this solution you can ensure that the password will not be stored in String in Java side.
Some tips and examples for using PasswordEditText and/or PasswordHandler:
View
<com.tresorit.zerokit.PasswordEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
Zerokit.getInstance().login(userId, passwordEditText).subscribe(responseLogin -> {...});
Data Binding
<com.tresorit.zerokit.PasswordEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:passwordExporter="@{viewmodel.passwordExporter}"
...
Zerokit.getInstance().login(userId, passwordExporter).subscribe(responseLogin -> {...});
It is also possible to securely compare two PasswordEditText and/or PasswordHandler without access of the concrete content in it. It can be useful when for example password confirmation is required:
passwordExporter.isContentEqual(passwordExporterConfirm)
passwordEditText.isContentEqual(passwordEditTextConfirm)
Identity provider
ZeroKit comes with OpenID Connect provider implementation that you can use in your app. Use the getIdentityTokens(String clientId) method of a ZeroKit object to get authorization code and identity token for the current ZeroKit user. A user must be logged in when calling this method. The ZeroKit Open ID client used in mobile apps should have the following settings:
- Redirect URL should have the following format:
https://{Client ID}.{Tenant ID}.[api.tresorit.io/](http://api.tresorit.io/) - Flow should be set to
Hybrid - You can optionally turn on
Requires proof key (DHCE)
You can add new clients and edit settings on the management portal.
Follow this steps to activate the identity provider on your client:
- Sign in to your Zerokit account: https://manage.tresorit.io/signin
- Turn the switch on next to Built-in OpenID Connect provider at the Identity provider section
- Click on the Add client button
- Add a client name. This should be an easy readable name for your client. This name is used only in logs and on this page.
- Fill the redirect URL field based on this pattern:
- your redirect URL must match this formula: https://{**client_id**}.{**tenant_id**}.api.tresorit.io/
- client id: the unique identifier of your newly created client
- tenant id: the identifier of your tenant
- your redirect URL must match this formula: https://{**client_id**}.{**tenant_id**}.api.tresorit.io/
- Click the Add button next to the newly created redirect URI
- Now your client is ready to handle the Identity provider requests
Administrative API
Most of the cryptographic operations (including invites and sharing) must be done client side by the SDK library. To provide control over these operations, and to prevent possible abuse by tampering the client, we introduced the admin API. All client initiated changes which has a permanent effect on the server has to be approved through the Admin API (typically by the server backend of the integrated app). For more information see the ZeroKit documentation.
Example Application
An example application is included with ZeroKit to demonstrate its usage. It demonstrates the following features:
- Registration
- Login and logout
- Tresor creation
- Tresor sharing
- Encryption
- Decryption
Configuring the Example
The example app requires a backend to function. We created a sample backend that you can use for the mobile and web ZeroKit sample apps. You can find the backend and setup instructions here. In the sample/src/main/AndroidManifest.xml set the values for com.tresorit.zerokitsdk.API_ROOT.
<meta-data
android:name="com.tresorit.zerokitsdk.API_ROOT"
android:value="YOUR API ROOT HERE (eg. https://{your tenant's service url})"/>
In the sample/src/main/assets/zerokit.properties set the values for adminkey and adminuserid. If this file does not exist, copy the sample zerokit.demo.properties file in the same directory to create one:
clientid={client id for your openid}
appbackend={url of the sample application backend}
apiroot: This is your tenant's service URL. You can find this URL on the management portal.clientid: This is the client ID for your OpenID Connect client that you wish to use with your mobile.appbackend: This is the URL of the sample application backend. You can find the sample backend and setup instructions here.
!!! IMPORTANT NOTE: You must never include your Admin key in your application. All Admin key calls must be done by your backend. We implemented a mock application in this example so you can run it without setting up a server. The admin key must be kept secret and not included in any client applications that you distribute.
Now you are ready to Build and Run the example in Android Studio.
Registering Test Users
Register test users following the 'test-user-{XYZ}' username format. These users will be automatically validated by the sample backend so you can log in right after registration.
Used 3rd party libraries in the Example Application
- Dagger 2: Dependency injector for Android
- EventBus: A publish/subscribe event bus
- Retrofit: Type-safe HTTP client for Android and Java
API Documentation
Configuration
void init(@NonNull Context context)
This method is responsible for the Zerokit instance initialization. This is a package-private function, so it can not be called from outside. Despite of this the sdk can acquire the context object (via a content provider), which will be passed to the webview, so the user of the sdk has to not deal with that.
Parameters:
- context a context object used to pass it to the webview and to get the metadata from manifest file
Zerokit getInstance()
Returns the Zerokit instance, which was initialized before
Parameters:
Returns:
The Zerokit instance
Invitation links
@NonNull public Call<String, ResponseZerokitError> acceptInvitationLinkNoPassword(@NonNull final String token)
A link with no password can be accepted by any logged in user that has access to the token returned by getInvitationLinkInfo.
Parameters:
- tokenThe token is the token field of the InvitationLinkPublicInfo of the link returned by getInvitationLinkInfo.
Returns:
Resolves to the operation id that must be approved for the operation to be effective.
@NonNull public Call<ResponseZerokitInvitationLinkInfo, ResponseZerokitError> getInvitationLinkInfo(@NonNull final String secret)
You can get some information about the link by calling getInvitationLinkInfo with the link secret. The returned object contains a token necessary to accept the invitation. This also is a client side secret, that should never be uploaded to your site as that would compromise the zero knowledge nature of the system by providing ways to open the tresor.Parameters:
- secret The secret is the one that was concatenated to the end of the url in createInvitationLink.
Returns: Resolves to all the information available.
@NonNull public Call<ResponseZerokitCreateInvitationLink, ResponseZerokitError> createInvitationLinkNoPassword(@NonNull final String linkBase, @NonNull final String tresorId, @Nullable final String message)
You can create an invitation link with no password
Parameters:
- linkBase the base of the link. The link secret is concatenated after this after a '#'
- tresorId the id of the tresor
- message optional arbitrary string data that can be retrieved without a password or any other information
Returns:
Resolves to the operation id and the url of the created link. The operation must be approved before the link is enabled.
@NonNull public Call<ResponseZerokitCreateInvitationLink, ResponseZerokitError> createInvitationLink(@NonNull final String linkBase, @NonNull final String tresorId, @Nullable final String message, @NonNull final byte[] password)
This method creates an invitation link with the password entered. There are overload of this method, that accept passwordExporter and passwordEditText references as password.
Overloads:
- Call<ResponseZerokitCreateInvitationLink, ResponseZerokitError> createInvitationLink(@NonNull final String linkBase, @NonNull final String tresorId, @Nullable final String message, @NonNull final passwordExporter[] password)
- Call<ResponseZerokitCreateInvitationLink, ResponseZerokitError> createInvitationLink(@NonNull final String linkBase, @NonNull final String tresorId, @Nullable final String message, @NonNull final passwordEditText[] password)
**Parameters:**
- linkBase the base of the link. The link secret is concatenated after this after a '#'
- tresorId the id of the tresor
- message optional arbitrary string data that can be retrieved without a password or any other information
- password:the password
Returns
- Resolves to the operation id and the url of the created link. The operation must be approved before the link is enabled.
@NonNull public Call<String, ResponseZerokitError> acceptInvitationLink(@NonNull final String token, @NonNull final byte[] password)
This method will add the user to the tresor of the link using the password entered.Overloads:
- @NonNull public Call<String, ResponseZerokitError> acceptInvitationLink(@NonNull final String token, @NonNull final passwordExporter[] password)
- @NonNull public Call<String, ResponseZerokitError> acceptInvitationLink(@NonNull final String token, @NonNull final passwordEditText[] password)
Parameters:
- token The token is the $token field of the InvitationLinkPublicInfo of the link returned by getInvitationLinkInfo.
- password the password for the link
Returns:
Resolves to the operation id that must be approved for the operation to be effective.
User handling
@NonNull public Call<ResponseZerokitRegister, ResponseZerokitError> register(@NonNull final String userId, @NonNull final String regSessionId, @NonNull final byte[] password)
Registers the user in ZKit with the provided userId. The returned value is the regValidationVerifier which is used during user validation, so it should be saved on the app server.
Overloads:
- @NonNull public Call<ResponseZerokitRegister, ResponseZerokitError> register(@NonNull final String userId, @NonNull final String regSessionId, @NonNull final passwordExporter[] password)**
- @NonNull public Call<ResponseZerokitRegister, ResponseZerokitError> register(@NonNull final String userId, @NonNull final String regSessionId, @NonNull final passwordEditText[] password)**
Parameters:
- userId The userId provided by the InitUserRegistration API call for the given alias
- regSessionId The regSessionId provided by the InitUserRegistration API call for the given alias
- **password the password provided by the User**
Returns:
The RegValidationVerifier property.
@NonNull public Call<ResponseZerokitLogin, ResponseZerokitError> login(@NonNull final String userId, @NonNull final byte[] password, final boolean rememberMe)
This method tries to log in the given user with the given password entered by the userOverloads:
- @NonNull public Call<ResponseZerokitLogin, ResponseZerokitError> login(@NonNull final String userId, @NonNull final passwordExporter[] password, final boolean rememberMe)
- @NonNull public Call<ResponseZerokitLogin, ResponseZerokitError> login(@NonNull final String userId, @NonNull final passwordEditText[] password, final boolean rememberMe)
Parameters:
- userId The userId of the user to log in.
- **password The password of the user to log in.**
- rememberMe [Optional] If true, than next time the login without password will be possible
Returns:
Resolved userId of the logged in user.
@NonNull public Call<String, ResponseZerokitError> changePassword(@Nullable final String userId, @NonNull final byte[] oldPassword, @NonNull final byte[] newPassword)
This method logs into a security session and changes the password of the user.
Overloads:
- @NonNull public Call<String, ResponseZerokitError> changePassword(@Nullable final String userId, @NonNull final passwordExporter[] oldPassword, @NonNull final passwordExporter[] newPassword)
- @NonNull public Call<String, ResponseZerokitError> changePassword(@Nullable final String userId, @NonNull final passwordEditText[] oldPassword, @NonNull final passwordEditText[] newPassword)
Parameters:
- userId**[Optional]** parameter to specify the id of the user changing password. This is only required if the user is not logged in.
- old **password** The currently used password
- new **password **The new password
Returns:
Resolves to the userId of the logged in user
| Rejection | Reason |
|---|---|
| InvalidAuthorization | Invalid username or password |
| UserNameDoesntExist | The user does not exist |
@NonNull public Call<String, ResponseZerokitError> logout(final boolean deleteRememberMe)
Log out the current user
Parameters:
- deleteRememberMe [Optional] If true, after logout the remember me key will be deleted (default is true)
Returns:
The results
@NonNull public Call<String, ResponseZerokitError> whoAmI()
Use this methods to get the logged in user's identity.Parameters:
Returns:
The user ID if logged in or null if not.
Identity tokens
public Call<IdentityTokens, ResponseZerokitError> getIdentityTokens(final String clientId)
Get authorization code and identity tokens for the currenty logged in user.
Parameters:
- clientId: The cliend ID for the current ZeroKit OpenID Connect client set up in the management portal.
Returns:
- authorizationCode: Authorization code
- identityToken: Identity token
- codeVerifier?: Contains the code verifier if you have 'Requires proof key' enabled for your client
Tresors
@NonNull public Call<String, ResponseZerokitError> createTresor()
Tresors are the basic unit of key handling and sharing.They can be referenced by a server generated id, returned on tresor creation.We currently provide no means to list a user's tresors, so the application should save these ids.Both tresor creation and sharing needs administrative approval to be effective.Since the encrypted data has the tresor id included, it can be decrypted even if the tresorId is lost from the application database.
Returns:
Resolves to the tresorId of the newly created tresor. This id can be used to approve the tresor creation and to encrypt/decrypt using the tresor.
@NonNull public Call<String, ResponseZerokitError> shareTresor(@NonNull final String tresorId, @NonNull final String userId)
The shareTresor method will share the tresor with the given user.The operation will only be effective after it is approved using the returned OperationId.This uploads a modified tresor, but the new version is downloadable only after it has been approved.This should be done as soon as possible, as approving any operation to a tresor may invalidate any pending ones.Parameters:
- tresorId The id of the tresor to invite the user to.
- userId The id of the user to invite. Important to notice, that this is not an alias.
Returns:
Resolves to the OperationId that can be used to approve this share.
| Rejection | Reason |
|---|---|
| BadInput | Invalid tresor or userId |
| TresorNotExists | Couldn't find a tresor by the given id |
| Forbidden | This user does not have access to the tresor |
| UserNotFound | There is no user by that id |
@NonNull public Call<String, ResponseZerokitError> kickFromTresor(@NonNull final String tresorId, @NonNull final String userId)
Removes the given user from the tresor. The operation will only be effective after it is approved using the returned OperationId.Parameters:
- tresorId The id of the tresor, which from the user will be kicked out
- userId The id of the user, who will be kicked out
Returns:
Resolves to the operation id. The operation must be approved before the user is kicked out.
| Rejection | Reason |
|---|---|
| InvalidAuthorization | Invalid username or password |
| UserNameDoesntExist | The user does not exist |
Encryption/Decryption
@NonNull public Call<String, ResponseZerokitError> decrypt(@NonNull final String cipherText)
Decrypts the given cipherTextParameters:
- cipherText ZeroKit encrypted text
Returns:
Resolves to the plain text.
| Rejection | Reason |
|---|---|
| BadInput | Invalid cipherText |
| Forbidden | This user does not have access to the tresor |
@NonNull public Call<String, ResponseZerokitError> encrypt(@NonNull final String tresorId, @NonNull final String plainText)
Encrypts the plaintext by the given tresor.
Parameters:
- tresorId The id of the tresor, that will be used to encrypt the text
- plainText The plainText to encrypt
Returns:
Resolves to the cipher text. It contains the tresorId, so the it can be decrypted by itself.
| Rejection | Reason |
|---|---|
| BadInput | The tresorId and plainText has to be a non-empty string |
| BadInput | Invalid tresorId |
| TresorNotExists | Couldn't find a tresor by the given id |
| Forbidden | This user does not have access to the tresor |