Skip to content

Commit

Permalink
Release 9.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
DorianMazur committed Nov 11, 2024
1 parent c9e2322 commit 8852b5b
Show file tree
Hide file tree
Showing 41 changed files with 1,987 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-keychain",
"version": "9.1.0",
"version": "9.2.0",
"description": "Keychain Access for React Native",
"main": "./lib/commonjs/index.js",
"module": "./lib/module/index",
Expand Down
219 changes: 219 additions & 0 deletions website/docs/choosing-storage-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
---
id: choosing-storage-type
title: '[Android] Choosing Storage Type'
---

On Android, securing sensitive data requires careful consideration of different storage types. This guide helps you choose the right storage type.

## Security Levels

We offer three security levels for data storage:

### 1. High Security (with Biometric Authentication)

- **AES_GCM**: Symmetric encryption with biometric protection
- **RSA**: Asymmetric encryption with biometric protection
- Best for: Passwords, personal data, sensitive keys

### 2. Medium Security (without Authentication)

- **AES_GCM_NO_AUTH**: Symmetric encryption without biometric requirements
- Best for: Cached data, non-sensitive encrypted data

### 3. Legacy/Deprecated

- **AES_CBC**, **FB** (Facebook Conceal)
- ⚠️ Not recommended for new implementations

## Storage Type Selection Guide

### Use AES_GCM (High Security) for:

- User credentials (passwords, tokens)
- Personal information (SSN, credit cards)
- Encryption keys (symmetric keys)

```typescript
import { setGenericPassword, STORAGE_TYPE } from 'react-native-keychain';

await setGenericPassword(
'username',
'password123',
{
accessControl: ACCESS_CONTROL.BIOMETRY_ANY,
accessible: ACCESSIBLE.WHEN_UNLOCKED,
storage: STORAGE_TYPE.AES_GCM,
}
);
```

### Use RSA (High Security) for:

- Digital signatures
- Key exchange
- Public/private key operations

```typescript
import { setGenericPassword, STORAGE_TYPE } from 'react-native-keychain';

await setGenericPassword(
'auth_key_id',
privateKeyData,
{
accessControl: ACCESS_CONTROL.BIOMETRY_ANY,
accessible: ACCESSIBLE.WHEN_UNLOCKED,
storage: STORAGE_TYPE.RSA,
}
);
```

### Use AES_GCM_NO_AUTH (Medium Security) for:

- Cache data
- Local data
- Temporary storage

```typescript
import { setGenericPassword, STORAGE_TYPE } from 'react-native-keychain';

await setGenericPassword(
'cache_key',
cacheData,
{
accessible: ACCESSIBLE.WHEN_UNLOCKED,
storage: STORAGE_TYPE.AES_GCM_NO_AUTH,
}
);
```

## Complete Examples

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

<Tabs>
<TabItem value="biometrics" label="With Biometrics">

```typescript
import {
setGenericPassword,
getGenericPassword,
getSupportedBiometryType,
STORAGE_TYPE,
ACCESS_CONTROL,
ACCESSIBLE,
} from 'react-native-keychain';

// Store credentials with biometric protection
async function storeCredentials(username: string, password: string) {
try {
// Check biometric availability
const biometryType = await getSupportedBiometryType();

// Handle biometric requirement
if (options.requireBiometrics && !biometryType) {
throw new Error('Biometric authentication is required but not available');
}

await setGenericPassword(username, password, {
accessControl: ACCESS_CONTROL.BIOMETRY_ANY,
accessible: ACCESSIBLE.WHEN_UNLOCKED,
storage: STORAGE_TYPE.AES_GCM,
authenticationType: AUTHENTICATION_TYPE.BIOMETRICS,
});
console.log('Credentials stored successfully');
} catch (error) {
console.error('Error storing credentials:', error);
}
}

// Retrieve credentials (will trigger biometric prompt)
async function retrieveCredentials() {
try {
const credentials = await getGenericPassword();
if (credentials) {
console.log('Username:', credentials.username);
console.log('Password:', credentials.password);
return credentials;
}
return null;
} catch (error) {
console.error('Error retrieving credentials:', error);
return null;
}
}
```
</TabItem>
<TabItem value="no-biometrics" label="Without Biometrics">

```typescript
import {
setGenericPassword,
getGenericPassword,
STORAGE_TYPE,
ACCESS_CONTROL,
ACCESSIBLE,
} from 'react-native-keychain';

// Store credentials with biometric protection
async function storeCredentials(username: string, password: string) {
try {
await setGenericPassword(username, password, {
accessControl: ACCESS_CONTROL.BIOMETRY_ANY,
accessible: ACCESSIBLE.WHEN_UNLOCKED,
storage: STORAGE_TYPE.AES_GCM_NO_AUTH,
authenticationType: AUTHENTICATION_TYPE.BIOMETRICS,
});
console.log('Credentials stored successfully');
} catch (error) {
console.error('Error storing credentials:', error);
}
}

// Retrieve credentials (will trigger biometric prompt)
async function retrieveCredentials() {
try {
const credentials = await getGenericPassword();
if (credentials) {
console.log('Username:', credentials.username);
console.log('Password:', credentials.password);
return credentials;
}
return null;
} catch (error) {
console.error('Error retrieving credentials:', error);
return null;
}
}
```
</TabItem>
</Tabs>

## Security Considerations

### AES_GCM
- Requires biometric authentication for both encryption and decryption
- Uses 256-bit keys
- Provides authenticated encryption (confidentiality + integrity)
- Best choice for most sensitive data

### RSA
- Requires biometric authentication for private key operations
- Uses 2048-bit keys
- Limited by maximum encryption size
- Best for asymmetric operations

### AES_GCM_NO_AUTH
- No biometric requirement
- Still provides authenticated encryption
- Good balance of security and usability for non-sensitive data


## Best Practices

1. Always use biometric protection (`AES_GCM` or `RSA`) for sensitive user data
2. Use `AES_GCM_NO_AUTH` for non-sensitive but private app data
3. Handle biometric authentication errors gracefully
4. Provide fallback mechanisms when biometrics are not available
5. Clear sensitive data when the user logs out
6. Don't store sensitive data in plain text or with deprecated storage types
2 changes: 1 addition & 1 deletion website/docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Ensure the `rules` property is set to the string value `AUTOMATIC_UPGRADE`.
**A:** To force a specific encryption level, call:

```tsx
setGenericPassword({ ...otherProps, storage: "AES" });
setGenericPassword({ ...otherProps, storage: "AES_GCM_NO_AUTH" });
```

> **Note:** If you attempt to force `RSA` storage when biometrics are not available, the call will be rejected with an error related to the device's biometric configuration.
2 changes: 1 addition & 1 deletion website/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ The module automatically selects the appropriate `CipherStorage` implementation
- **API levels 16-22**: Uses Facebook Conceal for encryption/decryption.
- **API level 23+**: Uses Android Keystore for encryption/decryption.

Encrypted data is stored in `SharedPreferences`.
Encrypted data is stored in `Jetpack DataStore`.

#### Multiple Credentials

Expand Down
5 changes: 5 additions & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const sidebars: SidebarsConfig = {
id: 'usage',
label: 'Usage',
},
{
type: 'doc',
id: 'choosing-storage-type',
label: '[Android] Choosing Storage Type',
},
{
type: 'doc',
id: 'jest',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Enumeration: ACCESSIBLE

Enum representing when a keychain item is accessible.

## Enumeration Members

### AFTER\_FIRST\_UNLOCK

> **AFTER\_FIRST\_UNLOCK**: `"AccessibleAfterFirstUnlock"`
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.

#### Defined in

[enums.ts:12](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L12)

***

### AFTER\_FIRST\_UNLOCK\_THIS\_DEVICE\_ONLY

> **AFTER\_FIRST\_UNLOCK\_THIS\_DEVICE\_ONLY**: `"AccessibleAfterFirstUnlockThisDeviceOnly"`
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user. Items with this attribute never migrate to a new device.

#### Defined in

[enums.ts:20](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L20)

***

### ALWAYS

> **ALWAYS**: `"AccessibleAlways"`
The data in the keychain item can always be accessed regardless of whether the device is locked.

#### Defined in

[enums.ts:14](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L14)

***

### WHEN\_PASSCODE\_SET\_THIS\_DEVICE\_ONLY

> **WHEN\_PASSCODE\_SET\_THIS\_DEVICE\_ONLY**: `"AccessibleWhenPasscodeSetThisDeviceOnly"`
The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device. Items with this attribute never migrate to a new device.

#### Defined in

[enums.ts:16](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L16)

***

### WHEN\_UNLOCKED

> **WHEN\_UNLOCKED**: `"AccessibleWhenUnlocked"`
The data in the keychain item can be accessed only while the device is unlocked by the user.

#### Defined in

[enums.ts:10](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L10)

***

### WHEN\_UNLOCKED\_THIS\_DEVICE\_ONLY

> **WHEN\_UNLOCKED\_THIS\_DEVICE\_ONLY**: `"AccessibleWhenUnlockedThisDeviceOnly"`
The data in the keychain item can be accessed only while the device is unlocked by the user. Items with this attribute do not migrate to a new device.

#### Defined in

[enums.ts:18](https://github.com/oblador/react-native-keychain/blob/7eaf30e4858d9a03afd4c8e017b83a96fbc4e982/src/enums.ts#L18)
Loading

0 comments on commit 8852b5b

Please sign in to comment.