Skip to content

Persisted-key AesCng in CFB mode always uses CFB8 #55477

@vcsjones

Description

@vcsjones

Description

When using AesCng with the CipherMode in CFB mode with a persisted CNG key, it appears that CFB8 is always used for the actual feedback size, even if FeedbackSize is set to 128.

Steps to reproduce:

Run the following snippet (with package reference to System.Security.Cryptography.Cng):

using System;
using System.Security.Cryptography;

// Create the key
CngAlgorithm aesAlgorithm = new CngAlgorithm("AES");
CngKeyCreationParameters opts =  new CngKeyCreationParameters
{
    ExportPolicy = CngExportPolicies.AllowPlaintextExport,
};

try
{
    CngKey key = CngKey.Create(aesAlgorithm, "potato-key", opts);
    key.Dispose();
}
catch (CryptographicException ce) when ((uint)ce.HResult == 0x8009000F)
{
    // Don't worry about the key already existing.
}

static byte[] Encrypt(Aes aes, int feebackSizeBits)
{
    aes.FeedbackSize = feebackSizeBits;
    aes.Mode = CipherMode.CFB;
    aes.Padding = PaddingMode.PKCS7;
    aes.IV = new byte[aes.BlockSize / 8];

    var input = new byte[] { 1, 2, 3, 4, 5 };
    using ICryptoTransform transform = aes.CreateEncryptor();
    byte[] result = transform.TransformFinalBlock(input, 0, input.Length);
    return result;
}

AesCng cng = new AesCng("potato-key");
Aes aes = Aes.Create();
aes.Key = cng.Key;

byte[] cng8Result = Encrypt(cng, 8);
byte[] aes8Result = Encrypt(aes, 8);

Console.WriteLine("CNG  8: " + Convert.ToHexString(cng8Result));
Console.WriteLine("AES  8: " + Convert.ToHexString(aes8Result));


byte[] cng128Result = Encrypt(cng, 128);
byte[] aes128Result = Encrypt(aes, 128);

Console.WriteLine("CNG128: " + Convert.ToHexString(cng128Result));
Console.WriteLine("AES128: " + Convert.ToHexString(aes128Result));

It will produce an output that looks something like this. The output will be different from this one since the code generates a key, but this illustrates the pattern.

CNG  8: 3CF1DB609559
AES  8: 3CF1DB609559
CNG128: 3CF1DB6095538DD2611E7FBC7531083C
AES128: 3CD079280665EE399880253D9B40D035

AesCng and Aes.Create() agree for CFB8. However for CFB128, the results do not agree. The CNG128 line differs from the AES128 line. In this case, the CNG128 line's first 5 bytes match the result of CNG8, indicating CFB8 was actually used for the encryption, however it was padded as if CFB128 were used.

Configuration

Occurs in .NET 5 and main on all versions of Windows.

Other information

I suspect this is also the same for TripleDESCng with CFB64.

Metadata

Metadata

Assignees

Labels

area-System.Securitybreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions