The Prehash and SignPrehash primitives split the computation of a digital
signature into two steps:

1. **Prehash** needs only the *public* key. It turns a message of arbitrary length into a short, fixed-size *prehash value*.
2. **SignPrehash** needs the *private* key. It turns a prehash value into a signature.

The signature that comes out is an ordinary signature over the original
message. You verify it with the regular
[Digital Signature](https://developers.google.com/tink/digital-signature) `PublicKeyVerify` primitive, and
verifiers don't need to know -- or care -- that the signature was produced in
two steps.

Treat the prehash value as opaque bytes. It has a fixed size and it carries the
ID of the key it was computed for, but its layout is part of Tink's wire format,
and you should not parse or construct one yourself. If you are porting Tink or
need the byte-level details, see
[Tink wire format](https://developers.google.com/tink/wire-format#prehash).

Use this pair of primitives when:

- **The signing key lives somewhere else**, for example in an HSM, in a KMS, or behind an RPC boundary, and you don't want to ship the full message across that boundary.
- **The message is large**, and the remote signer enforces a request size limit.

If neither of these applies, use the plain
[Digital Signature](https://developers.google.com/tink/digital-signature) primitive instead: it is simpler,
and it is harder to misuse.

### Keysets

The two primitives select keys differently, in the same way that signing and
verification do for the [Digital Signature](https://developers.google.com/tink/digital-signature) primitive:

- `Prehash.Compute` always uses the **primary key** of the public keyset, and records that key's ID in the prehash value. It is the side that *chooses* which key the signature will be made with.
- `SignPrehash.Sign` reads the key ID out of the prehash value and signs with the matching **enabled** key of the private keyset. It is the side that *follows* a choice someone else has already made. If no enabled key in the keyset has that ID, the call fails.

Every key in a SignPrehash keyset must have an ID requirement, otherwise
creating the primitive fails.

### Minimal security guarantees

- The resulting signature has the same properties as a signature produced by the [Digital Signature](https://developers.google.com/tink/digital-signature) primitive with the same key type.
- Tink prefixes the prehash value with 5 bytes containing a special reserved value and the ID of the key it was computed for. `SignPrehash` signs the value only with that key. Whether the value is *cryptographically* bound to that key depends on the algorithm; for External Mu ML-DSA it is, see [Tink wire format](https://developers.google.com/tink/wire-format#prehash).
- Messages can have arbitrary length.

### Things to watch out for

- **The signer cannot inspect what it signs.** Anyone who can call `SignPrehash` can get an arbitrary message signed, and the signer has no way to apply a policy to the message contents. Protect access to `SignPrehash` exactly as you would protect access to `PublicKeySign`.
- **Protect the prehash value in transit.** It is not secret, but an attacker who can modify it in flight controls what gets signed.

### Choose a key type

ML-DSA in *External Mu* mode, as described in
[RFC 9881](https://www.rfc-editor.org/rfc/rfc9881.html#externalmu), is the only
algorithm Tink supports for Prehash and SignPrehash. You should use a standard
ML-DSA key with these primitives.

We recommend **ML_DSA_44** for most use cases.

The key must have an ID requirement, because every prehash value starts with a
prefix that contains the ID of the key it was computed for. The following
variants are accepted:

- `TINK` -- the resulting signature starts with Tink's usual 5-byte output prefix.
- `NO_PREFIX_WITH_PREHASH_ID` -- the resulting signature carries no output prefix, while the key still has the ID that the prehash value needs.

Keys that use the `NO_PREFIX` (raw) variant are not supported, because they
have no key ID.

## Examples

The following examples sign a message in two steps and then verify the
resulting signature with the ordinary
[Digital Signature](https://developers.google.com/tink/digital-signature) primitive.

They are shown as one block for readability. In a real deployment the two steps
run in different places; see
[I want to sign data with a remote signer](https://developers.google.com/tink/sign-data-remotely) for a
step-by-step walkthrough.

### C++

```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

```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

```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)
```

## Related topics

- [I want to sign data with a remote signer](https://developers.google.com/tink/sign-data-remotely) -- a step-by-step walkthrough of the two-step flow.
- [Digital signature](https://developers.google.com/tink/digital-signature) -- sign and verify in a single step, when the signer can see the message.
- [Supported primitive key types by language](https://developers.google.com/tink/supported-key-types#signature)
- [Tink wire format](https://developers.google.com/tink/wire-format#prehash) -- the byte-level layout of a prehash value, for porting Tink to another language.