Skip to content

Commit d0ca375

Browse files
committedOct 7, 2024
parent f0f6c7c
author Nicolas Gimenez <[email protected]> 1716205204 +0200 committer Nicolas Gimenez <[email protected]> 1728301787 +0200 gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg9OUtNQdUox99iVfbkCzO9VDkTr FxtJweIm9OTf+NYj8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQL3zRS6B+Lf6sF+My28t69cngeIuG+1TVJAKYt46zS4TunA59HmlzD8gpX0MZwgDgY yLPysQysIVIFAqC51pWwY= -----END SSH SIGNATURE----- parent f0f6c7c author Nicolas Gimenez <[email protected]> 1716205204 +0200 committer Nicolas Gimenez <[email protected]> 1728301766 +0200 gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg9OUtNQdUox99iVfbkCzO9VDkTr FxtJweIm9OTf+NYj8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQOpFDlBkZ35f2aMTGS1xfPrP9bDa2Khsx9xTtDUyVY3dTVQwA+0MmHUzpdxHI6Eg9J dfm+GM3iryPPWy+q6wfgo= -----END SSH SIGNATURE----- parent f0f6c7c author Nicolas Gimenez <[email protected]> 1716205204 +0200 committer Nicolas Gimenez <[email protected]> 1728301715 +0200 gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg9OUtNQdUox99iVfbkCzO9VDkTr FxtJweIm9OTf+NYj8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQJuJqjR2T8ohMmEL7bMaBj8COBMnJ+cKmeNHPI5eq6379uXZYKvcnzMNIvgcsyRWHC 8qJzstNc+rU74BHLXlOQE= -----END SSH SIGNATURE----- parent f0f6c7c author Nicolas Gimenez <[email protected]> 1716205204 +0200 committer Nicolas Gimenez <[email protected]> 1728301654 +0200 gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg9OUtNQdUox99iVfbkCzO9VDkTr FxtJweIm9OTf+NYj8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQAZxCVsneUK/IIHZ1FraPTuX8bBlY6tw2zL/r84tLuVNaTzj3gsqj47kOJskAI2NrJ 1TEx/Pi66CNPcI4RTuJQk= -----END SSH SIGNATURE----- parent f0f6c7c author Nicolas Gimenez <[email protected]> 1716205204 +0200 committer Nicolas Gimenez <[email protected]> 1728301613 +0200 gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg9OUtNQdUox99iVfbkCzO9VDkTr FxtJweIm9OTf+NYj8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQL0i1xgDTUnc0Gp+Rk5waVbS3sm67IYMWz9yas/J9dXuJQUCuSsi/l+R+zD17EusHS KN70kFC9UvnHwdu+uEHQU= -----END SSH SIGNATURE----- feat(android): enforce biometrics or device credentials to use key for 15min feat(android): enforce biometrics or device credentials to use key for 15min fix: ... fix: access public fix: test 30sec chore: linting fix(android): 15min unlock chore: auto lint chore: license feat: handle error fix: interface
1 parent f0f6c7c commit d0ca375

File tree

9 files changed

+104
-29
lines changed

9 files changed

+104
-29
lines changed
 

‎.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ captures/
6565
*.xcworkspace
6666

6767
.eslintcache
68+
69+
android/.settings/org.eclipse.buildship.core.prefs
70+
android/.project
71+
android/.classpath

‎LICENSE

+24-22
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
Copyright 2020-present Aparajita Fishman
2-
3-
MIT License
4-
5-
Permission is hereby granted, free of charge, to any person obtaining
6-
a copy of this software and associated documentation files (the
7-
"Software"), to deal in the Software without restriction, including
8-
without limitation the rights to use, copy, modify, merge, publish,
9-
distribute, sublicense, and/or sell copies of the Software, and to
10-
permit persons to whom the Software is furnished to do so, subject to
11-
the following conditions:
12-
13-
The above copyright notice and this permission notice shall be
14-
included in all copies or substantial portions of the Software.
15-
16-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1+
BSD-2-Clause Plus Patent
2+
3+
Note: This license is designed to provide: a) a simple permissive license; b) that is compatible with the GNU General Public License (GPL), version 2; and c) which also has an express patent grant included.
4+
5+
Copyright (c) 2024, ZKorum SAS.
6+
7+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10+
11+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12+
13+
Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by:
14+
15+
(a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or
16+
17+
(b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution.
18+
19+
Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise.
20+
21+
DISCLAIMER
22+
23+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+

‎LICENSE_ORIGINAL

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Copyright 2020-present Aparajita Fishman
2+
3+
MIT License
4+
5+
Permission is hereby granted, free of charge, to any person obtaining
6+
a copy of this software and associated documentation files (the
7+
"Software"), to deal in the Software without restriction, including
8+
without limitation the rights to use, copy, modify, merge, publish,
9+
distribute, sublicense, and/or sell copies of the Software, and to
10+
permit persons to whom the Software is furnished to do so, subject to
11+
the following conditions:
12+
13+
The above copyright notice and this permission notice shall be
14+
included in all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

‎README.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<div class="markdown-body">
22

3+
Modified version to ensure access to secure storage must use biometrics or device credential every 15 minutes.
4+
5+
Original project: https://github.com/aparajita/capacitor-secure-storage
6+
7+
Original License: [MIT](./LICENSE_ORIGINAL).
8+
9+
Our changes are licensed under [BSD-2-Clause-Patent](./LICENSE).
10+
311
# capacitor-secure-storage
412

513
This plugin for [Capacitor 6+](https://capacitorjs.com) provides secure key/value storage on iOS and Android. It was originally designed to be a companion to [@aparajita/capacitor-biometric-auth](https://github.com/aparajita/capacitor-biometric-auth/#readme) in order to securely store login credentials, but can be used to store any JSON data types.

‎android/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ android {
1818
namespace "com.aparajita.capacitor.securestorage"
1919
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
2020
defaultConfig {
21-
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
21+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
2222
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
2323
versionCode 1
2424
versionName "1.0"

‎android/src/main/java/com/aparajita/capacitor/securestorage/KeyStoreException.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public class KeyStoreException extends Throwable {
1717
);
1818
errorMap.put(ErrorKind.osError, "An OS error occurred (%s)");
1919
errorMap.put(ErrorKind.unknownError, "An unknown error occurred: %s");
20+
errorMap.put(
21+
ErrorKind.secureLockScreenDisabled,
22+
"Secure lock screen is disabled"
23+
);
24+
errorMap.put(ErrorKind.userNotAuthenticated, "User is not authenticated");
2025
}
2126

2227
private String message = "";
@@ -48,7 +53,10 @@ void init(ErrorKind kind, @Nullable Throwable osException) {
4853

4954
if (message != null) {
5055
switch (kind) {
51-
case osError, unknownError -> {
56+
case osError,
57+
unknownError,
58+
secureLockScreenDisabled,
59+
userNotAuthenticated -> {
5260
if (osException != null) {
5361
this.message = String.format(
5462
message,
@@ -80,5 +88,7 @@ public enum ErrorKind {
8088
invalidData,
8189
osError,
8290
unknownError,
91+
secureLockScreenDisabled,
92+
userNotAuthenticated,
8393
}
8494
}

‎android/src/main/java/com/aparajita/capacitor/securestorage/SecureStorage.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.SharedPreferences;
55
import android.security.keystore.KeyGenParameterSpec;
66
import android.security.keystore.KeyProperties;
7+
import android.security.keystore.UserNotAuthenticatedException;
78
import android.util.Base64;
89
import com.getcapacitor.JSObject;
910
import com.getcapacitor.Plugin;
@@ -13,6 +14,7 @@
1314
import java.io.IOException;
1415
import java.nio.charset.StandardCharsets;
1516
import java.security.GeneralSecurityException;
17+
import java.security.InvalidAlgorithmParameterException;
1618
import java.security.KeyStore;
1719
import java.security.UnrecoverableKeyException;
1820
import java.security.spec.AlgorithmParameterSpec;
@@ -201,6 +203,17 @@ private void tryStorageOp(PluginCall call, StorageOp op) {
201203
return;
202204
} catch (KeyStoreException e) {
203205
exception = e;
206+
} catch (InvalidAlgorithmParameterException e) {
207+
// java.lang.IllegalStateException: Secure lock screen must be enabled to create keys requiring user authentication
208+
exception = new KeyStoreException(
209+
KeyStoreException.ErrorKind.secureLockScreenDisabled,
210+
e
211+
);
212+
} catch (UserNotAuthenticatedException e) {
213+
exception = new KeyStoreException(
214+
KeyStoreException.ErrorKind.userNotAuthenticated,
215+
e
216+
);
204217
} catch (GeneralSecurityException | IOException e) {
205218
exception = new KeyStoreException(KeyStoreException.ErrorKind.osError, e);
206219
} catch (Exception e) {
@@ -237,7 +250,8 @@ private String getDataParam(PluginCall call) {
237250

238251
private String encryptString(String str, String prefixedKey)
239252
throws GeneralSecurityException, IOException {
240-
// Code taken from https://medium.com/@josiassena/using-the-android-keystore-system-to-store-sensitive-information-3a56175a454b
253+
// Code taken from
254+
// https://medium.com/@josiassena/using-the-android-keystore-system-to-store-sensitive-information-3a56175a454b
241255
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
242256
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(prefixedKey));
243257

@@ -254,8 +268,8 @@ private String encryptString(String str, String prefixedKey)
254268

255269
private String decryptString(String ciphertext, String prefixedKey)
256270
throws GeneralSecurityException, IOException, KeyStoreException {
257-
// Code taken from https://medium.com/@josiassena/using-the-android-keystore-system-to-store-sensitive-information-3a56175a454b
258-
271+
// Code taken from
272+
// https://medium.com/@josiassena/using-the-android-keystore-system-to-store-sensitive-information-3a56175a454b
259273
// Split the ciphertext into data + IV
260274
String[] parts = ciphertext.split(DATA_IV_SEPARATOR.toString());
261275

@@ -310,6 +324,12 @@ private SecretKey getSecretKey(String prefixedKey)
310324
);
311325
AlgorithmParameterSpec spec = builder
312326
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
327+
.setUserAuthenticationRequired(true)
328+
.setUserAuthenticationParameters(
329+
15 * 60,
330+
KeyProperties.AUTH_BIOMETRIC_STRONG |
331+
KeyProperties.AUTH_DEVICE_CREDENTIAL
332+
)
313333
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
314334
.build();
315335
keyGenerator.init(spec);

‎package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@aparajita/capacitor-secure-storage",
2+
"name": "@zkorum/capacitor-secure-storage",
33
"version": "6.0.1",
44
"description": "Capacitor 5+ plugin that provides secure storage for the iOS and Android",
55
"author": "Aparajita Fishman",
@@ -38,7 +38,7 @@
3838
"verify": "pnpm verify.ios && pnpm verify.android",
3939
"prerelease": "scripts/ensure-clean.sh && pnpm build",
4040
"release.preview": "commit-and-tag-version --dry-run",
41-
"release": "commit-and-tag-version --commit-all && git push --follow-tags && pnpm publish"
41+
"release": "commit-and-tag-version --commit-all && git push --follow-tags && pnpm publish --access public"
4242
},
4343
"commit-and-tag-version": {
4444
"scripts": {

‎src/definitions.ts

+9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ export enum StorageErrorType {
2626
* An unclassified system-level error occurred.
2727
*/
2828
unknownError = 'unknownError',
29+
/**
30+
* Secure lock screen must be enabled to create keys requiring user authentication
31+
* */
32+
33+
secureLockScreenDisabled = 'secureLockScreenDisabled',
34+
/**
35+
* User must be authenticated to access the secure storage
36+
* */
37+
userNotAuthenticated = 'userNotAuthenticated',
2938
}
3039

3140
/**

0 commit comments

Comments
 (0)
Please sign in to comment.