1.6.2: manifiesto firmado, tiempo estimado en tareas, pruebas automáticas
- firma.py: RSA-2048 PKCS#1 v1.5 SHA-256 sin dependencias; empaquetar.py firma el manifiesto y actualizador.py exige la firma (CLAVE_PUBLICA incrustada). - Barra de tareas: tiempo restante estimado a partir del avance. - Corregido: APLICANDO nunca llegaba al total y «Moviendo» quedaba fijo, bloqueando desconectar la carpeta. - probar.py: reglas, firma y recorrido completo sobre una copia temporal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Este commit está contenido en:
@@ -13,6 +13,7 @@ Lo que se exige del manifiesto para instalar (si no se cumple, no se instala y s
|
||||
- nombre de archivo simple (sin rutas) terminado en .zip
|
||||
- sha256 de 64 hex, obligatorio
|
||||
- URL de descarga con el mismo esquema y host que el manifiesto (nada de saltar a otro servidor)
|
||||
- firma RSA (firma.py) de versión+archivo+sha256+tamaño que cuadre con CLAVE_PUBLICA; sin ella no se instala
|
||||
|
||||
`O` es el módulo organizador (lo fija él al arrancar).
|
||||
"""
|
||||
@@ -28,6 +29,7 @@ import tempfile
|
||||
import threading
|
||||
import subprocess
|
||||
import urllib.error
|
||||
import firma
|
||||
import urllib.request
|
||||
from urllib.parse import urljoin, urlparse
|
||||
|
||||
@@ -55,6 +57,10 @@ def _tupla(v):
|
||||
return tuple(out + [0] * (3 - len(out)))
|
||||
|
||||
|
||||
# clave pública de firma.py (la privada está en ~/.labstream/organizador-firma.json, solo la usa empaquetar.py)
|
||||
CLAVE_PUBLICA = {"e": 65537, "n": 24937087096150856258549531047458881410156319770314378325709810834727102787144078753904837107336360100277476122470417827694103702029600632424402930901393600571590411504459673905624547394933513534401412673838815719634257887193733377640612491708305947101493071063533297310409777772800911393696346540036769491297235656643827279260544972034028016485933509783117840560074417501599224256143123720254264555615803987537224119534643367425486525306755766385726396897033934795259582227391903282650010470084464660818450797096588538639818043343189296266160938215570507865913766129394056803324311835125960516203968300455854004216307}
|
||||
|
||||
|
||||
def _validar(m, url_manifiesto):
|
||||
"""Devuelve (dict disponible, "") o (None, motivo). Solo acepta manifiestos bien formados."""
|
||||
app = m.get("app") or {}
|
||||
@@ -73,6 +79,9 @@ def _validar(m, url_manifiesto):
|
||||
return None, f"la descarga apunta a otro servidor ({b.netloc}); solo se acepta {a.netloc}"
|
||||
if a.scheme != "https" and not a.netloc.split(":")[0] in ("127.0.0.1", "localhost"):
|
||||
return None, "el manifiesto debe servirse por https"
|
||||
f = m.get("firma") or {}
|
||||
if not isinstance(f, dict) or not firma.verificar(firma.texto_manifiesto(m), str(f.get("valor") or ""), CLAVE_PUBLICA):
|
||||
return None, "el manifiesto no está firmado con la clave de Labstream (o se modificó); no se instala nada"
|
||||
return {"version": version, "notes": str(m.get("notes", ""))[:2000], "archivo": archivo,
|
||||
"size": int(app.get("size") or 0), "sha256": sha.lower(), "url": url}, ""
|
||||
|
||||
|
||||
Referencia en una nueva incidencia
Block a user