Получение ошибки “crypto не найдено” в React Native Expo

Вопрос или проблема

Я продолжаю получать ошибку ниже

ОШИБКА  ReferenceError: Свойство 'crypto' не существует, js движок: hermes 
    в ContextNavigator (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:145632:24)
    в ExpoRoot (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:145588:28)
    в App
    в ErrorToastContainer (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:242934:24)
    в ErrorOverlay
    в withDevTools(ErrorOverlay) (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:242437:27)
    в RCTView
    в View (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:41517:43)
    в RCTView
    в View (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:41517:43)

всякий раз, когда я пытаюсь запустить свое React Native Expo приложение в Xcode. Я не знаю, почему. Однако оно работает, когда я запускаю npm run ios в своем vscode

Я пробовал снова сгенерировать файл pod, удалить hermes из определения файла pod, но это все равно не работает в Xcode.

Вот мой компонент React Native Expo


import * as crypto from 'crypto';
import React, { useEffect, useState } from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import DeviceInfo from 'react-native-device-info';
import * as Device from 'expo-device';
import { useVerifyDeviceMutation } from './verifyDeviceQuery.generated';

type DeviceVerificationPayload = {
    deviceVariantIdentifier: string;
    deviceOsVersion: string;
};

const encrypt = (payload: DeviceVerificationPayload) => {
    const algorithm = ‘aes-256-cbc’;
    const encryptionAlgoKey = ‘Key’;
    const encryptionKey = base64ToUtf8(encryptionAlgoKey);
    const key = CryptoJS.SHA256(encryptionKey);
    const iv = CryptoJS.lib.WordArray.create(key.words.slice(0, 4));
    const stringifiedPayload = JSON.stringify(payload);
    const cipher = crypto.createCipheriv(algorithm, key, iv); 
    let encrypted = cipher.update(stringifiedPayload, 'utf8', 'hex'); 
    encrypted += cipher.final('hex'); return encrypted;
    return encrypted;
};

export default function HomeScreen() {
    const deviceVerificationGuid = 'deviceVerificationGuid';
    const [isVerifying, setIsVerifying] = useState<boolean>(true);
    const [deviceVerificationFailure, setDeviceVerificationFailure] = useState<boolean>(false);

    const [verifyDevice, { loading }] = useVerifyDeviceMutation({
        onCompleted: () => {
            setIsVerifying(false);
        },
        onError: (data) => {
            setIsVerifying(false);
            setDeviceVerificationFailure(true);
        }
    });

    useEffect(() => {
            const deviceVariantIdentifier = Device.modelName || '';
            const deviceOsVersion = Device.osVersion || '';
            const signature = encrypt({
                deviceVariantIdentifier,
                deviceOsVersion
            });

            verifyDevice({
                variables: {
                    input: {
                        deviceVariantIdentifier,
                        deviceOsVersion,
                        signature,
                        deviceVerificationGuid
                    }
                }
            });
    }, [deviceVerificationGuid, verifyDevice]);

    if (!deviceVerificationGuid) {
        return (
            <View style={styles.container}>
                <Image source={require('./assets/loadicon.gif')} style={styles.image} />
            </View>
        );
    }

    return (
        <View style={styles.container}>
          Логика пользовательского интерфейса
        </View>
    );
}

Вышеуказанное работает всякий раз, когда я запускаю npm run ios, но конкретно не работает, когда я запускаю его на Xcode.
Не совсем уверен, почему это происходит

Проблема в

import * as crypto from 'crypto';

Модуль Crypto доступен только в приложениях javascript на стороне сервера, т.е. в приложениях, которые запускаются на node. React и React Native являются клиентскими, поэтому нативная библиотека crypto не будет работать. Вы можете вместо этого использовать встроенную библиотеку expo crypto или использовать сторонний пакет, такой как crypto-js

Ответ или решение

Ошибка "crypto not found" в вашему проекте React Native Expo связана с попыткой использовать модуль crypto, который доступен только в серверной среде Node.js. В контексте React и React Native, которые ориентированы на клиентскую часть, использование встроенного модуля crypto невозможно, что и приводит к возникновению этой ошибки, особенно при запуске проекта через Xcode.

Рекомендации по решению проблемы

  1. Использование библиотеки Expo Crypto:
    Expo предоставляет собственный модуль для работы с криптографией, который можно использовать вместо стандартного crypto. Чтобы это сделать, внесите следующие изменения в ваш код:

    Замените строку импорта:

    import * as crypto from 'crypto';

    на

    import * as Crypto from 'expo-crypto';

    После чего обновите вашу функцию encrypt для использования методов из expo-crypto.

  2. Как использовать expo-crypto:
    Пример вашего кода с учетом изменений может выглядеть следующим образом:

    import * as Crypto from 'expo-crypto';
    import { Buffer } from 'buffer';
    
    const encrypt = async (payload) => {
       const algorithm = 'aes-256-cbc';
       const encryptionAlgoKey = 'Key';
       const encryptionKey = base64ToUtf8(encryptionAlgoKey);
       const key = CryptoJS.SHA256(encryptionKey);
       const iv = CryptoJS.lib.WordArray.create(key.words.slice(0, 4));
       const stringifiedPayload = JSON.stringify(payload);
    
       // Использование expo-crypto для криптографии
       const cipher = await Crypto.getRandomBytesAsync(32); // Получение случайного байта
       const encrypted = // Здесь ваша логика шифрования с использованием crypto из Expo
       return encrypted;
    };
  3. Использование crypto-js:
    Если вам нужно больше возможностей для криптографии или если вы хотите оставить много кода без изменений, вы можете использовать библиотеку crypto-js. Для установки выполните:

    npm install crypto-js

    Затем импортируйте необходимые алгоритмы в свой файл:

    import CryptoJS from 'crypto-js';

    Измените логику шифрования в функции encrypt, используя методы из crypto-js.

Заключение

Если вы продолжаете сталкиваться с ошибками при запуске вашего приложения через Xcode, убедитесь, что вы очищаете кэш и перестраиваете проект. Это можно сделать с помощью следующих команд:

cd ios
pod install
cd ..
expo start -c

Следуя предложенным рекомендациям, вы сможете избавиться от ошибки ReferenceError: Property 'crypto' doesn't exist и успешно запустить ваше React Native приложение с использованием Expo.

Оцените материал
Добавить комментарий

Капча загружается...