/// <inheritsdoc /> public override int GetKeyWrapSize() { Debug.Assert(Algorithm != null); Debug.Assert(Algorithm.WrappedAlgorithm != null); Debug.Assert(Algorithm.WrappedAlgorithm.Category == AlgorithmCategory.Aes); return(AesKeyWrapper.GetKeyWrappedSize(EncryptionAlgorithm)); }
/// <inheritsdoc /> public override SymmetricJwk WrapKey(Jwk?staticKey, JwtHeader header, Span <byte> destination) { if (header is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.header); } var contentEncryptionKey = CreateSymmetricKey(EncryptionAlgorithm, (SymmetricJwk?)staticKey); Span <byte> buffer = stackalloc byte[_saltSizeInBytes + 1 + _algorithmNameLength]; _saltGenerator.Generate(buffer.Slice(_algorithmNameLength + 1)); buffer[_algorithmNameLength] = 0x00; _algorithm.EncodedUtf8Bytes.CopyTo(buffer); Span <byte> derivedKey = stackalloc byte[_keySizeInBytes]; Pbkdf2.DeriveKey(_password, buffer, _hashAlgorithm, _iterationCount, derivedKey); Span <byte> salt = buffer.Slice(_algorithmNameLength + 1, _saltSizeInBytes); Span <byte> b64Salt = stackalloc byte[Base64Url.GetArraySizeRequiredToEncode(salt.Length)]; Base64Url.Encode(salt, b64Salt); header.Add(JwtHeaderParameterNames.P2s, Utf8.GetString(b64Salt)); header.Add(JwtHeaderParameterNames.P2c, _iterationCount); using var keyWrapper = new AesKeyWrapper(derivedKey, EncryptionAlgorithm, _keyManagementAlgorithm); return(keyWrapper.WrapKey(contentEncryptionKey, header, destination)); }
/// <inheritsdoc /> public override SymmetricJwk WrapKey(Jwk?staticKey, JwtHeader header, Span <byte> destination) { if (header is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.header); } var contentEncryptionKey = CreateSymmetricKey(EncryptionAlgorithm, (SymmetricJwk?)staticKey); int bufferSize = _saltSizeInBytes + _algorithmNameLength + 1; byte[]? bufferToReturn = null; Span <byte> buffer = bufferSize > Pbkdf2.SaltSizeThreshold + 18 + 1 // 18 = max alg name length ? (bufferToReturn = ArrayPool <byte> .Shared.Rent(bufferSize)) : stackalloc byte[Pbkdf2.SaltSizeThreshold + 18 + 1]; buffer = buffer.Slice(0, bufferSize); _saltGenerator.Generate(buffer.Slice(_algorithmNameLength + 1)); buffer[_algorithmNameLength] = 0x00; _algorithm.EncodedUtf8Bytes.CopyTo(buffer); Span <byte> derivedKey = stackalloc byte[KeySizeThreshold].Slice(0, _keySizeInBytes); Pbkdf2.DeriveKey(_password, buffer, _hashAlgorithm, _iterationCount, derivedKey); Span <byte> salt = buffer.Slice(_algorithmNameLength + 1, _saltSizeInBytes); int saltLengthB64 = Base64Url.GetArraySizeRequiredToEncode(salt.Length); byte[]? arrayToReturn = null; Span <byte> b64Salt = saltLengthB64 > Pbkdf2.SaltSizeThreshold * 4 / 3 ? (arrayToReturn = ArrayPool <byte> .Shared.Rent(saltLengthB64)) : stackalloc byte[Pbkdf2.SaltSizeThreshold * 4 / 3]; try { int length = Base64Url.Encode(salt, b64Salt); header.Add(JwtHeaderParameterNames.P2s, Utf8.GetString(b64Salt.Slice(0, saltLengthB64))); header.Add(JwtHeaderParameterNames.P2c, _iterationCount); using var keyWrapper = new AesKeyWrapper(derivedKey, EncryptionAlgorithm, _keyManagementAlgorithm); return(keyWrapper.WrapKey(contentEncryptionKey, header, destination)); } finally { if (bufferToReturn != null) { ArrayPool <byte> .Shared.Return(bufferToReturn); } if (arrayToReturn != null) { ArrayPool <byte> .Shared.Return(arrayToReturn); } } }
/// <inheritsdoc /> public override int GetKeyWrapSize() { int size; var alg = Algorithm; if (alg.ProduceEncryptionKey) { var wrappedAlgorithm = alg.WrappedAlgorithm; if (wrappedAlgorithm is null) { ThrowHelper.ThrowNotSupportedException_EncryptionAlgorithm(EncryptionAlgorithm); } size = wrappedAlgorithm.Category switch { AlgorithmCategory.Aes => AesKeyWrapper.GetKeyWrappedSize(EncryptionAlgorithm), #if SUPPORT_AES_GCM AlgorithmCategory.AesGcm => AesGcmKeyWrapper.GetKeyWrapSize(EncryptionAlgorithm), #endif _ => throw ThrowHelper.CreateNotSupportedException_EncryptionAlgorithm(EncryptionAlgorithm) }; } else { if (alg == KeyManagementAlgorithm.EcdhEs) { size = _keySizeInBytes; } else { #if SUPPORT_AES_GCM if (EncryptionAlgorithm.Category == EncryptionType.AesGcm) { size = _keySizeInBytes + 8; } #endif size = EncryptionAlgorithm.KeyWrappedSizeInBytes; } } return(size); }