예제 #1
0
        /// <inheritsdoc />
        public override bool TryUnwrapKey(ReadOnlySpan <byte> keyBytes, Span <byte> destination, JwtHeaderDocument header, out int bytesWritten)
        {
            if (!header.TryGetHeaderParameter(JwtHeaderParameterNames.IV.EncodedUtf8Bytes, out var encodedIV))
            {
                ThrowHelper.ThrowJwtDescriptorException_HeaderIsRequired(JwtHeaderParameterNames.IV);
            }

            if (!header.TryGetHeaderParameter(JwtHeaderParameterNames.Tag.EncodedUtf8Bytes, out var encodedTag))
            {
                ThrowHelper.ThrowJwtDescriptorException_HeaderIsRequired(JwtHeaderParameterNames.Tag);
            }

            var         rawIV  = encodedIV.GetRawValue();
            Span <byte> nonce  = stackalloc byte[Base64Url.GetArraySizeRequiredToDecode(rawIV.Length)];
            var         rawTag = encodedTag.GetRawValue();
            Span <byte> tag    = stackalloc byte[Base64Url.GetArraySizeRequiredToDecode(rawTag.Length)];

            try
            {
                Base64Url.Decode(rawIV.Span, nonce);
                Base64Url.Decode(rawTag.Span, tag);
                using var aesGcm = new AesGcm(_key.K);
                if (destination.Length > keyBytes.Length)
                {
                    destination = destination.Slice(0, keyBytes.Length);
                }

                aesGcm.Decrypt(nonce, keyBytes, tag, destination);
                bytesWritten = destination.Length;

                return(true);
            }
            catch (CryptographicException)
            {
                return(ThrowHelper.TryWriteError(out bytesWritten));
            }
        }
예제 #2
0
        private byte[] BuildSecretAppend(string?apuS, string?apvS)
        {
            byte[]? apuToReturn = null;
            byte[]? apvToReturn = null;
            byte[] secretAppend;
            try
            {
                int         apuLength = apuS == null ? 0 : Utf8.GetMaxByteCount(apuS.Length);
                Span <byte> apu       = apuLength <= Constants.MaxStackallocBytes
                                        ? stackalloc byte[apuLength]
                                        : (apuToReturn = ArrayPool <byte> .Shared.Rent(apuLength));
                if (apuS != null)
                {
                    apuLength = Utf8.GetBytes(apuS, apu);
                    apu       = apu.Slice(0, apuLength);
                }

                int         apvLength = apvS == null ? 0 : Utf8.GetMaxByteCount(apvS.Length);
                Span <byte> apv       = apvLength <= Constants.MaxStackallocBytes
                                        ? stackalloc byte[apvLength]
                                        : (apvToReturn = ArrayPool <byte> .Shared.Rent(apvLength));
                if (apvS != null)
                {
                    apvLength = Utf8.GetBytes(apvS, apv);
                    apv       = apv.Slice(0, apvLength);
                }

                apuLength = Base64Url.GetArraySizeRequiredToDecode(apuLength);
                apvLength = Base64Url.GetArraySizeRequiredToDecode(apvLength);

                int       algorithmLength   = sizeof(int) + _algorithmNameLength;
                int       partyUInfoLength  = sizeof(int) + apuLength;
                int       partyVInfoLength  = sizeof(int) + apvLength;
                const int suppPubInfoLength = sizeof(int);

                int secretAppendLength = algorithmLength + partyUInfoLength + partyVInfoLength + suppPubInfoLength;
                secretAppend = new byte[secretAppendLength];
                var secretAppendSpan = secretAppend.AsSpan();
                WriteAlgorithmId(secretAppendSpan);
                secretAppendSpan = secretAppendSpan.Slice(algorithmLength);
                WritePartyInfo(apu, apuLength, secretAppendSpan);
                secretAppendSpan = secretAppendSpan.Slice(partyUInfoLength);
                WritePartyInfo(apv, apvLength, secretAppendSpan);
                secretAppendSpan = secretAppendSpan.Slice(partyVInfoLength);
                BinaryPrimitives.WriteInt32BigEndian(secretAppendSpan, _keySizeInBytes << 3);
            }
            finally
            {
                if (apuToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(apuToReturn);
                }

                if (apvToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(apvToReturn);
                }
            }

            return(secretAppend);
        }