[feat] add shared mobile device trust protocol and pairing resources

This commit is contained in:
dijunkun committed 2026-11-13 11:07:00 +08:00
1 parent 7d8daa27eb
commit e6e72ed511
26 files changed
+372 -3

No files matched your search

@@ -314,6 +314,13 @@ final class LocalizationKeys {
IDS.put("被控端分辨率", R.string.text_59c9dca5568a6cd3);
IDS.put("设备不支持", R.string.text_36e0073276c0e39f);
IDS.put("等待电脑端确认…", R.string.text_7b3440ad0f81b811);
IDS.put("将配对信息添加到被控端的可信设备列表,并核对指纹。", R.string.text_728ea431051d269e);
IDS.put("本机配对信息", R.string.text_56a998ff5c730e20);
IDS.put("查看指纹", R.string.text_976f1504103f24ac);
IDS.put("复制配对信息", R.string.text_3aab57c59aba6543);
IDS.put("配对信息已复制。", R.string.text_cbacf1eafbca53e0);
IDS.put("无法复制配对信息,请重试。", R.string.text_cde42ccdeacbbbd9);
IDS.put("安全存储不可用,请解锁设备后重试", R.string.text_7383b2ae09252c59);
}
private LocalizationKeys() {}
}
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"被控端分辨率"</string>
<string name="text_36e0073276c0e39f" formatted="false">"设备不支持"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"等待电脑端确认…"</string>
<string name="text_728ea431051d269e" formatted="false">"将配对信息添加到被控端的可信设备列表,并核对指纹。"</string>
<string name="text_56a998ff5c730e20" formatted="false">"本机配对信息"</string>
<string name="text_976f1504103f24ac" formatted="false">"查看指纹"</string>
<string name="text_3aab57c59aba6543" formatted="false">"复制配对信息"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"配对信息已复制。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"无法复制配对信息,请重试。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全存储不可用,请解锁设备后重试"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"被控端解析度"</string>
<string name="text_36e0073276c0e39f" formatted="false">"裝置不支援"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"等待電腦端確認…"</string>
<string name="text_728ea431051d269e" formatted="false">"將配對資訊新增至被控端的可信裝置清單,並核對指紋。"</string>
<string name="text_56a998ff5c730e20" formatted="false">"本機配對資訊"</string>
<string name="text_976f1504103f24ac" formatted="false">"查看指紋"</string>
<string name="text_3aab57c59aba6543" formatted="false">"複製配對資訊"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"配對資訊已複製。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"無法複製配對資訊,請重試。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全儲存不可用,請解鎖裝置後重試"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Auflösung des entfernten Bildschirms"</string>
<string name="text_36e0073276c0e39f" formatted="false">"Nicht unterstützt"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"Warten auf Bestätigung vom Computer..."</string>
<string name="text_728ea431051d269e" formatted="false">"Fügen Sie diese Kopplungsdaten auf dem gesteuerten Gerät zur Vertrauensliste hinzu und prüfen Sie den Fingerabdruck."</string>
<string name="text_56a998ff5c730e20" formatted="false">"Kopplungsdaten dieses Geräts"</string>
<string name="text_976f1504103f24ac" formatted="false">"Fingerabdruck anzeigen"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Kopplungsdaten kopieren"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Kopplungsdaten kopiert."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Kopplungsdaten konnten nicht kopiert werden. Bitte erneut versuchen."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Der sichere Speicher ist nicht verfügbar. Bitte entsperren Sie das Gerät und versuchen Sie es erneut"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Resolución de la pantalla remota"</string>
<string name="text_36e0073276c0e39f" formatted="false">"No compatible"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"Esperando confirmación del ordenador..."</string>
<string name="text_728ea431051d269e" formatted="false">"Añada esta información de emparejamiento a la lista de confianza del dispositivo controlado y verifique la huella."</string>
<string name="text_56a998ff5c730e20" formatted="false">"Información de este dispositivo"</string>
<string name="text_976f1504103f24ac" formatted="false">"Ver huella"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Copiar información"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Información de emparejamiento copiada."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"No se pudo copiar la información de emparejamiento. Inténtelo de nuevo."</string>
<string name="text_7383b2ae09252c59" formatted="false">"El almacenamiento seguro no está disponible. Desbloquee el dispositivo e inténtelo nuevamente."</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Résolution de l’écran distant"</string>
<string name="text_36e0073276c0e39f" formatted="false">"Non pris en charge"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"En attente de confirmation de l\'ordinateur..."</string>
<string name="text_728ea431051d269e" formatted="false">"Ajoutez ces informations à la liste des appareils de confiance de l’appareil contrôlé et vérifiez l’empreinte."</string>
<string name="text_56a998ff5c730e20" formatted="false">"Informations de cet appareil"</string>
<string name="text_976f1504103f24ac" formatted="false">"Afficher l’empreinte"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Copier les informations"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Informations d’association copiées."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Impossible de copier les informations d’association. Réessayez."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Le stockage sécurisé n\'est pas disponible, veuillez déverrouiller l\'appareil et réessayer"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"接続先の画面解像度"</string>
<string name="text_36e0073276c0e39f" formatted="false">"サポートされていません"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"コンピューターからの確認を待っています..."</string>
<string name="text_728ea431051d269e" formatted="false">"操作されるデバイスの信頼済みリストにこのペアリング情報を追加し、フィンガープリントを確認してください。"</string>
<string name="text_56a998ff5c730e20" formatted="false">"このデバイスのペアリング情報"</string>
<string name="text_976f1504103f24ac" formatted="false">"フィンガープリントを表示"</string>
<string name="text_3aab57c59aba6543" formatted="false">"ペアリング情報をコピー"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"ペアリング情報をコピーしました。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"ペアリング情報をコピーできません。もう一度お試しください。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全なストレージが利用できません。デバイスのロックを解除して、もう一度お試しください。"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"원격 화면 해상도"</string>
<string name="text_36e0073276c0e39f" formatted="false">"지원되지 않음"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"컴퓨터의 확인을 기다리는 중..."</string>
<string name="text_728ea431051d269e" formatted="false">"제어 대상 장치의 신뢰 목록에 이 페어링 정보를 추가하고 지문을 확인하세요."</string>
<string name="text_56a998ff5c730e20" formatted="false">"이 장치의 페어링 정보"</string>
<string name="text_976f1504103f24ac" formatted="false">"지문 보기"</string>
<string name="text_3aab57c59aba6543" formatted="false">"페어링 정보 복사"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"페어링 정보를 복사했습니다."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"페어링 정보를 복사할 수 없습니다. 다시 시도하세요."</string>
<string name="text_7383b2ae09252c59" formatted="false">"보안 저장소를 사용할 수 없습니다. 장치를 잠금 해제한 후 다시 시도해 주세요."</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Resolução da tela remota"</string>
<string name="text_36e0073276c0e39f" formatted="false">"Não suportado"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"Aguardando confirmação do computador..."</string>
<string name="text_728ea431051d269e" formatted="false">"Adicione estas informações de pareamento à lista de confiança do dispositivo controlado e confira a impressão digital."</string>
<string name="text_56a998ff5c730e20" formatted="false">"Informações deste dispositivo"</string>
<string name="text_976f1504103f24ac" formatted="false">"Ver impressão digital"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Copiar informações"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Informações de pareamento copiadas."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Não foi possível copiar as informações de pareamento. Tente novamente."</string>
<string name="text_7383b2ae09252c59" formatted="false">"O armazenamento seguro não está disponível. Desbloqueie o dispositivo e tente novamente"</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Разрешение удалённого экрана"</string>
<string name="text_36e0073276c0e39f" formatted="false">"Не поддерживается"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"Ожидание подтверждения от компьютера..."</string>
<string name="text_728ea431051d269e" formatted="false">"Добавьте эти данные сопряжения в список доверенных устройств на управляемом компьютере и сверьте отпечаток."</string>
<string name="text_56a998ff5c730e20" formatted="false">"Данные этого устройства"</string>
<string name="text_976f1504103f24ac" formatted="false">"Показать отпечаток"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Копировать данные"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Данные сопряжения скопированы."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Не удалось скопировать данные сопряжения. Повторите попытку."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Безопасное хранилище недоступно. Разблокируйте устройство и повторите попытку."</string>
</resources>
@@ -308,4 +308,11 @@
<string name="text_59c9dca5568a6cd3" formatted="false">"Remote display resolution"</string>
<string name="text_36e0073276c0e39f" formatted="false">"Unsupported"</string>
<string name="text_7b3440ad0f81b811" formatted="false">"Waiting for confirmation from the computer..."</string>
<string name="text_728ea431051d269e" formatted="false">"Add this pairing information to the controlled device’s trusted list and verify the fingerprint."</string>
<string name="text_56a998ff5c730e20" formatted="false">"This device’s pairing info"</string>
<string name="text_976f1504103f24ac" formatted="false">"View fingerprint"</string>
<string name="text_3aab57c59aba6543" formatted="false">"Copy pairing info"</string>
<string name="text_cbacf1eafbca53e0" formatted="false">"Pairing information copied."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Unable to copy pairing information. Please try again."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Secure storage is unavailable, please unlock the device and try again"</string>
</resources>
@@ -242,4 +242,10 @@ export const translations: Record<string, string[]> = {
"鼠标控制": ["鼠标控制", "Mouse control", "Управление мышью", "滑鼠控制", "マウスコントロール", "마우스 제어", "Maussteuerung", "Contrôle de la souris", "Control del ratón", "Controle do mouse"],
"被控端分辨率": ["被控端分辨率", "Remote display resolution", "Разрешение удалённого экрана", "被控端解析度", "接続先の画面解像度", "원격 화면 해상도", "Auflösung des entfernten Bildschirms", "Résolution de l’écran distant", "Resolución de la pantalla remota", "Resolução da tela remota"],
"设备不支持": ["设备不支持", "Unsupported", "Не поддерживается", "裝置不支援", "サポートされていません", "지원되지 않음", "Nicht unterstützt", "Non pris en charge", "No compatible", "Não suportado"],
"将配对信息添加到被控端的可信设备列表,并核对指纹。": ["将配对信息添加到被控端的可信设备列表,并核对指纹。", "Add this pairing information to the controlled device’s trusted list and verify the fingerprint.", "Добавьте эти данные сопряжения в список доверенных устройств на управляемом компьютере и сверьте отпечаток.", "將配對資訊新增至被控端的可信裝置清單,並核對指紋。", "操作されるデバイスの信頼済みリストにこのペアリング情報を追加し、フィンガープリントを確認してください。", "제어 대상 장치의 신뢰 목록에 이 페어링 정보를 추가하고 지문을 확인하세요.", "Fügen Sie diese Kopplungsdaten auf dem gesteuerten Gerät zur Vertrauensliste hinzu und prüfen Sie den Fingerabdruck.", "Ajoutez ces informations à la liste des appareils de confiance de l’appareil contrôlé et vérifiez l’empreinte.", "Añada esta información de emparejamiento a la lista de confianza del dispositivo controlado y verifique la huella.", "Adicione estas informações de pareamento à lista de confiança do dispositivo controlado e confira a impressão digital."],
"本机配对信息": ["本机配对信息", "This device’s pairing info", "Данные этого устройства", "本機配對資訊", "このデバイスのペアリング情報", "이 장치의 페어링 정보", "Kopplungsdaten dieses Geräts", "Informations de cet appareil", "Información de este dispositivo", "Informações deste dispositivo"],
"查看指纹": ["查看指纹", "View fingerprint", "Показать отпечаток", "查看指紋", "フィンガープリントを表示", "지문 보기", "Fingerabdruck anzeigen", "Afficher l’empreinte", "Ver huella", "Ver impressão digital"],
"复制配对信息": ["复制配对信息", "Copy pairing info", "Копировать данные", "複製配對資訊", "ペアリング情報をコピー", "페어링 정보 복사", "Kopplungsdaten kopieren", "Copier les informations", "Copiar información", "Copiar informações"],
"配对信息已复制。": ["配对信息已复制。", "Pairing information copied.", "Данные сопряжения скопированы.", "配對資訊已複製。", "ペアリング情報をコピーしました。", "페어링 정보를 복사했습니다.", "Kopplungsdaten kopiert.", "Informations d’association copiées.", "Información de emparejamiento copiada.", "Informações de pareamento copiadas."],
"无法复制配对信息,请重试。": ["无法复制配对信息,请重试。", "Unable to copy pairing information. Please try again.", "Не удалось скопировать данные сопряжения. Повторите попытку.", "無法複製配對資訊,請重試。", "ペアリング情報をコピーできません。もう一度お試しください。", "페어링 정보를 복사할 수 없습니다. 다시 시도하세요.", "Kopplungsdaten konnten nicht kopiert werden. Bitte erneut versuchen.", "Impossible de copier les informations d’association. Réessayez.", "No se pudo copiar la información de emparejamiento. Inténtelo de nuevo.", "Não foi possível copiar as informações de pareamento. Tente novamente."],
};
@@ -288,3 +288,10 @@
"被控端分辨率" = "Auflösung des entfernten Bildschirms";
"设备不支持" = "Nicht unterstützt";
"等待电脑端确认…" = "Warten auf Bestätigung vom Computer...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Fügen Sie diese Kopplungsdaten auf dem gesteuerten Gerät zur Vertrauensliste hinzu und prüfen Sie den Fingerabdruck.";
"本机配对信息" = "Kopplungsdaten dieses Geräts";
"查看指纹" = "Fingerabdruck anzeigen";
"复制配对信息" = "Kopplungsdaten kopieren";
"配对信息已复制。" = "Kopplungsdaten kopiert.";
"无法复制配对信息,请重试。" = "Kopplungsdaten konnten nicht kopiert werden. Bitte erneut versuchen.";
"安全存储不可用,请解锁设备后重试" = "Der sichere Speicher ist nicht verfügbar. Bitte entsperren Sie das Gerät und versuchen Sie es erneut";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Remote display resolution";
"设备不支持" = "Unsupported";
"等待电脑端确认…" = "Waiting for confirmation from the computer...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Add this pairing information to the controlled device’s trusted list and verify the fingerprint.";
"本机配对信息" = "This device’s pairing info";
"查看指纹" = "View fingerprint";
"复制配对信息" = "Copy pairing info";
"配对信息已复制。" = "Pairing information copied.";
"无法复制配对信息,请重试。" = "Unable to copy pairing information. Please try again.";
"安全存储不可用,请解锁设备后重试" = "Secure storage is unavailable, please unlock the device and try again";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Resolución de la pantalla remota";
"设备不支持" = "No compatible";
"等待电脑端确认…" = "Esperando confirmación del ordenador...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Añada esta información de emparejamiento a la lista de confianza del dispositivo controlado y verifique la huella.";
"本机配对信息" = "Información de este dispositivo";
"查看指纹" = "Ver huella";
"复制配对信息" = "Copiar información";
"配对信息已复制。" = "Información de emparejamiento copiada.";
"无法复制配对信息,请重试。" = "No se pudo copiar la información de emparejamiento. Inténtelo de nuevo.";
"安全存储不可用,请解锁设备后重试" = "El almacenamiento seguro no está disponible. Desbloquee el dispositivo e inténtelo nuevamente.";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Résolution de l’écran distant";
"设备不支持" = "Non pris en charge";
"等待电脑端确认…" = "En attente de confirmation de l'ordinateur...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Ajoutez ces informations à la liste des appareils de confiance de l’appareil contrôlé et vérifiez l’empreinte.";
"本机配对信息" = "Informations de cet appareil";
"查看指纹" = "Afficher l’empreinte";
"复制配对信息" = "Copier les informations";
"配对信息已复制。" = "Informations d’association copiées.";
"无法复制配对信息,请重试。" = "Impossible de copier les informations d’association. Réessayez.";
"安全存储不可用,请解锁设备后重试" = "Le stockage sécurisé n'est pas disponible, veuillez déverrouiller l'appareil et réessayer";
@@ -288,3 +288,10 @@
"被控端分辨率" = "接続先の画面解像度";
"设备不支持" = "サポートされていません";
"等待电脑端确认…" = "コンピューターからの確認を待っています...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "操作されるデバイスの信頼済みリストにこのペアリング情報を追加し、フィンガープリントを確認してください。";
"本机配对信息" = "このデバイスのペアリング情報";
"查看指纹" = "フィンガープリントを表示";
"复制配对信息" = "ペアリング情報をコピー";
"配对信息已复制。" = "ペアリング情報をコピーしました。";
"无法复制配对信息,请重试。" = "ペアリング情報をコピーできません。もう一度お試しください。";
"安全存储不可用,请解锁设备后重试" = "安全なストレージが利用できません。デバイスのロックを解除して、もう一度お試しください。";
@@ -288,3 +288,10 @@
"被控端分辨率" = "원격 화면 해상도";
"设备不支持" = "지원되지 않음";
"等待电脑端确认…" = "컴퓨터의 확인을 기다리는 중...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "제어 대상 장치의 신뢰 목록에 이 페어링 정보를 추가하고 지문을 확인하세요.";
"本机配对信息" = "이 장치의 페어링 정보";
"查看指纹" = "지문 보기";
"复制配对信息" = "페어링 정보 복사";
"配对信息已复制。" = "페어링 정보를 복사했습니다.";
"无法复制配对信息,请重试。" = "페어링 정보를 복사할 수 없습니다. 다시 시도하세요.";
"安全存储不可用,请解锁设备后重试" = "보안 저장소를 사용할 수 없습니다. 장치를 잠금 해제한 후 다시 시도해 주세요.";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Resolução da tela remota";
"设备不支持" = "Não suportado";
"等待电脑端确认…" = "Aguardando confirmação do computador...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Adicione estas informações de pareamento à lista de confiança do dispositivo controlado e confira a impressão digital.";
"本机配对信息" = "Informações deste dispositivo";
"查看指纹" = "Ver impressão digital";
"复制配对信息" = "Copiar informações";
"配对信息已复制。" = "Informações de pareamento copiadas.";
"无法复制配对信息,请重试。" = "Não foi possível copiar as informações de pareamento. Tente novamente.";
"安全存储不可用,请解锁设备后重试" = "O armazenamento seguro não está disponível. Desbloqueie o dispositivo e tente novamente";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Resolução da tela remota";
"设备不支持" = "Não suportado";
"等待电脑端确认…" = "Aguardando confirmação do computador...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Adicione estas informações de pareamento à lista de confiança do dispositivo controlado e confira a impressão digital.";
"本机配对信息" = "Informações deste dispositivo";
"查看指纹" = "Ver impressão digital";
"复制配对信息" = "Copiar informações";
"配对信息已复制。" = "Informações de pareamento copiadas.";
"无法复制配对信息,请重试。" = "Não foi possível copiar as informações de pareamento. Tente novamente.";
"安全存储不可用,请解锁设备后重试" = "O armazenamento seguro não está disponível. Desbloqueie o dispositivo e tente novamente";
@@ -288,3 +288,10 @@
"被控端分辨率" = "Разрешение удалённого экрана";
"设备不支持" = "Не поддерживается";
"等待电脑端确认…" = "Ожидание подтверждения от компьютера...";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "Добавьте эти данные сопряжения в список доверенных устройств на управляемом компьютере и сверьте отпечаток.";
"本机配对信息" = "Данные этого устройства";
"查看指纹" = "Показать отпечаток";
"复制配对信息" = "Копировать данные";
"配对信息已复制。" = "Данные сопряжения скопированы.";
"无法复制配对信息,请重试。" = "Не удалось скопировать данные сопряжения. Повторите попытку.";
"安全存储不可用,请解锁设备后重试" = "Безопасное хранилище недоступно. Разблокируйте устройство и повторите попытку.";
@@ -288,3 +288,10 @@
"被控端分辨率" = "被控端分辨率";
"设备不支持" = "设备不支持";
"等待电脑端确认…" = "等待电脑端确认…";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "将配对信息添加到被控端的可信设备列表,并核对指纹。";
"本机配对信息" = "本机配对信息";
"查看指纹" = "查看指纹";
"复制配对信息" = "复制配对信息";
"配对信息已复制。" = "配对信息已复制。";
"无法复制配对信息,请重试。" = "无法复制配对信息,请重试。";
"安全存储不可用,请解锁设备后重试" = "安全存储不可用,请解锁设备后重试";
@@ -288,3 +288,10 @@
"被控端分辨率" = "被控端解析度";
"设备不支持" = "裝置不支援";
"等待电脑端确认…" = "等待電腦端確認…";
"将配对信息添加到被控端的可信设备列表,并核对指纹。" = "將配對資訊新增至被控端的可信裝置清單,並核對指紋。";
"本机配对信息" = "本機配對資訊";
"查看指纹" = "查看指紋";
"复制配对信息" = "複製配對資訊";
"配对信息已复制。" = "配對資訊已複製。";
"无法复制配对信息,请重试。" = "無法複製配對資訊,請重試。";
"安全存储不可用,请解锁设备后重试" = "安全儲存不可用,請解鎖裝置後重試";
@@ -0,0 +1,37 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-11-13
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _MOBILE_DEVICE_TRUST_H_
#define _MOBILE_DEVICE_TRUST_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
namespace crossdesk::mobile_controller {
// The platform must durably save the seed in its secure store before using it.
// Existing invalid/unavailable identities must never be replaced automatically.
class DeviceTrustIdentity {
public:
explicit DeviceTrustIdentity(std::string_view seed);
~DeviceTrustIdentity();
static std::string GeneratePrivateKey();
static void ClearSecret(std::string& value);
static std::string Advertise(std::string_view host_information);
static bool IsChallenge(std::string_view data) noexcept;
std::string PairingInfo(const std::string& device_id, const std::string& name) const;
const std::string& Fingerprint() const;
// nullopt: ordinary control message; empty: unsupported/malformed challenge.
std::optional<std::string> ChallengeResponse(std::string_view data,
const std::string& device_id, const std::string& name) const noexcept;
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace crossdesk::mobile_controller
#endif
+140
View File
@@ -0,0 +1,140 @@
#include "mobile_device_trust.h"
#include <nlohmann/json.hpp>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <algorithm>
#include <array>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
namespace crossdesk::mobile_controller {
// The platform must durably save the seed in its secure store before using it.
// A missing seed may be generated on first use; a malformed one must never be
// replaced automatically, since that would invalidate existing pairings.
class DeviceTrustIdentity::Impl {
public:
explicit Impl(std::string_view seed) {
Require(IsHex(seed, 32));
Secret bytes;
for (size_t i = 0; i < bytes.value.size(); ++i)
bytes.value[i] = (Digit(seed[2 * i]) << 4) | Digit(seed[2 * i + 1]);
key_.reset(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, nullptr,
bytes.value.data(), bytes.value.size()));
Require(bool(key_));
std::array<unsigned char, 32> public_key{};
size_t size = public_key.size();
Require(EVP_PKEY_get_raw_public_key(key_.get(), public_key.data(), &size) == 1 && size == 32);
public_key_ = Hex(public_key.data(), public_key.size());
std::array<unsigned char, SHA256_DIGEST_LENGTH> hash{};
Require(SHA256(public_key.data(), public_key.size(), hash.data()) != nullptr);
fingerprint_ = Hex(hash.data(), hash.size());
}
static std::string GeneratePrivateKey() {
Key key(EVP_PKEY_Q_keygen(nullptr, nullptr, "ED25519"), EVP_PKEY_free);
Require(bool(key));
Secret bytes;
size_t size = bytes.value.size();
Require(EVP_PKEY_get_raw_private_key(key.get(), bytes.value.data(), &size) == 1 && size == 32);
return Hex(bytes.value.data(), bytes.value.size());
}
std::string PairingInfo(const std::string& device_id, const std::string& name) const {
Require(Label(device_id) && Label(name));
return nlohmann::json{{"type", "crossdesk-pairing"}, {"version", 1},
{"public_key", public_key_}, {"device_id", device_id}, {"name", name}}.dump();
}
const std::string& Fingerprint() const { return fingerprint_; }
// nullopt: ordinary control message; empty: unsupported/malformed challenge.
// No peer-controlled parse or crypto exception may escape a data callback.
std::optional<std::string> ChallengeResponse(std::string_view data,
const std::string& device_id, const std::string& name) const noexcept {
if (data.empty() || data.size() > 2048) return std::nullopt;
try {
auto message = nlohmann::json::parse(data.begin(), data.end(), nullptr, false);
if (!message.is_object() || !message.contains("type") ||
message["type"] != "device_trust_challenge") return std::nullopt;
if (!message.at("version").is_number_integer() || message.at("version") != 1 ||
!message.at("nonce").is_string()) return std::string{};
const auto nonce = message.at("nonce").get<std::string>();
if (!IsHex(nonce, 32) || !Label(device_id) || !Label(name)) return std::string{};
const auto transcript = nlohmann::json::array({"crossdesk.device-trust.v1", nonce,
public_key_, device_id, name}).dump();
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> context(EVP_MD_CTX_new(), EVP_MD_CTX_free);
std::array<unsigned char, 64> signature{};
size_t size = signature.size();
Require(context && EVP_DigestSignInit(context.get(), nullptr, nullptr, nullptr, key_.get()) == 1 &&
EVP_DigestSign(context.get(), signature.data(), &size,
reinterpret_cast<const unsigned char*>(transcript.data()), transcript.size()) == 1 && size == 64);
return nlohmann::json{{"type", "device_trust_proof"}, {"version", 1}, {"nonce", nonce},
{"public_key", public_key_}, {"device_id", device_id}, {"name", name},
{"signature", Hex(signature.data(), signature.size())}}.dump();
} catch (const std::exception&) { return std::string{}; }
}
private:
using Key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>;
struct Secret {
std::array<unsigned char, 32> value{};
~Secret() { OPENSSL_cleanse(value.data(), value.size()); }
};
static void Require(bool ok) {
if (!ok) throw std::runtime_error("Device signing identity unavailable");
}
static int Digit(char c) { return c <= '9' ? c - '0' : c - 'a' + 10; }
static bool IsHex(std::string_view value, size_t bytes) {
return value.size() == bytes * 2 && std::all_of(value.begin(), value.end(),
[](char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); });
}
static std::string Hex(const unsigned char* bytes, size_t size) {
constexpr char digits[] = "0123456789abcdef";
std::string result;
result.reserve(size * 2);
for (size_t i = 0; i < size; ++i) {
result += digits[bytes[i] >> 4]; result += digits[bytes[i] & 15];
}
return result;
}
static bool Label(const std::string& value) {
return value.size() <= 128 && std::none_of(value.begin(), value.end(),
[](unsigned char c) { return c < 32 || c == 127; });
}
Key key_{nullptr, EVP_PKEY_free};
std::string public_key_, fingerprint_;
};
DeviceTrustIdentity::DeviceTrustIdentity(std::string_view seed) : impl_(std::make_unique<Impl>(seed)) {}
DeviceTrustIdentity::~DeviceTrustIdentity() = default;
std::string DeviceTrustIdentity::GeneratePrivateKey() { return Impl::GeneratePrivateKey(); }
std::string DeviceTrustIdentity::PairingInfo(const std::string& id, const std::string& name) const {
return impl_->PairingInfo(id, name);
}
const std::string& DeviceTrustIdentity::Fingerprint() const { return impl_->Fingerprint(); }
std::optional<std::string> DeviceTrustIdentity::ChallengeResponse(std::string_view data,
const std::string& id, const std::string& name) const noexcept {
return impl_->ChallengeResponse(data, id, name);
}
std::string DeviceTrustIdentity::Advertise(std::string_view host_information) {
auto info = nlohmann::json::parse(host_information.begin(), host_information.end());
info["device_trust_version"] = 1;
return info.dump();
}
void DeviceTrustIdentity::ClearSecret(std::string& value) {
OPENSSL_cleanse(value.data(), value.size());
value.clear();
}
bool DeviceTrustIdentity::IsChallenge(std::string_view data) noexcept {
if (data.empty() || data.size() > 2048) return false;
try {
const auto message = nlohmann::json::parse(data.begin(), data.end(), nullptr, false);
return message.is_object() && message.contains("type") && message["type"] == "device_trust_challenge";
} catch (const std::exception&) { return false; }
}
} // namespace crossdesk::mobile_controller
+35 -3
View File
@@ -11051,6 +11051,18 @@
"fr": "Résolution de l’écran distant",
"es": "Resolución de la pantalla remota",
"pt-BR": "Resolução da tela remota"
},
"将配对信息添加到被控端的可信设备列表,并核对指纹。": {
"zh-Hans": "将配对信息添加到被控端的可信设备列表,并核对指纹。",
"en": "Add this pairing information to the controlled device’s trusted list and verify the fingerprint.",
"ru": "Добавьте эти данные сопряжения в список доверенных устройств на управляемом компьютере и сверьте отпечаток.",
"zh-Hant": "將配對資訊新增至被控端的可信裝置清單,並核對指紋。",
"ja": "操作されるデバイスの信頼済みリストにこのペアリング情報を追加し、フィンガープリントを確認してください。",
"ko": "제어 대상 장치의 신뢰 목록에 이 페어링 정보를 추가하고 지문을 확인하세요.",
"de": "Fügen Sie diese Kopplungsdaten auf dem gesteuerten Gerät zur Vertrauensliste hinzu und prüfen Sie den Fingerabdruck.",
"fr": "Ajoutez ces informations à la liste des appareils de confiance de l’appareil contrôlé et vérifiez l’empreinte.",
"es": "Añada esta información de emparejamiento a la lista de confianza del dispositivo controlado y verifique la huella.",
"pt-BR": "Adicione estas informações de pareamento à lista de confiança do dispositivo controlado e confira a impressão digital."
}
},
"desktop": {
@@ -12413,7 +12425,14 @@
",点击重试",
"被控端分辨率",
"设备不支持",
"等待电脑端确认…"
"等待电脑端确认…",
"将配对信息添加到被控端的可信设备列表,并核对指纹。",
"本机配对信息",
"查看指纹",
"复制配对信息",
"配对信息已复制。",
"无法复制配对信息,请重试。",
"安全存储不可用,请解锁设备后重试"
],
"ios": [
"%1$@ 传输失败",
@@ -12704,7 +12723,14 @@
"新版本需要 iOS %1$@ 或更高版本",
"被控端分辨率",
"设备不支持",
"等待电脑端确认…"
"等待电脑端确认…",
"将配对信息添加到被控端的可信设备列表,并核对指纹。",
"本机配对信息",
"查看指纹",
"复制配对信息",
"配对信息已复制。",
"无法复制配对信息,请重试。",
"安全存储不可用,请解锁设备后重试"
],
"harmony": [
"OpenFEC 告知",
@@ -12948,7 +12974,13 @@
"鼠标左键,按住拖动",
"鼠标控制",
"被控端分辨率",
"设备不支持"
"设备不支持",
"将配对信息添加到被控端的可信设备列表,并核对指纹。",
"本机配对信息",
"查看指纹",
"复制配对信息",
"配对信息已复制。",
"无法复制配对信息,请重试。"
]
}
}