Her WebSocket Mesajını İmzalayın

TLS, kanalın hat üzerinde kurcalanmadığını kanıtlar. Bir mesajı kimin ürettiğini kanıtlamaz ve mesaj günlüğe kaydedildikten, kalıcı hale getirildikten veya yeniden oynatıldıktan sonra varlığını sürdürmez. Bu eğitim, sgcWebSockets ve sgcSign'i birleştirir, böylece sunucunuzun yaydığı her çerçeve — veya istemcinizin gönderdiği her çerçeve — karşı tarafın bilinen bir imzalayıcı sertifikasına göre doğruladığı ayrık bir CAdES imzası taşır.

Kimliğe bağlı mesajlar
Çerçeve başına ayrık CAdES
Yeniden oynatma ve günlüklemeyi atlatır

TLS yeterli değil

TLS, iki uç nokta arasında aktarımdaki baytları korur. Bir çerçeve günlüğe kaydedildiğinde, arşivlendiğinde veya ara yazılım aracılığıyla yeniden oynatıldığında, TLS kanıtı kaybolur — yalnızca yükün kendisindeki bir dijital imza varlığını sürdürür.

Mesaj başına inkar edilemezlik

Borsa salonları, bahis borsaları, IoT komut kanalları ve klinik veri akışlarının tümü, mesaj başına kurcalamaya karşı korumalı bir denetim izine ihtiyaç duyar. Her çerçevedeki ayrık bir CAdES imzası, alıcının saatler veya yıllar sonra tam olarak kimin neyi ve ne zaman yaydığını kanıtlamasına olanak tanır.

Karşılıklı kimlik

WebSocket mTLS, bağlanma sırasında istemci kimliğini kanıtlar. Mesaj başına imzalama, çerçeve başına uygulama kimliğini kanıtlar — WebSocket ağ geçidi paylaşılan bir uç proxy olduğunda ve gerçek üretici alt akışta olduğunda yararlıdır.

Yeniden oynatmaya karşı güvenli

İmzalı yükün içine WebSocket oturum kimliğini ve monoton olarak artan bir nonce ekleyin. Yeniden oynatma saldırganı, özel anahtara erişim olmadan mesajı yeni bir nonce ile yeniden imzalayamaz.

Zarf yapısı

Her WebSocket mesajını; yükü, bir nonce'ı, bir zaman damgasını ve base64 kodlu ayrık imzayı taşıyan küçük bir JSON zarfına sarın.

Zarf sözleşmesi

Zarf, belirleyici bir bayt dizisi üzerinden imzalanır: session_id || nonce || timestamp || payload_sha256. Yük ikili olabileceği (Protobuf, MessagePack) ve imzalayıcıya sabit uzunlukta bir giriş istediğimiz için SHA-256 kullanıyoruz.

CAdES burada doğru seçimdir — yükün yanında rahatça sığacak kadar küçük base64 kodlanan kompakt CMS/PKCS#7 imzaları üretir. PAdES PDF'ye özgü ve XAdES XML'e özgüdür; hiçbiri ikili-veya-JSON gerçek zamanlı bir kanala uymaz.

envelope.json
{
  "sid": "7f3a-b6e1",
  "nonce": 42,
  "ts": "2026-05-26T11:24:09Z",
  "payload": { /* the actual app message */ },
  "sig": "MIIK...base64...detached CAdES..."
}

Birimleri ekleyin ve imzalama anahtarını yükleyin

sgcWebSockets taşımayı sağlar, sgcSign imza motorunu sağlar. Hiçbir durumu paylaşmazlar — bunları uygulama kodunuzda bağlarsınız.

Uses cümlesi

Hem istemci hem de sunucu için WebSocket bileşenlerine, CAdES profiline, bir anahtar sağlayıcıya ve doğrulayıcıya ihtiyacınız vardır. İstemci tarafı için bir PFX ve sunucu tarafı için uzun ömürlü bir hizmet sertifikası (genellikle Windows deposundan) kullanın.

uses-clauses.pas
uses
  Classes, SysUtils,
  // sgcWebSockets
  sgcWebSocket, sgcWebSocket_Classes,
  // sgcSign
  sgcSign_KeyProvider_PFX,
  sgcSign_CAdES,
  sgcSign_Profile_CAdES,
  sgcSign_Verifier,
  sgcJSON;

İstemci tarafı — göndermeden önce imzalayın

İstemcinin giden akışına bağlanın, yük ile oturum meta verilerinin özetini hesaplayın, CAdES imzasını ekleyin ve zarfı WriteData aracılığıyla yayın.

Yükü sarın

İmzalayıcıyı ve anahtar sağlayıcıyı formunuzdaki veya veri modülünüzdeki alanlar olarak tutun. TsgcSignCAdES.SignDetached bir bayt arabelleği kabul eder ve ayrık CMS yapısını döndürür. Belirleyici bayt dizisini BuildToBeSigned'da oluştururuz — oturum kimliği, nonce, ISO 8601 zaman damgası ve yük baytlarının SHA-256'sı.

TsgcWebSocketClient üzerinde WriteData çağırmak, zarfı normal bir metin çerçevesi olarak gönderir. Sunucu tarafı doğrulayıcı, yükü uygulama işleyicisine iletmeden önce bu işlemi tersine çevirir.

client-send.pas
procedure TForm1.SendSignedMessage(const aPayload: string);
var
  vTBS: TBytes;
  vSig: TBytes;
  vEnvelope: ISuperObject;
begin
  Inc(FNonce);
  vTBS := BuildToBeSigned(FSessionId, FNonce, NowUTC, aPayload);

  vSig := FCAdESSigner.SignDetached(vTBS);  // CMS SignedData, bytes

  vEnvelope := SO();
  vEnvelope.S['sid']     := FSessionId;
  vEnvelope.I['nonce']   := FNonce;
  vEnvelope.S['ts']      := DateToISO8601(NowUTC, True);
  vEnvelope.S['payload'] := aPayload;
  vEnvelope.S['sig']     := TNetEncoding.Base64.EncodeBytesToString(vSig);

  WSClient.WriteData(vEnvelope.AsJSon);
end;

Sunucu tarafı — göndermeden önce doğrulayın

Sunucunun OnMessage olayına bağlanın, zarf alanlarından imzalanacak baytları yeniden hesaplayın, ayrık imzayı doğrulayın ve ancak o zaman yükü iş mantığınıza iletin.

OnMessage işleyicisi

İşleyici, zarfı ayrıştırır, belirleyici bayt dizisini yeniden oluşturur ve imza baytları ile imzalanacak baytlarla TsgcSignatureVerifier.VerifyDetached çağırır. Doğrulayıcı; imzalayan konusu, zincir durumu ve herhangi bir zaman damgası meta verisiyle bir rapor döndürür.

Güvenilir imzalayıcı sertifikalarını sunucu içinde parmak iziyle önbelleğe alın — her çerçevede tam zincir doğrulaması, yüksek verimli bağlantılarda pahalı hale gelir. İlk doğrulamadan sonra yalnızca imzanın geçerli olduğunu ve parmak izinin zaten güvendiğiniz biri olduğunu onaylamanız gerekir.

server-receive.pas
procedure TFormSrv.WSServerMessage(Connection: TsgcWSConnection;
  const Text: string);
var
  vEnv: ISuperObject;
  vSig, vTBS: TBytes;
  vReport: TsgcSignatureReport;
begin
  vEnv := SO(Text);
  vSig := TNetEncoding.Base64.DecodeStringToBytes(vEnv.S['sig']);
  vTBS := BuildToBeSigned(
    vEnv.S['sid'], vEnv.I['nonce'],
    ISO8601ToDate(vEnv.S['ts'], True),
    vEnv.S['payload']);

  vReport := FVerifier.VerifyDetached(vSig, vTBS);
  if vReport.Signatures[0].Status <> svValid then
  begin
    Connection.Disconnect;
    Exit;
  end;

  HandlePayload(Connection, vEnv.S['payload']);
end;

Yeniden oynatma koruması

Geçerli bir imza yeterli değildir — imzalı bir zarfı yakalayan bir saldırgan, sertifika hâlâ geçerli olduğu sürece onu yeniden oynatabilir. Her mesajı oturuma bağlayın ve monoton nonce'lar uygulayın.

Bağlantı başına nonce penceresi

Şimdiye kadar görülen en yüksek nonce ile (SessionId, SignerThumbprint) tarafından anahtarlanan sunucu tarafı bir sözlük tutun. Nonce'ı kesinlikle daha büyük olmayan herhangi bir zarfı reddedin. Zaman damgası sunucu saatinden birkaç saniyeden fazla uzak olan herhangi bir zarfı reddedin — aynı nonce bir şekilde yeniden kullanılsa bile yeniden oynatma penceresini sınırlandırın.

Sıralamanın garanti edilmediği kayıplı ağlar için, kesin büyüktür kontrolünü bir kayan pencereye geçirin: son N girişteki daha önce görülmemiş herhangi bir nonce'ı kabul edin, daha eski olanı reddedin. Temel gereksinim, hiçbir iki çerçevenin aynı (SessionId, Nonce)'ı taşımamasıdır.

replay.pas
function TFormSrv.AcceptNonce(const aSid: string;
  aNonce: Int64): Boolean;
var
  vLast: Int64;
begin
  FNonceLock.Acquire;
  try
    vLast := FNonces.Items[aSid];
    Result := aNonce > vLast;
    if Result then
      FNonces.AddOrSetValue(aSid, aNonce);
  finally
    FNonceLock.Release;
  end;
end;

Genellikle ne ters gider

Geliştiriciler sgcSign'i ilk kez sgcWebSockets'e bağladığında en sık gördüğümüz üç başarısızlık modu.

Tutarsız kanonikleştirme

İstemci imzalanacak baytları ekleme sırası anahtarlarına sahip bir JSON dizesinden oluşturur ve sunucu bunları ayrıştırılmış ve yeniden serileştirilmiş bir nesneden yeniden oluşturursa, özetler eşleşmez. Her zaman kendiniz oluşturduğunuz belirleyici bir bayt dizisini imzalayın — yeniden serileştirilmiş JSON'u imzalamayın.

Yüksek verimli akışlarda gecikme

Her mesajı bir RSA-2048 anahtarıyla imzalamak, çerçeve başına birkaç milisaniye ekler. 10 bin msj/sn akışlarında bu bir darboğaza dönüşür. ECDSA-P256 anahtarlarına (bir kat daha hızlı) geçin veya N mesajı tek bir zarfta gruplayarak toplu olarak imzalayın.

SubjectKeyIdentifier'ı unutmak

CAdES varsayılan olarak imzalayıcı sertifikasını içerir, bu da her çerçeveyi 1-2 KB şişirir. Bir oturumdaki ilk çerçeveden sonra vProfile.IncludeCertificate := False kullanın ve doğrulayıcının güvenilir imzalayıcı önbelleğine karşı SubjectKeyIdentifier ile eşleştirmesine izin verin.

Buradan nereye gidilir

Uçtan uca şifreleme, imzalamayı tamamlar. sgcSign Server, istemci filoları için anahtar saklamayı merkezileştirir.

10 Anahtar Sağlayıcı

Özel anahtarları uygulama sürecinin tamamen dışında tutmak için Azure Trusted Signing, AWS KMS, Google KMS veya HashiCorp Vault kullanın.

Devamını okuyun →

sgcSign Server

İstemcilerin özel anahtarı asla görmemesi için REST imzalama hizmeti. WebSocket üreticisi yalıtılmış bir çalışan olduğunda yararlıdır.

Devamını okuyun →

sgcWebSockets

Bu eğitimde kullanılan tam WebSocket / HTTP2 / HTTP3 / MQTT / AMQP taşıma kitaplığı.

Devamını okuyun →

Her WebSocket çerçevesini imzalamaya hazır mısınız?

Her iki kitaplık da aynı denemede gelir. Bir kez indirin, uçtan uca imzalı kanalı bir öğleden sonra oluşturun.