Prehash ve SignPrehash

Prehash ve SignPrehash temel işlevleri, dijital imza hesaplamasını iki adıma böler:

  1. Prehash için yalnızca ortak anahtar gerekir. İstediğiniz uzunluktaki bir mesajı kısa ve sabit boyutlu bir ön karma değerine dönüştürür.
  2. SignPrehash için özel anahtar gerekir. Önceden karma oluşturulmuş bir değeri imzaya dönüştürür.

Ortaya çıkan imza, orijinal mesajın üzerindeki normal bir imzadır. Bu imzayı normal dijital imza PublicKeyVerify öğesiyle doğruladığınızda doğrulayıcıların, imzanın iki adımda oluşturulduğunu bilmesi veya bununla ilgilenmesi gerekmez.

Ön karma değerini opak baytlar olarak değerlendirin. Sabit bir boyuta sahiptir ve hesaplandığı anahtarın kimliğini taşır ancak düzeni Tink'in kablo biçiminin bir parçasıdır ve kendiniz ayrıştırmamalı veya oluşturmamalısınız. Tink'i taşıyorsanız veya bayt düzeyindeki ayrıntılara ihtiyacınız varsa Tink'in kablo biçimi bölümüne bakın.

Bu temel öğe çiftini şu durumlarda kullanın:

  • İmzalama anahtarı başka bir yerde bulunuyorsa (ör. HSM, KMS veya RPC sınırı içinde) ve tam mesajı bu sınırın ötesine göndermek istemiyorsanız.
  • İleti büyük ve uzaktan imzalayan, istek boyutu sınırı uyguluyor.

Bu durumlardan hiçbiri geçerli değilse bunun yerine basit Digital Signature (Dijital İmza) öğesini kullanın. Bu öğe daha basittir ve kötüye kullanılması daha zordur.

Anahtar kümeleri

İki temel, anahtarları farklı şekilde seçer. Bu, imzalama ve doğrulamanın dijital imza temelinde yaptığıyla aynıdır:

  • Prehash.Compute, her zaman ortak anahtar kümesinin birincil anahtarını kullanır ve bu anahtarın kimliğini karma öncesi değerine kaydeder. İmzanın hangi anahtarla oluşturulacağını seçen taraftır.
  • SignPrehash.Sign, anahtar kimliğini ön karma değerinden okur ve özel anahtar kümesinin eşleşen etkin anahtarıyla imzalar. Bu taraf, başka birinin daha önce yaptığı bir seçimi takip eder. Anahtar setinde bu kimliğe sahip etkin bir anahtar yoksa arama başarısız olur.

SignPrehash anahtar grubundaki her anahtarın bir kimlik koşulu olmalıdır. Aksi takdirde, temel öğe oluşturma işlemi başarısız olur.

Minimum güvenlik garantileri

  • Elde edilen imza, aynı anahtar türüyle Dijital İmza temel öğesi tarafından oluşturulan imza ile aynı özelliklere sahiptir.
  • Tink, ön karma değerine özel ayrılmış bir değer ve hesaplandığı anahtarın kimliğini içeren 5 baytlık bir ön ek ekler. SignPrehash değeri yalnızca bu anahtarla imzalar. Değerin bu anahtara kriptografik olarak bağlı olup olmadığı algoritmaya bağlıdır. Harici Mu ML-DSA için bu durum geçerlidir. Tink tel biçimine bakın.
  • Mesajlar herhangi bir uzunlukta olabilir.

Dikkat etmeniz gerekenler

  • İmzalayan kişi, imzaladığı şeyi inceleyemez. SignPrehash kullanıcısına telefon edebilen herkes rastgele bir mesajı imzalayabilir ve imzalayan, mesaj içeriklerine politika uygulayamaz. SignPrehash hizmetine erişimi, PublicKeySign hizmetine erişimi koruduğunuz şekilde koruyun.
  • Karma oluşturma işleminden önceki değeri geçiş sırasında koruyun. Gizli olmasa da saldırgan, uçuş sırasında değiştirebildiği için neyin imzalanacağını kontrol eder.

Anahtar türü seçin

External Mu modunda ML-DSA, RFC 9881'de açıklandığı gibi, Tink'in Prehash ve SignPrehash için desteklediği tek algoritmadır. Bu temel işlevlerle standart bir ML-DSA anahtarı kullanmanız gerekir.

Çoğu kullanım alanı için ML_DSA_44'ü öneririz.

Her karma oluşturma öncesi değer, hesaplandığı anahtarın kimliğini içeren bir önekle başladığı için anahtarın kimlik şartı olmalıdır. Aşağıdaki varyantlar kabul edilir:

  • TINK: Ortaya çıkan imza, Tink'in normal 5 baytlık çıkış ön ekiyle başlar.
  • NO_PREFIX_WITH_PREHASH_ID: Sonuçta elde edilen imza, çıkış öneki içermez. Anahtar ise karma oluşturma öncesi değerin ihtiyaç duyduğu kimliğe sahiptir.

NO_PREFIX (ham) varyantını kullanan anahtarlar, anahtar kimliği içermediğinden desteklenmez.

Örnekler

Aşağıdaki örneklerde, bir ileti iki adımda imzalanır ve sonuçtaki imza, normal dijital imza öğesiyle doğrulanır.

Okunabilirlik için tek bir blok olarak gösterilir. Gerçek bir dağıtımda iki adım farklı yerlerde çalışır. Adım adım açıklama için Verileri uzaktan imzalayan bir kişiyle imzalamak istiyorum başlıklı makaleye bakın.

C++

#include "tink/keyset_handle.h"
#include "tink/public_key_verify.h"
#include "tink/signature/config_2026.h"
#include "tink/signature/prehash.h"
#include "tink/signature/sign_prehash.h"

using ::crypto::tink::ConfigSignature2026;
using ::crypto::tink::Prehash;
using ::crypto::tink::PublicKeyVerify;
using ::crypto::tink::SignPrehash;

// 1. Wherever the message is: compute the prehash value. This needs only
//    the public keyset.
absl::StatusOr<std::unique_ptr<Prehash>> prehasher =
    public_handle.GetPrimitive<Prehash>(ConfigSignature2026());
if (!prehasher.ok()) return prehasher.status();

absl::StatusOr<std::string> prehash = (*prehasher)->Compute(message);
if (!prehash.ok()) return prehash.status();

// 2. Wherever the private key is: turn the prehash value into a signature.
absl::StatusOr<std::unique_ptr<SignPrehash>> signer =
    private_handle.GetPrimitive<SignPrehash>(ConfigSignature2026());
if (!signer.ok()) return signer.status();

absl::StatusOr<std::string> signature = (*signer)->Sign(*prehash);
if (!signature.ok()) return signature.status();

// 3. Anywhere: verify the signature over the original message.
absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
    public_handle.GetPrimitive<PublicKeyVerify>(ConfigSignature2026());
if (!verifier.ok()) return verifier.status();

absl::Status verified = (*verifier)->Verify(*signature, message);

Go

import (
    "github.com/tink-crypto/tink-go/v2/signature"
    "github.com/tink-crypto/tink-go/v2/signprehash"
)

// 1. Wherever the message is: compute the prehash value. This needs only
//    the public keyset.
prehasher, err := signprehash.NewPrehash(publicHandle)
if err != nil {
    return err
}
prehash, err := prehasher.ComputePrehash(message)
if err != nil {
    return err
}

// 2. Wherever the private key is: turn the prehash value into a signature.
signer, err := signprehash.NewPrehashSigner(privateHandle)
if err != nil {
    return err
}
sig, err := signer.SignPrehash(prehash)
if err != nil {
    return err
}

// 3. Anywhere: verify the signature over the original message.
verifier, err := signature.NewVerifier(publicHandle)
if err != nil {
    return err
}
if err := verifier.Verify(sig, message); err != nil {
    return err
}

Python

from tink import signature

# Needed for PublicKeyVerify in step 3. Due to the internal structure of
# Tink Python, Prehash and SignPrehash are an exception where calling
# signature.register() is not necessary; do not expect the same for other
# primitives.
signature.register()

# 1. Wherever the message is: compute the prehash value. This needs only
#    the public keyset.
prehasher = public_handle.primitive(signature.Prehash)
prehash = prehasher.compute(message)

# 2. Wherever the private key is: turn the prehash value into a signature.
signer = private_handle.primitive(signature.SignPrehash)
sig = signer.sign(prehash)

# 3. Anywhere: verify the signature over the original message.
verifier = public_handle.primitive(signature.PublicKeyVerify)
verifier.verify(sig, message)