ChaCha20.NetCore 2.0.0

dotnet add package ChaCha20.NetCore --version 2.0.0
                    
NuGet\Install-Package ChaCha20.NetCore -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ChaCha20.NetCore" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ChaCha20.NetCore" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="ChaCha20.NetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ChaCha20.NetCore --version 2.0.0
                    
#r "nuget: ChaCha20.NetCore, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ChaCha20.NetCore@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ChaCha20.NetCore&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=ChaCha20.NetCore&version=2.0.0
                    
Install as a Cake Tool

ChaCha20.NetCore

License: MIT nuget

ChaCha20.NetCore is a .NET implementation of the ChaCha20 stream cipher.

The implementation is optimized for secure memory handling and integrates with PinnedMemory to support memory-sensitive workflows.

This package provides ChaCha20 encryption/decryption only. It does not include authentication (for example, Poly1305).


Table of contents


Requirements

  • .NET 8 SDK for building/testing this repository.
  • Target runtime/framework for the project: .NET 8.

The repository includes a global.json to pin the SDK family used for development.


Installation

NuGet Package Manager (CLI)

dotnet add package ChaCha20.NetCore

Package Manager Console

Install-Package ChaCha20.NetCore

Quick start

using System;
using System.Security.Cryptography;
using ChaCha20.NetCore;
using PinnedMemory;

var nonce = RandomNumberGenerator.GetBytes(12);   // RFC 8439 nonce size
var keyBytes = RandomNumberGenerator.GetBytes(32); // 256-bit key
var plaintext = new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 };

using var key = new PinnedMemory<byte>(keyBytes, false);
using var chacha20 = new ChaCha20(key, nonce); // default: 20 rounds

chacha20.UpdateBlock(plaintext, 0, plaintext.Length);

using var output = new PinnedMemory<byte>(new byte[chacha20.GetLength()]);
chacha20.DoFinal(output, 0);

var ciphertext = output.ToArray();

// ChaCha20 decrypts by applying the same keystream operation again
chacha20.Reset();
chacha20.UpdateBlock(ciphertext, 0, ciphertext.Length);

using var decrypted = new PinnedMemory<byte>(new byte[chacha20.GetLength()]);
chacha20.DoFinal(decrypted, 0);

API reference

ChaCha20

Constructor

ChaCha20(PinnedMemory<byte> key, byte[] nonce, int rounds = 20)
  • key must be 32 bytes (256-bit).
  • nonce must be 12 bytes (96-bit RFC 8439 nonce).
  • rounds must be positive and even (20 is standard ChaCha20).

Core members

int Rounds { get; }
int GetLength()
byte[] GetBuffer()
void Update(byte value)
void UpdateBlock(byte[] value, int offset, int length)
void UpdateBlock(PinnedMemory<byte> value, int offset, int length)
void DoFinal(byte[] output, int offset)
void DoFinal(PinnedMemory<byte> output, int offset)
void Reset()
void Dispose()

Behavior notes

  • GetLength() returns the current buffered input length in bytes.
  • DoFinal(...) writes encrypted/decrypted output for the currently buffered input.
  • Reset() clears buffered input and rewinds counter/index state to the initial position for the same key/nonce.
  • Dispose() clears internal state and pinned buffers.

Usage notes

1) Never reuse a nonce with the same key

ChaCha20 is a stream cipher. Reusing (key, nonce) across different plaintexts can reveal relationships between messages.

2) Add authentication separately

ChaCha20 alone does not provide tamper detection. For authenticated encryption, pair with Poly1305 (ChaCha20-Poly1305) or use an AEAD library.

3) Treat keys as sensitive material

  • Keep keys in pinned memory where practical.
  • Dispose cipher instances promptly (using blocks).
  • Avoid logging keys, nonces, or raw plaintext in production diagnostics.

4) Use explicit framing for protocols

If you split messages across frames/chunks, ensure both sender and receiver agree on:

  • nonce lifecycle
  • message boundaries
  • replay protections
  • encoding/canonicalization of higher-level payloads

Performance notes

  • The DoFinal(byte[] output, int offset) path uses a SIMD-accelerated XOR routine when hardware vector support is available at runtime (Vector.IsHardwareAccelerated).
  • SIMD use is automatic and transparent; no extra configuration is required.
  • A scalar fallback is always used when SIMD is unavailable or for any trailing bytes that do not fill a full vector width.
  • The DoFinal(PinnedMemory<byte> output, int offset) overload currently uses scalar writes.

Security notes

  • ChaCha20 in this package follows RFC 8439 parameter conventions:
    • 256-bit key (32 bytes)
    • 96-bit nonce (12 bytes)
    • 32-bit block counter
  • This implementation enforces the ChaCha20 per-nonce processing limit and will throw if exceeded.
  • Cryptographic integration should be reviewed against your protocol and threat model.

Validation and test vectors

The test project includes RFC 8439-focused verification, including keystream generation and roundtrip encryption/decryption behavior.

Run tests with:

dotnet test ChaCha20.NetCore.sln

Development

Build

dotnet build ChaCha20.NetCore.sln

Test

dotnet test ChaCha20.NetCore.sln

If dotnet is installed locally but not on PATH, invoke it explicitly:

$HOME/.dotnet/dotnet test ChaCha20.NetCore.sln

License

MIT. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ChaCha20.NetCore:

Package Downloads
AeadChaCha20Poly1305.NetCore

Implementation of AEAD_CHACHA20_POLY1305 authenticated encryption with additional data using ChaCha20 and Poly1305, optimized for PinnedMemory and .NET.

Poly1305ChaCha20.NetCore

Implementation of poly1305-dona message authentication code, designed by D. J. Bernstein with a chacha20 nonce. Optimized for PinnedMemory depends on ChaCha20.NetCore.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 126 2/24/2026
1.0.3 1,122 8/11/2020
1.0.2 677 8/11/2020
1.0.1 661 8/11/2020
1.0.0 849 7/26/2020