Claves API asimétricas

  • Actualización

Las claves asimétricas implican el uso de dos claves: una clave privada y una clave pública, que son diferentes pero están vinculadas criptográficamente. La clave privada se usa para la generación de firmas, mientras que la clave pública se usa para la verificación de firmas. La clave de API la genera Deribit, pero el usuario genera el par de clave privada y clave pública. Deribit admite pares de claves Ed25519 o RSA. Deribit solo necesita usar la clave pública para la verificación de la firma, lo que permite que la clave privada

La principal ventaja del cifrado asimétrico radica en su modelo de seguridad mejorado, que separa las claves utilizadas para la generación de firmas y la verificación. Esta separación garantiza que, si bien los sistemas externos pueden autenticar las firmas para confirmar el origen y la integridad de los datos, son incapaces de generar firmas por sí mismos. Este atributo es crucial para mantener la seguridad y evitar el rechazo de los datos, ya que solo el titular de la clave privada puede originar las firmas

Además, el cifrado asimétrico proporciona una capa adicional de seguridad mediante la capacidad de agregar una contraseña a las claves privadas. Esto significa que, incluso si una entidad no autorizada accede de alguna manera a la clave privada, no se puede usar sin conocer también la contraseña

Tenga en cuenta que solo Autenticación de credenciales de Deribit Signature está disponible para claves API asimétricas.

Figura 2. Diagrama asimétrico de claves de API

Diagrama asimétrico de claves de API

¿Cómo configurar una clave API asimétrica?

  1. Crear el par de claves públicas y privadas

  2. Creación de una nueva clave de API en Deribit

  3. Autentica con una clave API asimétrica

Creación del par de claves públicas y privadas

Para crear un par de claves públicas y privadas, puede usar el script de Python que se proporciona más adelante o usar OpenSSL. OpenSSL es una biblioteca de software de código abierto que proporciona herramientas y bibliotecas para una comunicación segura e implementa los protocolos SSL y TLS para el cifrado, las funciones criptográficas

OpenSSL

Paso 1: Asegúrese de que OpenSSL esté instalado en su sistema operativo

Ventanas

Compruebe si OpenSSL está instalado:

  1. Abra la línea de comandos o PowerShell.

  2. Escriba el siguiente comando y pulse Entrar:openssl version

  3. Si OpenSSL está instalado, verá el número de versión. Si no es así, proceda a instalarlo

Instale OpenSSL:

  1. Descargue el instalador desde este enlace.

  2. Elija la versión adecuada para su sistema (Win32 o Win64).

  3. Ejecute el instalador y siga las instrucciones.

macOS

Compruebe si OpenSSL está instalado:

  1. Abra la terminal.

  2. Escriba el siguiente comando y pulse Entrar:openssl version

  3. Si OpenSSL está instalado, verá el número de versión. Si no es así, proceda a instalarlo

Instale OpenSSL:

  1. Usa Homebrew para instalar OpenSSL. Si no tiene instalado Homebrew su sitio web oficial.

  2. Una vez que Homebrew esté instalado, ejecuta:brew install openssl

  3. Es posible que tengas que añadir OpenSSL a tu PATH. Siga las instrucciones dadas por Homebrew después de la instalación para hacerlo

Linux

Compruebe si OpenSSL está instalado:

  1. Abra la terminal.

  2. Escriba el siguiente comando y pulse Entrar:openssl version

  3. Si OpenSSL está instalado, verá el número de versión. Si no es así, proceda a instalarlo

Instale OpenSSL:

Los comandos de instalación pueden variar según la distribución de Linux. Estos son los comandos de algunas distribuciones comunes

Debian/Ubuntu:

sudo apt update sudo apt install openssl

Fedora:

sudo dnf install openssl

Arch Linux:

sudo pacman -S openssl

Paso 2: Crear una clave ED25519 con OpenSSL

Ejecute el siguiente comando para generar una clave privada:

openssl genpkey -algorithm ed25519 -out private.pem

Paso 3: Calcular la clave pública (utilizada para el registro de la clave de API)

Ejecute el siguiente comando para generar la clave pública correspondiente:

openssl pkey -in private.pem -pubout -out public.pem

Secuencia de comandos Python

Asegúrese de tener instalada la criptografía: - pip install cryptography

Generador de claves Ed25519 público y privado

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization

private_key = Ed25519PrivateKey.generate()

private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

with open('private.pem', 'wb') as private_pem_file:
    private_pem_file.write(private_pem)


public_key = private_key.public_key()

public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

with open('public.pem', 'wb') as public_pem_file:
    public_pem_file.write(public_pem)

Generador de claves RSA públicas y privadas

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# Generate RSA private key
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048
)

# Serialize the private key to PEM format
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

# Write the private key to a file
with open('private.pem', 'wb') as private_pem_file:
    private_pem_file.write(private_pem)

# Get the corresponding public key
public_key = private_key.public_key()

# Serialize the public key to PEM format
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# Write the public key to a file
with open('public.pem', 'wb') as public_pem_file:
    public_pem_file.write(public_pem)

Creación de una nueva clave API asimétrica en Deribit

Puede crear una nueva clave de API de Deribit mediante la interfaz de usuario o mediante la API de Deribit. Si quieres utilizar la API, consulta Cómo crear la clave de API asimétrica mediante la

Interfaz frontal

asymmetric_keys_api_section.jpeg

Presiona 'Añadir nueva clave'en el lado derecho de la interfaz.

asymmetric_keys_new_key.jpeg

Seleccione Clave autogenerada y proporcione la clave pública generada anteriormente.

Importante

Pegue todo el contenido del archivo de clave pública, no solo el hash de base64. La clave pública debe incluir el encabezado -----BEGIN PUBLIC KEY-----, los datos de la clave codificada en base64 y el pie de página -----END PUBLIC KEY

asymmetric_keys_self_generated_key.jpeg

Declare los alcances y otros detalles de la clave de la API:

  • Ámbitos: Describe el acceso máximo para la autorización con una clave determinada. Por favor, diríjase documentación oficial para obtener más detalles.

  • Campo de nombre: Se trata de una entrada personalizada que puede introducir para utilizarla como identificador de la clave.

  • Campo de características: Funciones opcionales adicionales relacionadas con esta clave de API. Es posible que se amplíen en versiones futuras.

  • Lista blanca de IP: Como característica de seguridad adicional, este campo restringe las direcciones IP que pueden conectarse mediante esta IP.

asymmetric_key_scopes.jpeg

Una vez creado, recibirás ID de cliente

ID de cliente:El ID de cliente es un identificador público de la clave de API. No es un secreto. Puede quedar expuesto en los navegadores web, en el código fuente o en cualquier otro lugar sin problemas de seguridad inmediatos. Se usa principalmente para identificar la clave y no se usa por sí solo para la autenticación.

asymmetric_key.jpeg

Creación de la clave de API asimétrica mediante la API

Registro de claves mediante la clave pública mediante private/create_api_key:

Solicitud

{
  "method": "private/create_api_key",
  "params": {
    "public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/pQXmQa6m5NigEfu0UrbjDdzRORWYRluJasNiZau2Lo=\n-----END PUBLIC KEY-----",
    "name": "ed25519key",
    "max_scope": "account:read trade:read_write wallet:read"
  },
  "jsonrpc": "2.0",
  "id": 1
}

Respuesta

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "max_scope": "trade:read_write wallet:read account:read",
    "ip_whitelist": [],
    "client_secret": "81:c2:76:35:a7:1a:1c:f8:05:71:e1:42:7c:94:2c:4c",
    "client_id": "GgUXjYUj",
    "enabled_features": [],
    "public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/pQXmQa6m5NigEfu0UrbjDdzRORWYRluJasNiZau2Lo=\n-----END PUBLIC KEY-----",
    "timestamp": 1721816749587,
    "name": "ed25519key",
    "id": 11,
    "enabled": true,
    "default": false
  }
}

Autenticación con una clave API asimétrica

Solo Firma de Deribit: autenticación de credenciales está disponible para claves API asimétricas. Para autenticarse con una clave API asimétrica, la firma debe estar firmada con una clave privada. A continuación, se muestran ejemplos de cómo firmar la firma mediante comandos de shell y código Python

Ejemplo de Shell

base_url=

timestamp=$( date +%s000 )
nonce=$( cat /dev/urandom | tr -dc 'a-z0-9' | head -c8 )
verb=GET
uri='/api/v2/private/get_current_deposit_address?currency=eth'

datatosign=$(mktemp)
echo -ne "${timestamp}\n${nonce}\n${verb}\n${uri}\n\n" > ${datatosign}

# client_id received when creating the API key
client_id=xyz
signature=$(openssl pkeyutl -sign -inkey private.pem -rawin -in ${datatosign} | base64 -w 100 | sed 's#+#-#g;s#/#_#g;s#=##g')
rm ${datatosign}

curl -s -X ${verb} -H "Authorization: DERI-HMAC-SHA256 id=${client_id},ts=${timestamp},nonce=${nonce},sig=${signature}" "${base_url}${uri}" | jq

Secuencia de comandos Python

Autenticación Ed25519

import asyncio
from cryptography.hazmat.primitives import serialization
import websockets

import base64
import json
from datetime import datetime

# client_id received when creating the API key
client_id='xyz'

with open('private.pem', 'rb') as private_pem:
    private_key = serialization.load_pem_private_key(private_pem.read(), password=None)

timestamp = round(datetime.now().timestamp() * 1000)
nonce = "abcd"
data = ""

data_to_sign = bytes('{}\n{}\n{}'.format(timestamp, nonce, data), "latin-1")
signature = base64.urlsafe_b64encode(private_key.sign(data_to_sign)).decode('utf-8').rstrip('=')

msg = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "public/auth",
    "params": {
        "grant_type": "client_signature",
        "client_id": client_id,
        "timestamp": timestamp,
        "signature": signature,
        "nonce": nonce,
        "data": data
    }
}

async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            # do something with the response...
            print(response)
            await websocket.send(json.dumps({
                "jsonrpc": "2.0",
                "id": 2,
                "method": "private/get_positions",
                "params": {
                    "currency": "btc"
                }
            }))
            response = await websocket.recv()
            print(response)
            exit()

asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

Autenticación RSA

import asyncio
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
import websockets

import base64
import json
from datetime import datetime

# client_id received when creating the API key
client_id = 'xyz'

# Load the private key from the PEM file
with open('private.pem', 'rb') as private_pem:
    private_key = serialization.load_pem_private_key(private_pem.read(), password=None)

# Generate timestamp, nonce, and data to sign
timestamp = round(datetime.now().timestamp() * 1000)
nonce = "abcd"
data = ""

# Prepare the data to sign
data_to_sign = bytes('{}\n{}\n{}'.format(timestamp, nonce, data), "latin-1")

# Sign the data using the RSA private key with padding and hashing algorithm
signature = private_key.sign(
    data_to_sign,
    padding.PKCS1v15(),
    hashes.SHA256()
)

# Encode the signature to base64
encoded_signature = base64.urlsafe_b64encode(signature).decode('utf-8').rstrip('=')

# Prepare the message
msg = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "public/auth",
    "params": {
        "grant_type": "client_signature",
        "client_id": client_id,
        "timestamp": timestamp,
        "signature": encoded_signature,
        "nonce": nonce,
        "data": data
    }
}

# Function to call the API
async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            # do something with the response...
            print(response)
            await websocket.send(json.dumps({
                "jsonrpc": "2.0",
                "id": 2,
                "method": "private/get_positions",
                "params": {
                    "currency": "btc"
                }
            }))
            response = await websocket.recv()
            print(response)
            exit()

# Run the event loop to call the API
asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

Preguntas frecuentes

  • ¿Puedo usar varias teclas asimétricas?

    Sí, puede crear y administrar varias claves asimétricas para diferentes aplicaciones o sistemas.

  • ¿Qué debo hacer si mi clave privada está comprometida?

    Revoca inmediatamente la clave pública correspondiente de tu cuenta de Deribit y genera un nuevo par de claves.

  • ¿Siguen siendo necesarios los alcances y los permisos para las claves asimétricas?

    Sí, debes asignar datos específicos alcances (permisos) al crear una clave de API, al igual que con las credenciales de API estándar.