diff --git a/app/providers/ProtocolProvider/ProtocolProvider.tsx b/app/providers/ProtocolProvider/ProtocolProvider.tsx index 6fce06a..e60b1b8 100644 --- a/app/providers/ProtocolProvider/ProtocolProvider.tsx +++ b/app/providers/ProtocolProvider/ProtocolProvider.tsx @@ -4,8 +4,8 @@ import { usePublicKey } from "../AccountProvider/usePublicKey"; import { usePrivateKeyHash } from "../AccountProvider/usePrivateKeyHash"; import { useLogger } from "@/app/hooks/useLogger"; import { useMemory } from "../MemoryProvider/useMemory"; -import { useDeviceId } from "../DeviceProvider/useDeviceId"; import { useNavigate } from "react-router-dom"; +import { useSystemInformation } from "../SystemProvider/useSystemInformation"; export enum ProtocolState { CONNECTED, @@ -27,21 +27,22 @@ export function ProtocolProvider(props : ProtocolProviderProps) { const privateKey = usePrivateKeyHash(); const protocol = useMemo(() => { return new Protocol(props.serverAddress) - }, [props.serverAddress, publicKey, privateKey]); + }, [props.serverAddress]); const log = useLogger('ProtocolProvider'); const [connect, setConnect] = useState(ProtocolState.DISCONNECTED); const [_, setOnlineSubscribes] = useMemory("online_subscribes", [], true); - const deviceId = useDeviceId(); + const systemInfo = useSystemInformation(); const navigate = useNavigate(); useEffect(() => { if(publicKey.trim() == "" - || privateKey.trim() == "" || deviceId == "") { + || privateKey.trim() == "" || systemInfo.id == "") { return; } const device = { - deviceId: deviceId, - deviceName: window.deviceName || "Unknown Device" + deviceId: systemInfo.id, + deviceName: systemInfo.name, + deviceOs: systemInfo.os } protocol.startHandshakeExchange(publicKey, privateKey, device); protocol.on('connect', () => { @@ -69,7 +70,7 @@ export function ProtocolProvider(props : ProtocolProviderProps) { setConnect(ProtocolState.DEVICE_VERIFICATION_REQUIRED); navigate('/deviceconfirm'); }); - }, [publicKey, privateKey, deviceId]); + }, [publicKey, privateKey, systemInfo.id]); return ( diff --git a/app/providers/SystemProvider/SystemProvider.tsx b/app/providers/SystemProvider/SystemProvider.tsx new file mode 100644 index 0000000..906aa06 --- /dev/null +++ b/app/providers/SystemProvider/SystemProvider.tsx @@ -0,0 +1,91 @@ +import { decodeWithPassword, encodeWithPassword } from "@/app/crypto/crypto"; +import { useFileStorage } from "@/app/hooks/useFileStorage"; +import { generateRandomKey } from "@/app/utils/utils"; +import { createContext, useEffect, useState } from "react"; + +interface SystemProviderContextValue { + id: string; + name: string; + os: string; +} + +export const SystemProviderContext = createContext(null); + +export interface SystemProviderProps { + children?: React.ReactNode; +} + +/** + * Предоставляет информацию о системе и обезличенный + * идентификатор устройства. + */ +export function SystemProvider(props: SystemProviderProps) { + const [deviceId, setDeviceId] = useState(""); + const {writeFile, readFile} = useFileStorage(); + + useEffect(() => { + fetchDeviceId(); + }, []); + + const fetchDeviceId = async () => { + const device = await readFile("device"); + if(device){ + const decoded = await decodeDevice(Buffer.from(device).toString('utf-8')); + if(decoded){ + setDeviceId(decoded); + return; + } + } + await createDeviceId(); + } + + const createDeviceId = async () => { + const newDevice = generateRandomKey(128); + const encoded = await encodeDevice(newDevice); + await writeFile("device", encoded); + setDeviceId(newDevice); + } + + const decodeDevice = async (data: string) => { + const hwid = window.deviceId; + const platform = window.deviceName; + const salt = "rosetta-device-salt"; + + try { + const decoded = await decodeWithPassword(hwid + platform + salt, data); + return decoded; + } catch (e) { + console.error("Failed to decode device data:", e); + return null; + } + } + + const encodeDevice = async (data: string) => { + const hwid = window.deviceId; + const platform = window.deviceName; + const salt = "rosetta-device-salt"; + + try { + const encoded = await encodeWithPassword(hwid + platform + salt, data); + return encoded; + } catch (e) { + console.error("Failed to encode device data:", e); + return null; + } + } + + const systemName = window.deviceName || "Unknown Device"; + const systemOs = window.platform || "Unknown OS"; + + + + return ( + + {props.children} + + ); +} \ No newline at end of file