JSON Web Key ( JWK )

2019-12-29 JOSE

Una JSON Web Key ( JWK ) es una estructura JSON que representa una llave criptográfica. Los algoritmos de cifrado están definidos en una especificación diferente la cual no vamos a ver hoy, JWA (JSON Web Algorithms). Vamos a ver entonces de que se compone todo esto, y para no hacerlo tan técnico como la propia especificación (RFC 7518) , vamos a tratar de definir los conceptos en el camino.

Propiedades

Una llave JWK está compuesta por diferentes propiedades dentro de las cuáles algunas son comunes y otras son específicas para cada tipo de llave. Vamos a ver entonces de que se componen cada una de ellas.

kty (key type)

Este parámetro define la familia de algoritmos de crifrado usada en la llave. La lista de valores válidos está definida en la especificación RFC 7518 y es la siguiente:

kty key type Implementation
EC Elliptic Curve Recommended
RSA RSA [RFC3447] Required
oct Octet sequence Required

Los parámetros específicos para cada tipo están definidos en JWA, asi que no vamos a ahondar en ellos por ahora. El parámetro kty es obligatorio en este especificación.

use (public key use)

Este parámetro identifica el propósito de uso la llave pública. Este propósito puede ser el de encriptar información o verificar la firma en la información y define los siguientes valores para cada uso.

* sig (signature)
* enc (cifrado)

El parámetro use es opcional en esta especificación.

key_ops (key operations)

Este parámetro define las operaciones para las cuales se pretende usar la llave. Este parámetro debería ser un array en donde se adjunten cada una de las siguientes operaciones.

operation description
sign Calcular una firma digital o MAC
verify Verificar una firma digital o MAC
encrypt Encriptar contenido
decrypt Desencriptar contenido y validar el proceso, si aplica
wrapKey Encriptar una llave
unwrapKey Desencriptar una llave y validar el proceso, si aplica
deriveKey Derivar una llave
deriveBits Derivar bits que no se utilizarán como llave

El parámetro key_ops es opcional y no debe ser usado junto con el parámetro use, sin embargo, si los dos son utilizados la información que transmitan debe ser consistente.

alg (algorithm)

Este parámetro identifica el algoritmo destinado a utilizarse con la llave. Nuevamente los algorimos disponibles están definidos en la especificación JWA (RFC 7518). El parámetro alg es opcional.

kid (key id)

El parámetro kid se utiliza para hacer coincidir una llave específica. Cuando se utiliza dentro de un conjunto de llaves debe ser un parámetro único. Sin embargo, la excepción a la regla se presenta cuando una llave puede presentar distintos tipos (alternativas equivalentes a la misma llave), pudiendo así tener el mismo kid. Cuando se utilza con JWS o JWE sirve para hacer coincidir la llave con el mismo parámetro kid del Header. No hay un formato específico para el valor de este parámetro.

k5u (x.509 URL)

Este parámetro es la URI de un certificado de llave públic x.509 o cadena de certificados. Este parámetro debe estar codificado en formato PEM y debe estar delimitado como dice la sección 6.1 de la RFC 4945. El uso de este parámetro es opcional.

x5c (x.509 certificate chain)

Este parámetro contiene una cadena de uno o más certificados PKIX. Cada certificado debe estar codificado en base64 desde el formato DER del certificado y estar dispuesto en un array de strings JSON. Cada certificado debe estar seguido por otro que lo haya a su vez certificado.

Nótese que la llave en el primer certificado tanto del parámetro k5u como x5u debe coincidir con la llave pública representada por otros miembros del JWK. El uso de este parámetro es opcional.

x5t (X.509 certificate SHA-1 thumbprint)

Este parámetro es la codificación en BASE64URL SHA1 Thumbprint (digest) de un certificado x.509 en formato DER. La llave en el certificado debe coincidir también con la llave pública representada por otros miembros del JWK. El uso de este parámetro es opcional.

x5t#S256 (X.509 certificate SHA-256 thumbprint)

Este parámetro es la codificación en BASE64URL SHA256 Thumbprint (digest) de un certificado x.509 en formato DER. La llave en el certificado debe coincidir también con la llave pública representado por otros miembros dek JWK. El uso de este parámetro es opcional.

JWK Set

Un JWK Set no es más que un objeto JSON que representa un conjunto de llaves JWK. Cada llave JWK debe ser un elemento de un array que está definido en la propiedad keys.

Cálculo de valores para una JWK

Hasta aquí todo puede parecer muy claro, antes de realizar un ejemplo del cálculo de valores para una JWK vamos a ver las siguientes definiciones de función.

BASE64URL: Se refiere a una función que codifica un string en base64 usando un conjunto de caracteres seguros para envío por URL. Esto significa en pocas palabras, que después de codificado un string en base64, se debe omitir los caracteres =, y reemplazar / por _ y + por -.

UTF8: Representa un string de caracteres unicode de longitud variable definido como estándar en el RFC 3629.

El cálculo de valores para una llave JWK depende del tipo de llave. Por ejemplo, para una llave de tipo EC, se puede utilizar alguna librería en el lenguaje de programación respectivo para generar una llave privada de curva elípica para la curva P-256 y a los valores de X y Y aplicarles la función BASE64URL. Con lo cuál, la representación para la JWK sería similar a la siguiente:

{
    "kty":"EC",
    "crv":"P-256",
    "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
    "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
}

Los parámetros crv, x e y son específicos para este tipo de llave.

Por otro lado, un conjunto de llaves (JWK Set) en donde la primera sea una llave de tipo EC, y la segunda una RSA sería similar a la siguiente:

{
"keys": 
    [
        {
            "kty":"EC",
            "crv":"P-256",
            "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
            "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
            "use":"enc"
        },
        {
            "kty":"RSA",
            "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
            "e":"AQAB",
            "alg":"RS256"
        }
    ]
}

Acerca de Darío Rivera

Author

Ingeniero de desarrollo en PlacetoPay , Medellín. Darío ha trabajado por más de 6 años en lenguajes de programación web especialmente en PHP. Creador del microframework DronePHP basado en Zend y Laravel.

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.