CertificateHostAlgorithm
Implements certificate support for host algorithm.
            
                using Renci.SshNet.Security.Cryptography;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Renci.SshNet.Security
{
    [NullableContext(1)]
    [Nullable(0)]
    public class CertificateHostAlgorithm : KeyHostAlgorithm
    {
        [Nullable(new byte[] {
            2,
            1,
            1,
            1,
            1
        })]
        private readonly IReadOnlyDictionary<string, Func<byte[], KeyHostAlgorithm>> _keyAlgorithms;
        public Certificate Certificate { get; }
        internal override SshKeyData KeyData => Certificate.KeyData;
        public override byte[] Data => Certificate.Bytes;
        public CertificateHostAlgorithm(string name, Key privateKey, Certificate certificate)
            : base(name, privateKey)
        {
            Certificate = certificate;
        }
        public CertificateHostAlgorithm(string name, Key privateKey, Certificate certificate, DigitalSignature digitalSignature)
            : base(name, privateKey, digitalSignature)
        {
            Certificate = certificate;
        }
        public CertificateHostAlgorithm(string name, Certificate certificate, IReadOnlyDictionary<string, Func<byte[], KeyHostAlgorithm>> keyAlgorithms)
            : base(name, certificate.Key)
        {
            Certificate = certificate;
            _keyAlgorithms = keyAlgorithms;
        }
        public CertificateHostAlgorithm(string name, Certificate certificate, DigitalSignature digitalSignature, IReadOnlyDictionary<string, Func<byte[], KeyHostAlgorithm>> keyAlgorithms)
            : base(name, certificate.Key, digitalSignature)
        {
            Certificate = certificate;
            _keyAlgorithms = keyAlgorithms;
        }
        public override byte[] Sign(byte[] data)
        {
            return new SignatureKeyData(base.Name.EndsWith("-cert-v01@openssh.com", StringComparison.Ordinal) ? base.Name.Substring(0, base.Name.Length - 21) : base.Name, base.DigitalSignature.Sign(data)).GetBytes();
        }
        internal override bool VerifySignatureBlob(byte[] data, byte[] signatureBlob)
        {
            if (!base.VerifySignatureBlob(data, signatureBlob))
                return false;
            ulong num = (ulong)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            if (num < Certificate.ValidAfterUnixSeconds || num > Certificate.ValidBeforeUnixSeconds)
                return false;
            SignatureKeyData signatureKeyData = new SignatureKeyData();
            signatureKeyData.Load(Certificate.Signature);
            if (_keyAlgorithms == null)
                throw new InvalidOperationException("Invalid usage of CertificateHostAlgorithm.VerifySignature. Use a constructor which passes key algorithms.");
            if (_keyAlgorithms.TryGetValue(signatureKeyData.AlgorithmName, out Func<byte[], KeyHostAlgorithm> value))
                return value(Certificate.CertificateAuthorityKey).VerifySignatureBlob(Certificate.BytesForSignature, signatureKeyData.Signature);
            return false;
        }
    }
}