Lewati ke isi

Verifikasi tanda tangan entitlement

Respons /v1/activate dan /v1/validate menyertakan amplop entitlement dan entitlement_signature (Ed25519). Ini memungkinkan build produk memastikan respons tidak dipalsukan atau dimodifikasi oleh proxy/man-in-the-middle — tanpa harus memercayai transport.

Yang kamu butuhkan

  • Public key Ed25519 yang cocok, ditanam di rilis produkmu. Penerbit produk memberikannya (private key ada di sisi Berlanggan saja).
  • Kemampuan mereproduksi kanonikalisasi JSON yang persis sama.

Kanonikalisasi

Tanda tangan dibuat atas byte UTF-8 dari entitlement yang diserialisasi:

  • kunci diurutkan (sort_keys),
  • tanpa spasi,
  • pemisah hanya , dan :,
  • karakter non-ASCII tidak di-escape (ensure_ascii=false).

Setara dengan Python:

import json
canonical = json.dumps(
    entitlement, sort_keys=True, separators=(",", ":"), ensure_ascii=False
).encode("utf-8")

Verifikasi harus dilakukan atas hasil kanonikalisasi milikmu sendiri dari objek entitlement, bukan atas potongan mentah dari body HTTP.

Contoh verifikasi

import base64, json
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.exceptions import InvalidSignature

PUBLIC_KEY_B64 = "…"  # ditanam di build produk

def verify(entitlement: dict, signature_b64: str) -> bool:
    pub = Ed25519PublicKey.from_public_bytes(base64.b64decode(PUBLIC_KEY_B64))
    msg = json.dumps(entitlement, sort_keys=True,
                     separators=(",", ":"), ensure_ascii=False).encode("utf-8")
    try:
        pub.verify(base64.b64decode(signature_b64), msg)
        return True
    except InvalidSignature:
        return False
const nacl = require("tweetnacl");
// canon(): sort object keys recursively, JSON.stringify (default separators = no spaces)
function verify(entitlement, sigB64, pubB64) {
  const msg = Buffer.from(canon(entitlement), "utf8");
  return nacl.sign.detached.verify(
    msg, Buffer.from(sigB64, "base64"), Buffer.from(pubB64, "base64"));
}

Warning

Uji kesetaraan byte kanonikalisasi kamu dengan sisi Berlanggan sebelum rilis — perbedaan escaping/urutan akan membuat verifikasi selalu gagal.

Aturan kepercayaan

  • entitlement_signature kosong → server tidak dikonfigurasi untuk menandatangani (mode dev). Build produksi yang punya public key harus memperlakukan respons tak bertanda tangan sebagai tidak tepercaya, bukan sebagai "masih aktif".
  • Tanda tangan tidak cocok → jangan pakai entitlement dari respons itu; pertahankan state tepercaya terakhir dan jadwalkan retry.
  • Gunakan nilai dari entitlements untuk feature gating lokal, bukan hardcode tier di produk.