expo-crypto
Version:
Provides cryptography primitives for Android, iOS and web.
70 lines (63 loc) • 2.28 kB
text/typescript
import type { TypedArray } from 'expo-modules-core';
import { CodedError } from 'expo-modules-core';
import type { CryptoDigestAlgorithm, CryptoDigestOptions } from './Crypto.types';
import { CryptoEncoding } from './Crypto.types';
const getCrypto = (): Crypto => {
if (typeof globalThis.crypto !== 'undefined') {
return globalThis.crypto;
} else if (typeof window !== 'undefined') {
return window.crypto ?? (window as any).msCrypto;
} else {
return crypto;
}
};
export default {
async digestStringAsync(
algorithm: CryptoDigestAlgorithm,
data: string,
options: CryptoDigestOptions
): Promise<string> {
const crypto = getCrypto();
if (!crypto.subtle) {
throw new CodedError(
'ERR_CRYPTO_UNAVAILABLE',
'Access to the WebCrypto API is restricted to secure origins (localhost/https).'
);
}
const encoder = new TextEncoder();
const buffer = encoder.encode(data);
const hashedData = await crypto.subtle.digest(algorithm, buffer);
if (options.encoding === CryptoEncoding.HEX) {
return hexString(hashedData);
} else if (options.encoding === CryptoEncoding.BASE64) {
return btoa(String.fromCharCode(...new Uint8Array(hashedData)));
}
throw new CodedError('ERR_CRYPTO_DIGEST', 'Invalid encoding type provided.');
},
getRandomBytes(length: number): Uint8Array {
const array = new Uint8Array(length);
return getCrypto().getRandomValues(array);
},
async getRandomBytesAsync(length: number): Promise<Uint8Array> {
const array = new Uint8Array(length);
return getCrypto().getRandomValues(array);
},
getRandomValues(typedArray: TypedArray) {
return getCrypto().getRandomValues(typedArray as ArrayBufferView<ArrayBuffer>);
},
randomUUID() {
return getCrypto().randomUUID();
},
digestAsync(algorithm: AlgorithmIdentifier, data: ArrayBuffer): Promise<ArrayBuffer> {
return getCrypto().subtle.digest(algorithm, data);
},
};
function hexString(buffer: ArrayBuffer): string {
const byteArray = new Uint8Array(buffer);
const hexCodes = [...byteArray].map((value) => {
const hexCode = value.toString(16);
const paddedHexCode = hexCode.padStart(2, '0');
return paddedHexCode;
});
return hexCodes.join('');
}