@dotrino/identity 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/vault/capabilities.js +4 -6
- package/vault/core.js +14 -1
- package/vault/keyid.js +41 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotrino/identity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Identidad y rating de usuarios compartidos entre apps de Dotrino (vault iframe + postMessage)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -27,6 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"./content": {
|
|
29
29
|
"import": "./vault/content.js"
|
|
30
|
+
},
|
|
31
|
+
"./keyid": {
|
|
32
|
+
"import": "./vault/keyid.js"
|
|
30
33
|
}
|
|
31
34
|
},
|
|
32
35
|
"files": [
|
package/vault/capabilities.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* servidor de geo sin cargar el iframe.
|
|
22
22
|
*/
|
|
23
23
|
import { canonicalStringify, bufToBase64, base64ToBuf } from './core.js'
|
|
24
|
+
import { pubkeyId, keyLabel } from './keyid.js'
|
|
24
25
|
|
|
25
26
|
const ECDSA = { name: 'ECDSA', namedCurve: 'P-256' }
|
|
26
27
|
const SIGN = { name: 'ECDSA', hash: { name: 'SHA-256' } }
|
|
@@ -46,12 +47,9 @@ async function rawVerify (publicJwkStr, bytes, sigB64) {
|
|
|
46
47
|
const publicOf = (privateJwk) => ({ kty: privateJwk.kty, crv: privateJwk.crv, x: privateJwk.x, y: privateJwk.y })
|
|
47
48
|
const scopeAllows = (scope, expected) => Array.isArray(scope) ? scope.includes(expected) : scope === expected
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const h = await crypto.subtle.digest('SHA-256', enc(canonicalStringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y })))
|
|
53
|
-
return [...new Uint8Array(h)].map(b => b.toString(16).padStart(2, '0')).join('')
|
|
54
|
-
}
|
|
50
|
+
// El id de una llave y su huella legible viven en `./keyid.js`, que no tiene dependencias:
|
|
51
|
+
// así una interfaz puede mostrar `AB12-CD34` sin arrastrar todo esto. Una sola implementación.
|
|
52
|
+
export { pubkeyId, keyLabel }
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
55
|
* Verifica que `signature` (base64) sobre `data` fue hecha por la privada de
|
package/vault/core.js
CHANGED
|
@@ -1005,8 +1005,21 @@ export async function createIdentityCore ({ kv: rawKv, peers, makeSync = null, k
|
|
|
1005
1005
|
// ----- perfiles (multi-perfil por dispositivo) -----
|
|
1006
1006
|
// Cambiar/crear setea el perfil activo; la app RECARGA la página y re-inicializa con él
|
|
1007
1007
|
// (no reactivo, por diseño). Las apps abiertas conservan el perfil con el que cargaron.
|
|
1008
|
+
/**
|
|
1009
|
+
* Los perfiles de este dispositivo, para el conmutador. Incluye el AVATAR de cada uno:
|
|
1010
|
+
* sin él, la lista caía siempre al identicon automático y tu foto no aparecía —aunque la
|
|
1011
|
+
* hubieras subido— porque el avatar vive en el `me` de cada perfil, no en el registro.
|
|
1012
|
+
*/
|
|
1008
1013
|
async listProfiles () {
|
|
1009
|
-
return loadProfiles().map((p) =>
|
|
1014
|
+
return loadProfiles().map((p) => {
|
|
1015
|
+
let avatar = null
|
|
1016
|
+
try {
|
|
1017
|
+
const raw = p.id === currentPid ? JSON.stringify(me || null) : rawKv.getItem(`dotrino.identity.p.${p.id}.me`)
|
|
1018
|
+
const m = raw ? JSON.parse(raw) : null
|
|
1019
|
+
if (m && typeof m.avatar === 'string') avatar = m.avatar
|
|
1020
|
+
} catch (_) {}
|
|
1021
|
+
return { id: p.id, name: p.name || '', pubkey: p.pubkey || null, avatar, current: p.id === currentPid }
|
|
1022
|
+
})
|
|
1010
1023
|
},
|
|
1011
1024
|
async currentProfile () {
|
|
1012
1025
|
const e = loadProfiles().find((p) => p.id === currentPid) || {}
|
package/vault/keyid.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* keyid.js — el identificador LEGIBLE de una llave.
|
|
3
|
+
*
|
|
4
|
+
* Una pubkey es un JWK: `{"crv":"P-256","kty":"EC","x":"…","y":"…"}`. Eso no se le enseña a
|
|
5
|
+
* nadie — ni entero ni recortado, que es peor: parece un error. Para que una persona pueda
|
|
6
|
+
* reconocer y comparar una llave se usa su huella corta, `AB12-CD34`, que es la misma que
|
|
7
|
+
* ya se muestra al emparejar («aprueba el dispositivo AB12-CD34») y en el acta del perfil.
|
|
8
|
+
*
|
|
9
|
+
* Módulo aparte y sin dependencias a propósito: cualquier interfaz que necesite mostrar una
|
|
10
|
+
* llave puede importarlo sin arrastrar el resto de la identidad. `capabilities.js` reexporta
|
|
11
|
+
* `pubkeyId` desde aquí para que haya UNA sola implementación.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const enc = (s) => new TextEncoder().encode(s)
|
|
15
|
+
|
|
16
|
+
/** Serialización canónica de los campos que identifican la llave (mismo orden siempre). */
|
|
17
|
+
function canonicalJwk (jwk) {
|
|
18
|
+
return JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y })
|
|
19
|
+
.replace(/^{/, '{').replace(/}$/, '}')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** id corto y estable de un pubkey (sha-256 hex de los campos canónicos del JWK). */
|
|
23
|
+
export async function pubkeyId (publicJwkStr) {
|
|
24
|
+
const jwk = typeof publicJwkStr === 'string' ? JSON.parse(publicJwkStr) : publicJwkStr
|
|
25
|
+
const h = await crypto.subtle.digest('SHA-256', enc(canonicalJwk(jwk)))
|
|
26
|
+
return [...new Uint8Array(h)].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* La huella que SÍ se le enseña a una persona: `AB12-CD34`. Corta, comparable de un vistazo
|
|
31
|
+
* y la misma en todo el ecosistema (emparejamiento, acta, lista de dispositivos).
|
|
32
|
+
*/
|
|
33
|
+
export async function keyLabel (publicJwkStr) {
|
|
34
|
+
if (!publicJwkStr) return ''
|
|
35
|
+
try {
|
|
36
|
+
const id = (await pubkeyId(publicJwkStr)).slice(0, 8).toUpperCase()
|
|
37
|
+
return id.slice(0, 4) + '-' + id.slice(4, 8)
|
|
38
|
+
} catch (_) { return '' }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default { pubkeyId, keyLabel }
|