@rrishuyadav/react-native-encrypted-async-storage
Version:
A encryption library for ReactJS and React Native Web
3 lines (2 loc) • 11.5 kB
JavaScript
import e from"@react-native-async-storage/async-storage";import{generateAESKey as t,encryptAES as r,decryptAES as n,encryptAsyncAES as a,decryptAsyncAES as i,generateRSAKeyPair as s,encryptRSA as o,decryptRSA as c,encryptAsyncRSA as y,decryptAsyncRSA as p,generateECDSAKeyPair as u,signDataECDSA as l,verifySignatureECDSA as h}from"rn-encryption";import{NativeModules as E,Platform as S}from"react-native";const{RNKeychainManager:d}=E;let A=function(e){return e.WHEN_UNLOCKED="AccessibleWhenUnlocked",e.AFTER_FIRST_UNLOCK="AccessibleAfterFirstUnlock",e.ALWAYS="AccessibleAlways",e.WHEN_PASSCODE_SET_THIS_DEVICE_ONLY="AccessibleWhenPasscodeSetThisDeviceOnly",e.WHEN_UNLOCKED_THIS_DEVICE_ONLY="AccessibleWhenUnlockedThisDeviceOnly",e.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY="AccessibleAfterFirstUnlockThisDeviceOnly",e}({}),m=function(e){return e.USER_PRESENCE="UserPresence",e.BIOMETRY_ANY="BiometryAny",e.BIOMETRY_CURRENT_SET="BiometryCurrentSet",e.DEVICE_PASSCODE="DevicePasscode",e.APPLICATION_PASSWORD="ApplicationPassword",e.BIOMETRY_ANY_OR_DEVICE_PASSCODE="BiometryAnyOrDevicePasscode",e.BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE="BiometryCurrentSetOrDevicePasscode",e}({}),g=function(e){return e.DEVICE_PASSCODE_OR_BIOMETRICS="AuthenticationWithBiometricsDevicePasscode",e.BIOMETRICS="AuthenticationWithBiometrics",e}({}),w=function(e){return e[e.SECURE_SOFTWARE=d&&d.SECURITY_LEVEL_SECURE_SOFTWARE]="SECURE_SOFTWARE",e[e.SECURE_HARDWARE=d&&d.SECURITY_LEVEL_SECURE_HARDWARE]="SECURE_HARDWARE",e[e.ANY=d&&d.SECURITY_LEVEL_ANY]="ANY",e}({}),C=function(e){return e.TOUCH_ID="TouchID",e.FACE_ID="FaceID",e.OPTIC_ID="OpticID",e.FINGERPRINT="Fingerprint",e.FACE="Face",e.IRIS="Iris",e}({}),_=function(e){return e.FB="FacebookConceal",e.AES="KeystoreAES",e.AES_CBC="KeystoreAESCBC",e.AES_GCM_NO_AUTH="KeystoreAESGCM_NoAuth",e.AES_GCM="KeystoreAESGCM",e.RSA="KeystoreRSAECB",e}({}),I=function(e){return e.NONE="none",e.AUTOMATIC_UPGRADE="automaticUpgradeToMoreSecuredStorage",e}({});const f={title:"Authenticate to retrieve secret",cancel:"Cancel"};function R(e){return"string"==typeof e?(console.warn(`You passed a service string as an argument to one of the react-native-keychain functions.\n This way of passing service is deprecated and will be removed in a future major.\n Please update your code to use { service: ${JSON.stringify(e)} }`),{service:e}):e||{}}function T(e){return"string"==typeof e?(console.warn(`You passed a server string as an argument to one of the react-native-keychain functions.\n This way of passing service is deprecated and will be removed in a future major.\n Please update your code to use { service: ${JSON.stringify(e)} }`),{server:e}):e||{}}function O(e){const t=function(e){return"storage"in e&&e.storage===_.AES?(console.warn("You passed 'AES' as a storage option to one of the react-native-keychain functions.\n This way of passing storage is deprecated and will be removed in a future major."),{...e,storage:_.AES_CBC}):e}({authenticationPrompt:f,...R(e)}),{authenticationPrompt:r}=t;return"string"==typeof r?(console.warn(`You passed a authenticationPrompt string as an argument to one of the react-native-keychain functions.\n This way of passing authenticationPrompt is deprecated and will be removed in a future major.\n Please update your code to use { authenticationPrompt: { title: ${JSON.stringify(r)} }`),t.authenticationPrompt={...f,title:r}):t.authenticationPrompt={...f,...r},t}const{RNKeychainManager:K}=E;function P(e,t,r){const n=O(r);return K.setGenericPasswordForOptions(n,e,t)}function v(e){const t=O(e);return K.getGenericPasswordForOptions(t)}function D(e){const t=R(e);return K.resetGenericPasswordForOptions(t)}function N(){return K.getAllGenericPasswordServices()}function F(e,t,r,n){return K.setInternetCredentialsForServer(e,t,r,O(n))}function U(e,t){return K.getInternetCredentialsForServer(e,O(t))}function Y(e){const t=T(e);return K.resetInternetCredentialsForOptions(t)}function G(){return K.getSupportedBiometryType?K.getSupportedBiometryType():Promise.resolve(null)}function k(){return"ios"!==S.OS?Promise.reject(new Error(`requestSharedWebCredentials() is not supported on ${S.OS} yet`)):K.requestSharedWebCredentials()}function L(e,t,r){return"ios"!==S.OS?Promise.reject(new Error(`setSharedWebCredentials() is not supported on ${S.OS} yet`)):K.setSharedWebCredentialsForServer(e,t,r)}function B(e){return K.canCheckAuthentication?K.canCheckAuthentication(e):Promise.resolve(!1)}function M(e){return K.getSecurityLevel?K.getSecurityLevel(e):Promise.resolve(null)}var b={SECURITY_LEVEL:w,ACCESSIBLE:A,ACCESS_CONTROL:m,AUTHENTICATION_TYPE:g,BIOMETRY_TYPE:C,STORAGE_TYPE:_,SECURITY_RULES:I,getSecurityLevel:M,canImplyAuthentication:B,getSupportedBiometryType:G,setInternetCredentials:F,getInternetCredentials:U,resetInternetCredentials:Y,setGenericPassword:P,getGenericPassword:v,getAllGenericPasswordServices:N,resetGenericPassword:D,requestSharedWebCredentials:k,setSharedWebCredentials:L},W=Object.freeze({__proto__:null,setGenericPassword:P,getGenericPassword:v,hasGenericPassword:function(e){const t=R(e);return K.hasGenericPasswordForOptions(t)},resetGenericPassword:D,getAllGenericPasswordServices:N,hasInternetCredentials:function(e){const t=T(e);return K.hasInternetCredentialsForOptions(t)},setInternetCredentials:F,getInternetCredentials:U,resetInternetCredentials:Y,getSupportedBiometryType:G,requestSharedWebCredentials:k,setSharedWebCredentials:L,canImplyAuthentication:B,getSecurityLevel:M,default:b,ACCESSIBLE:A,ACCESS_CONTROL:m,AUTHENTICATION_TYPE:g,SECURITY_LEVEL:w,BIOMETRY_TYPE:C,STORAGE_TYPE:_,SECURITY_RULES:I});class H{constructor(e,t){if(this.encryptionKey=null,!e||!t)throw new Error("Both Keychain and Encryption instances are required.");this.keychain=e,this.encryption=t}async getEncryptionKey(){if("string"==typeof this.encryptionKey&&this.encryptionKey)return this.encryptionKey;const e=await this.getKeyFromKeychain("encrypted_storage_key");if(e)return this.encryptionKey=e,e;const t=await this.setEncryptionKey();return this.encryptionKey=t,t}async getRSAEncryptionKey(){if(this.encryptionKey&&"object"==typeof this.encryptionKey)return this.encryptionKey;const e=await this.getKeyFromKeychain("encrypted_rsa_storage_key",!0);if(e)return this.encryptionKey=e,e;const t=await this.setRSAEncryptionKey();return this.encryptionKey=t,t}async setEncryptionKey(){const e=this.encryption.aes?.generateAESKey?.(256);if(!e)throw new Error("Failed to generate AES encryption key.");return await this.saveKeyToKeychain("encrypted_storage_key",e),this.encryptionKey=e,e}async setRSAEncryptionKey(){const e=this.encryption.rsa?.generateRSAKey?.();if(!e)throw new Error("Failed to generate RSA encryption keypair.");return await this.saveKeyToKeychain("encrypted_rsa_storage_key",JSON.stringify(e)),this.encryptionKey=e,e}async getKeyFromKeychain(e,t=!1){try{const t=await this.keychain.getGenericPassword({service:e});if(t)return t.password}catch(t){console.error(`Failed to retrieve key from Keychain (${e}):`,t)}return null}async saveKeyToKeychain(e,t){try{await this.keychain.setGenericPassword(e,t,{service:e})}catch(t){throw new Error(`Failed to save key to Keychain (${e}): ${t}`)}}}const V={Keychain:W,getGenericPassword:async e=>await v(e),async setGenericPassword(e,t,r){await P(e,t,r)}},J={aes:{generateAESKey:e=>t(e),encryptAES:(e,t)=>r(e,t),decryptAES:(e,t)=>n(e,t),encryptAsyncAES:async(e,t)=>await a(e,t),decryptAsyncAES:async(e,t)=>await i(e,t)},rsa:{generateRSAKey:()=>s(),encryptRSA:(e,t)=>o(e,t),decryptRSA:(e,t)=>c(e,t),encryptAsyncRSA:async(e,t)=>await y(e,t),decryptAsyncRSA:async(e,t)=>await p(e,t)},dataIdentity:{generateECDSAKeyPair:()=>u(),signDataECDSA:(e,t)=>l(e,t),verifySignatureECDSA:(e,t,r)=>h(e,t,r)}},j={getItem:async t=>await e.getItem(t),setItem:async(t,r)=>await e.setItem(t,r),removeItem:async t=>await e.removeItem(t),getAllKeys:async()=>[...await e.getAllKeys()],multiGet:async t=>(await e.multiGet(t)).map((([e,t])=>[e,t])),multiSet:async t=>await e.multiSet(t),multiRemove:async t=>await e.multiRemove(t),mergeItem:async(t,r)=>await e.mergeItem(t,r),multiMerge:async t=>await e.multiMerge(t)},$=new class{constructor(e,t,r){if(!e||!t)throw new Error("Keychain and Encryption instances are required.");this.keyManager=new H(e,t),this.encryption=t,this.storageAdapter=r}async getItem(e){try{const t=await this.keyManager.getEncryptionKey(),r=await this.storageAdapter.getItem(e);return r?await this.decryptData(r,t):null}catch(e){return console.error("Failed to get item:",e),null}}async setItem(e,t){try{const r=await this.keyManager.getEncryptionKey(),n=await this.encryptData(t,r);await this.storageAdapter.setItem(e,n)}catch(e){console.error("Failed to set item:",e)}}async removeItem(e){try{await this.storageAdapter.removeItem(e)}catch(e){console.error("Failed to remove item:",e)}}async getAllKeys(){try{const e=await this.storageAdapter.getAllKeys();return Array.from(e)}catch(e){return console.error("Failed to get all keys:",e),[]}}async multiGet(e){try{const t=await this.keyManager.getEncryptionKey(),r=await this.storageAdapter.multiGet(e);return await Promise.all(r.map((async([e,r])=>[e,r?await this.decryptData(r,t):null])))}catch(t){return console.error("Failed to get multiple items:",e,t),[]}}async multiSet(e){try{const t=await this.keyManager.getEncryptionKey(),r=await Promise.all(e.map((async([e,r])=>[e,await this.encryptData(r,t)])));await this.storageAdapter.multiSet(r)}catch(e){console.error("Failed to set multiple items:",e)}}async multiMerge(e){try{const t=await this.keyManager.getEncryptionKey(),r=await this.storageAdapter.multiGet(e.map((([e])=>e))),n=await Promise.all(r.map((async([e,r])=>{if(r){return[e,await this.decryptData(r,t)]}return[e,null]}))),a=e.map((([e,t])=>{const r=n.find((([t])=>t===e));let a=t;if(r&&r[1])try{const e=JSON.parse(r[1]),n=JSON.parse(t);a=JSON.stringify({...e,...n})}catch{a=t}return[e,a]})),i=await Promise.all(a.map((async([e,r])=>[e,await this.encryptData(r,t)])));await this.storageAdapter.multiSet(i)}catch(e){console.error("Failed to merge multiple items:",e)}}async multiRemove(e){try{await this.storageAdapter.multiRemove(e)}catch(e){console.error("Failed to remove multiple items:",e)}}async mergeItem(e,t){try{const r=await this.keyManager.getEncryptionKey(),n=await this.storageAdapter.getItem(e);let a=t;if(n){const e=await this.decryptData(n,r);try{const r=JSON.parse(e),n=JSON.parse(t);a=JSON.stringify({...r,...n})}catch{a=t}}const i=await this.encryptData(a,r);await this.storageAdapter.setItem(e,i)}catch(e){console.error("Failed to merge item:",e)}}async encryptData(e,t){if(this.encryption.aes)return this.encryption.aes.encryptAsyncAES?await this.encryption.aes.encryptAsyncAES(e,t):this.encryption.aes.encryptAES?.(e,t)||e;if(this.encryption.rsa)return this.encryption.rsa.encryptAsyncRSA?await this.encryption.rsa.encryptAsyncRSA(e,t.publicKey):this.encryption.rsa.encryptRSA?.(e,t.publicKey)||e;throw new Error("No encryption method available.")}async decryptData(e,t){if(this.encryption.aes)return this.encryption.aes.decryptAsyncAES?await this.encryption.aes.decryptAsyncAES(e,t):this.encryption.aes.decryptAES?.(e,t)||e;if(this.encryption.rsa)return this.encryption.rsa.decryptAsyncRSA?await this.encryption.rsa.decryptAsyncRSA(e,t.privateKey):this.encryption.rsa.decryptRSA?.(e,t.privateKey)||e;throw new Error("No decryption method available.")}}(V,J,j);export{$ as default};
//# sourceMappingURL=index.es.js.map