Skip to content

API proposal: ChaCha20Poly1305 cryptographic algorithm #45130

@GrabYourPitchforks

Description

@GrabYourPitchforks

Background and Motivation

We've received requests to add more cryptographic primitives to the BCL. Among these requests is support for ChaCha20-Poly1305 (see #16010), an AEAD algorithm standardized in RFC 7539. This algorithm is beginning to see widespread use in networking protocols - notably, for TLS.

We're not considering shipping APIs for standalone ChaCha20 and Poly1305 primitives. This proposal is only for the combined ChaCha20Poly1305 AEAD construction.

Proposed API

Since this is an AEAD algorithm, the proposed API surface exactly mirrors the API surface of System.Security.Cryptography.AesGcm. We're not using the existing SymmetricAlgorithm class, as it's not well-suited for AEAD algorithms.

namespace System.Security.Cryptography
{
    [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
    public sealed partial class ChaCha20Poly1305 : System.IDisposable
    {
        public ChaCha20Poly1305(byte[] key) { }
        public ChaCha20Poly1305(System.ReadOnlySpan<byte> key) { }
        // public static System.Security.Cryptography.KeySizes NonceByteSizes { get { throw null; } } // (removed - see discussion)
        // public static System.Security.Cryptography.KeySizes TagByteSizes { get { throw null; } } // (removed - see discussion)
        public void Decrypt(byte[] nonce, byte[] ciphertext, byte[] tag, byte[] plaintext, byte[]? associatedData = null) { }
        public void Decrypt(System.ReadOnlySpan<byte> nonce, System.ReadOnlySpan<byte> ciphertext, System.ReadOnlySpan<byte> tag, System.Span<byte> plaintext, System.ReadOnlySpan<byte> associatedData = default(System.ReadOnlySpan<byte>)) { }
        public void Dispose() { }
        public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] tag, byte[]? associatedData = null) { }
        public void Encrypt(System.ReadOnlySpan<byte> nonce, System.ReadOnlySpan<byte> plaintext, System.Span<byte> ciphertext, System.Span<byte> tag, System.ReadOnlySpan<byte> associatedData = default(System.ReadOnlySpan<byte>)) { }
    }
}

The key, nonce, and tag lengths are fixed at 256, 96, and 128 bits, respectively. Callers are expected to know this information. We could consider getting rid of the NonceByteSizes and TagByteSizes properties here, which were copied over from the AesGcm approved API surface.

Implementation and usage notes

We are not shipping an implementation of this algorithm. We rely on the underlying OS or a third-party crypto library to provide the implementation on our behalf. The support matrix is then:

  • Windows 10: Build 20142 or later.
  • OpenSSL: Version 1.1 or later.
  • Mac OSX: Unsupported unless the OpenSSL shim is enabled, same as AES-GCM.
  • Browser: Unsupported.

Open questions

Do we need to attribute the type with "if on Windows, supported in 20142+ only"? I don't know how useful this would be, since normally some high-level orchestration layer or config dictates what algorithms to use, and the low-level code which would be using this proposed type would be far-removed from any orchestration code. That low-level code normally wouldn't be responsible for checking support, as any PNSE that's thrown would indicate a failure on the part of the orchestration layer, not the component that attempted to create a ChaCha20Poly1305 instance.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions