dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.15k stars 4.71k forks source link

[API Proposal]: AesGcm/AesCcm.KeyByteSizes, AesGcm/AesCcm.KeySize #72191

Open sdrapkin opened 2 years ago

sdrapkin commented 2 years ago

Background and motivation

System.Security.Cryptography:

Proposal-1: AesGcm and AesCcm currently expose .NonceByteSizes and .TagByteSizes. However they do not expose allowed .KeyByteSizes.

AesGcm and AesCcm currently each support 3 key sizes: 16, 24, and 32 bytes. This proposal is for a public static property exposing these supported key sizes. Note: an instance of Aes already provides .LegalKeySizes property.

Proposal-2: Add .KeySize public property to instances of AesGcm and AesCcm. The purpose is to validate the externally-provided instance of each of these classes for adherence to specific key-strength level (ex. API requires AesGcm instance with 256-bit key strength only). Note that instance of Aes already provides .KeySize property precisely for that purpose.

API Proposal

namespace System.Security.Cryptography;

public class AesGcm // and AesCcm
{
    public int KeySize { get; }
    public static KeySizes KeyByteSizes = new KeySizes(16, 32, 8);
}

API Usage

// don't use in production, but shows the new APIs
bool IsValidGcmKey(byte[] key)
{
    var allowedKeySizes = AesGcm.KeyByteSizes;
    var keyLength = key.Length;
    var min = allowedKeySizes.MinSize;
    var max = allowedKeySizes.MaxSize;
    var step = allowedKeySizes.SkipSize;
    for (var i = min; i <= max; i += step)
        if (keyLength == i) return true;
    return false;
}

void OnlyAesGcm256(AesGcm gcm)
{
    const int ALLOWED_KEY_SIZE = 256 / 8;
    if (gcm.KeySize != ALLOWED_KEY_SIZE) throw new CryptographicException();
    // do stuff
}

Alternative Designs

No response

Risks

New APIs. No breaking changes/risks. No performance regressions/impacts.

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation System.Security.Cryptography: **Proposal-1:** `AesGcm` and `AesCcm` currently expose [`.NonceByteSizes`](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aesgcm.noncebytesizes) and [`.TagByteSizes`](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aesgcm.tagbytesizes). However they do not expose allowed `.KeyByteSizes`. `AesGcm` and `AesCcm` currently each support 3 key sizes: 16, 24, and 32 bytes. This proposal is for a public static property exposing these supported key sizes. Note: an instance of `Aes` already provides `.LegalKeySizes` property. **Proposal-2:** Add `.KeySize` public property to instances of `AesGcm` and `AesCcm`. The purpose is to validate the externally-provided instance of each of these classes for adherence to specific key-strength level (ex. API requires `AesGcm` instance with 256-bit key strength only). Note that instance of `Aes` already provides `.KeySize` property precisely for that purpose. ### API Proposal ```csharp namespace System.Security.Cryptography; public class AesGcm // and AesCcm { public int KeySize { get; } public static KeySizes KeyByteSizes = new KeySizes(16, 32, 8); } ``` ### API Usage ```csharp // don't use in production, but shows the new APIs bool IsValidGcmKey(byte[] key) { var allowedKeySizes = AesGcm.KeyByteSizes; var keyLength = key.Length; var min = allowedKeySizes.MinSize; var max = allowedKeySizes.MaxSize; var step = allowedKeySizes.SkipSize; for (var i = min; i <= max; i += step) if (keyLength == i) return true; return false; } void OnlyAesGcm256(AesGcm gcm) { const int ALLOWED_KEY_SIZE = 256 / 8; if (gcm.KeySize != ALLOWED_KEY_SIZE) throw new CryptographicException(); // do stuff } ``` ### Alternative Designs _No response_ ### Risks New APIs. No breaking changes/risks. No performance regressions/impacts.
Author: sdrapkin
Assignees: -
Labels: `api-suggestion`, `area-System.Security`
Milestone: -
bartonjs commented 2 years ago

The reason for providing the NonceSizeBytes and TagSizeBytes is mainly to bring up that these have variability of implementation in the ecosystem at large; we've generally not found evidence that anyone actually ever reads them.

We intentionally don't allow retrieving the key itself from these new types, but adding an instance KeySize property seems reasonable to me.

sdrapkin commented 1 year ago

Can this be added to .NET 8?