# Poly1305

## Purpose

[Poly1305](https://datatracker.ietf.org/doc/html/rfc8439#section-2.5) is a fast **one-time** message authentication code (MAC). It takes a 256-bit key **that can only be used once** and produces a 128-bit tag.

{% hint style="danger" %}
You almost definitely want [BLAKE2b](https://www.geralt.xyz/message-authentication) instead. **Poly1305 is easy to misuse and less secure due to the short tag length**.
{% endhint %}

## Usage

### ComputeTag

Fills a span with a tag computed from a message and a **one-time** key.

```csharp
Poly1305.ComputeTag(Span<byte> tag, ReadOnlySpan<byte> message, ReadOnlySpan<byte> oneTimeKey)
```

#### Exceptions

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`tag` has a length not equal to `TagSize`.

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`oneTimeKey` has a length not equal to `KeySize`.

[CryptographicException](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptographicexception)

The tag could not be computed.

### VerifyTag

Verifies that a tag is correct in constant time for a given message and **one-time** key. It returns `true` if the tag is valid and `false` otherwise.

```csharp
Poly1305.VerifyTag(ReadOnlySpan<byte> tag, ReadOnlySpan<byte> message, ReadOnlySpan<byte> oneTimeKey)
```

#### Exceptions

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`tag` has a length not equal to `TagSize`.

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`oneTimeKey` has a length not equal to `KeySize`.

### IncrementalPoly1305

Provides support for computing a tag from several messages and a **one-time** key.

```csharp
using var poly1305 = new IncrementalPoly1305(ReadOnlySpan<byte> oneTimeKey);
poly1305.Update(ReadOnlySpan<byte> message1);
poly1305.Update(ReadOnlySpan<byte> message2);
// Compute
poly1305.Finalize(Span<byte> tag);
// Or verify
bool valid = poly1305.FinalizeAndVerify(ReadOnlySpan<byte> tag);

// Avoid another using statement
// WARNING: Do NOT reuse the same key
poly1305.Reinitialize(ReadOnlySpan<byte> differentOneTimeKey);
poly1305.Update(ReadOnlySpan<byte> message3);
poly1305.Finalize(Span<byte> tag);
```

#### Exceptions

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`oneTimeKey` has a length not equal to `KeySize`.

[ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception)

`tag` has a length not equal to `TagSize`.

[CryptographicException](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptographicexception)

The tag could not be computed.

[InvalidOperationException](https://learn.microsoft.com/en-us/dotnet/api/system.invalidoperationexception)

Cannot update after finalizing or finalize twice (without reinitializing).

[ObjectDisposedException](https://learn.microsoft.com/en-us/dotnet/api/system.objectdisposedexception)

The object has been disposed.

## Constants

These are used for validation and/or save you defining your own constants.

```csharp
public const int KeySize = 32;
public const int TagSize = 16;
public const int BlockSize = 16;
```

## Notes

{% hint style="danger" %}
Each key **MUST** be uniformly random, unpredictable, and unique. You **MUST NOT** reuse a key or use the same key for multiple purposes (e.g., encryption and Poly1305).
{% endhint %}

{% hint style="danger" %}
Do **NOT** use Poly1305 as a hash function or key derivation function (KDF). Use [BLAKE2b](https://www.geralt.xyz/key-derivation).
{% endhint %}

{% hint style="danger" %}
Tags **MUST** be compared in constant time to avoid leaking information, so use the `VerifyTag()` or `FinalizeAndVerify()` function.​
{% endhint %}

{% hint style="danger" %}
Tags **MUST NOT** be truncated to minimise the opportunity for forgery.
{% endhint %}

{% hint style="warning" %}
[BLAKE2b](https://www.geralt.xyz/message-authentication) is **strongly recommended** over Poly1305 as a MAC because it has better security guarantees. Due to the 128-bit tag length, Poly1305 should only ever be used for online protocols and small messages.
{% endhint %}
