Changeset View
Changeset View
Standalone View
Standalone View
native/utils/aes-crypto-module.js
// @flow | // @flow | ||||
import { requireNativeModule } from 'expo-modules-core'; | import { requireNativeModule } from 'expo-modules-core'; | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
const KEY_SIZE = 32; // bytes | const KEY_SIZE = 32; // bytes | ||||
const IV_LENGTH = 12; // bytes, IV - unique Initialization Vector (nonce) | const IV_LENGTH = 12; // bytes, IV - unique Initialization Vector (nonce) | ||||
const TAG_LENGTH = 16; // bytes - GCM auth tag | const TAG_LENGTH = 16; // bytes - GCM auth tag | ||||
const AESCryptoModule: { | const AESCryptoModule: { | ||||
+generateKey: (destination: Uint8Array) => void, | +generateKey: (destination: Uint8Array) => void, | ||||
+encrypt: ( | +encrypt: ( | ||||
key: Uint8Array, | key: Uint8Array, | ||||
data: Uint8Array, | data: Uint8Array, | ||||
destination: Uint8Array, | destination: Uint8Array, | ||||
) => void, | ) => void, | ||||
+decrypt: ( | |||||
key: Uint8Array, | |||||
data: Uint8Array, | |||||
destination: Uint8Array, | |||||
) => void, | |||||
} = requireNativeModule('AESCrypto'); | } = requireNativeModule('AESCrypto'); | ||||
export function generateKey(): Uint8Array { | export function generateKey(): Uint8Array { | ||||
const keyBuffer = new Uint8Array(KEY_SIZE); | const keyBuffer = new Uint8Array(KEY_SIZE); | ||||
AESCryptoModule.generateKey(keyBuffer); | AESCryptoModule.generateKey(keyBuffer); | ||||
return keyBuffer; | return keyBuffer; | ||||
} | } | ||||
export function encrypt(key: Uint8Array, data: Uint8Array): Uint8Array { | export function encrypt(key: Uint8Array, data: Uint8Array): Uint8Array { | ||||
invariant(AESCryptoModule.encrypt, 'AESCrypto.encrypt is not implemented'); | invariant(AESCryptoModule.encrypt, 'AESCrypto.encrypt is not implemented'); | ||||
const sealedDataBuffer = new Uint8Array(data.length + IV_LENGTH + TAG_LENGTH); | const sealedDataBuffer = new Uint8Array(data.length + IV_LENGTH + TAG_LENGTH); | ||||
AESCryptoModule.encrypt(key, data, sealedDataBuffer); | AESCryptoModule.encrypt(key, data, sealedDataBuffer); | ||||
return sealedDataBuffer; | return sealedDataBuffer; | ||||
} | } | ||||
export function decrypt(key: Uint8Array, data: Uint8Array): Uint8Array { | |||||
invariant(AESCryptoModule.decrypt, 'AESCrypto.decrypt is not implemented'); | |||||
invariant(data.length >= IV_LENGTH + TAG_LENGTH, 'Invalid data length'); | |||||
const plaintextBuffer = new Uint8Array(data.length - IV_LENGTH - TAG_LENGTH); | |||||
AESCryptoModule.decrypt(key, data, plaintextBuffer); | |||||
return plaintextBuffer; | |||||
} |