Repository: dotnet/aspnetcore
File: src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs (C#)

Code before:
            fixed (byte* pExistingTemplate = existingTemplate)
            {
                if (ReadGuid(&pExistingTemplate[sizeof(uint)]) == keyId)
                {
                    return existingTemplate;
                }
            }

            // Clone since we're about to make modifications.
            // If this is an encryption operation, we only ever encrypt to the default key,
            // so we should replace the existing template. This could occur after the protector
            // has already been created, such as when the underlying key ring has been modified.
            byte[] newTemplate = (byte[])existingTemplate.Clone();
            fixed (byte* pNewTemplate = newTemplate)
            {
                WriteGuid(&pNewTemplate[sizeof(uint)], keyId);
                if (isProtecting)
                {
                    Volatile.Write(ref _aadTemplate, newTemplate);
                }
                return newTemplate;
            }
        }

#if NET10_0_OR_GREATER
        public AdditionalAuthenticatedDataTemplate(string[] purposes)
        {
            // additionalAuthenticatedData := { magicHeader (32-bit) || keyId || purposeCount (32-bit) || (purpose)* }
            // purpose := { utf8ByteCount (7-bit encoded) || utf8Text }

            var keySize = sizeof(Guid);
            int totalPurposeLen = 4 + keySize + 4;

            var purposeLengthsPool = ArrayPool<int>.Shared.Rent(purposes.Length);
            for (int i = 0; i < purposes.Length; i++)
            {
                string purpose = purposes[i];

                int purposeLength = EncodingUtil.SecureUtf8Encoding.GetByteCount(purpose);
                purposeLengthsPool[i] = purposeLength;

                var encoded7BitUIntLength = Measure7BitEncodedUIntLength((uint)purposeLength);
                totalPurposeLen += purposeLength /* length of actual string */ + encoded7BitUIntLength /* length of 'string length' 7-bit encoded int */;
            }

            byte[] targetArr = new byte[totalPurposeLen];
            var targetSpan = targetArr.AsSpan();

            // index 0: magic header
            BinaryPrimitives.WriteUInt32BigEndian(targetSpan.Slice(0), MAGIC_HEADER_V0);
            // index 4: key (skipped for now, will be populated in `GetAadForKey()`)

Review comment (suggestion):
Because we're replacing an existing implementation, I'd like to see at least one known payload correctness test, i.e.

- run the *old* code on something like an array of 5 strings, ideally with at least one of those strings being more than 127 utf8 bytes, and ideally containing some exotic unicode characters
- capture the return value from that, and get the base-64 (Convert.ToBase64String) or hex (BitConverter.ToString), so we can include it in a test trivially
- add a test that runs the new code for that some input, and compares the base-64 or hex output for equality

Code after:
            // simultaneously. We need to make sure all accesses to it are thread-safe.
            var existingTemplate = Volatile.Read(ref _aadTemplate);
            Debug.Assert(existingTemplate.Length >= sizeof(uint) /* MAGIC_HEADER */ + sizeof(Guid) /* keyId */);

            // If the template is already initialized to this key id, return it.
            // The caller will not mutate it.
            fixed (byte* pExistingTemplate = existingTemplate)
            {
                if (ReadGuid(&pExistingTemplate[sizeof(uint)]) == keyId)
                {
                    return existingTemplate;
                }
            }

            // Clone since we're about to make modifications.
            // If this is an encryption operation, we only ever encrypt to the default key,
            // so we should replace the existing template. This could occur after the protector
            // has already been created, such as when the underlying key ring has been modified.
            byte[] newTemplate = (byte[])existingTemplate.Clone();
            fixed (byte* pNewTemplate = newTemplate)
            {
                WriteGuid(&pNewTemplate[sizeof(uint)], keyId);
                if (isProtecting)
                {
                    Volatile.Write(ref _aadTemplate, newTemplate);
                }
                return newTemplate;
            }
        }

        internal static byte[] BuildAadTemplateBytes(string[] purposes)
        {
            // additionalAuthenticatedData := { magicHeader (32-bit) || keyId || purposeCount (32-bit) || (purpose)* }
            // purpose := { utf8ByteCount (7-bit encoded) || utf8Text }

            var keySize = sizeof(Guid);
            int totalPurposeLen = 4 + keySize + 4;

            int[]? lease = null;
            var targetLength = purposes.Length;
            Span<int> purposeLengthsPool = targetLength <= 32 ? stackalloc int[targetLength] : (lease = ArrayPool<int>.Shared.Rent(targetLength)).AsSpan(0, targetLength);
            for (int i = 0; i < targetLength; i++)
            {
                string purpose = purposes[i];

                int purposeLength = EncodingUtil.SecureUtf8Encoding.GetByteCount(purpose);
                purposeLengthsPool[i] = purposeLength;

                var encoded7BitUIntLength = purposeLength.Measure7BitEncodedUIntLength();
                totalPurposeLen += purposeLength /* length of actual string */ + encoded7BitUIntLength /* length of 'string length' 7-bit encoded int */;
            }