RSASSA-PSS без параметров, использующих поддержку SHA-256 .Net 4.5

Я пытаюсь использовать System.Security.Cryptography (целевой фреймворк.NET 4.5) для создания цифровых подписей в формате xml. До сих пор мне удавалось создавать и проверять подписи по следующей схеме: RSA PKCS#1 v1.5 и SHA-256: http://www.w3.org/2001/04/xmldsig-more

Однако я не могу использовать следующую схему: "RSASSA-PSS без параметров, использующих SHA-256" [RFC6931]: http://www.w3.org/2007/05/xmldsig-more

Отображаемая ошибка ясна: "SignatureDescription не может быть создано для предоставленного алгоритма подписи".

Для 'RSA PKCS#1 v1.5 и SHA-256' я добавил следующий открытый класс в качестве его подписи:

   public class RSAPKCS1SHA256SignatureDescription : SignatureDescription
   {
        public RSAPKCS1SHA256SignatureDescription()
        {
            base.KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
            base.DigestAlgorithm = "System.Security.Cryptography.SHA256Managed";
            base.FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
            base.DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
        }

        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
        {
            AsymmetricSignatureDeformatter asymmetricSignatureDeformatter = (AsymmetricSignatureDeformatter)
            CryptoConfig.CreateFromName(base.DeformatterAlgorithm);
            asymmetricSignatureDeformatter.SetKey(key);
            asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
            return asymmetricSignatureDeformatter;
        }
    }

Однако я понятия не имею, поддерживается ли в.Net 4.5 "RSASSA-PSS без параметров, использующих SHA-256", и если да, то как задать определение своей подписи.

Я был бы очень благодарен, если бы кто-то имел подобный опыт и мог бы оказать некоторую помощь.

1 ответ

Я наконец понял это. Хитрость заключается в том, чтобы зарегистрировать алгоритм, который указывает подпись XML, в моем случае " http://www.w3.org/2007/05/xmldsig-more". Зарегистрируйте его в пользовательском классе, который использует пользовательский форматер и деформататор подписи, которые применяются RSASignaturePadding.Pss,

Вот реализация, где все, что вам нужно сделать, это вызвать RsaSsaPss.RegisterSha256RsaMgf1() один раз, например, из статического конструктора в вашем клиенте. Затем, SignedXml.CheckSignature() а также SignedXml.ComputeSignature() автоматически работает для любой подписи XML, которая определяет этот алгоритм.

Протестировано на Core 2.1 и Framework 4.7.1:

/// <summary>
/// Contains classes for using RSA-SSA-PSS, as well as methods for registering them.
/// Registering such types adds support for them to SignedXml.
/// </summary>
public class RsaSsaPss
{
    /// <summary>
    /// Registers an implementation for "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1".
    /// </summary>
    public static void RegisterSha256RsaMgf1()
    {
        CryptoConfig.AddAlgorithm(typeof(RsaPssSha256SignatureDescription), "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1");
    }

    // Can add further registrations here...

    public class RsaPssSha256SignatureDescription : SignatureDescription
    {
        public RsaPssSha256SignatureDescription()
        {
            using (var rsa = RSA.Create())
            {
                this.KeyAlgorithm = rsa.GetType().AssemblyQualifiedName; // Does not like a simple algorithm name, but wants a type name (AssembyQualifiedName in Core)
            }
            this.DigestAlgorithm = "SHA256"; // Somehow wants a simple algorithm name
            this.FormatterAlgorithm = typeof(RsaPssSignatureFormatter).FullName;
            this.DeformatterAlgorithm = typeof(RsaPssSignatureDeformatter).FullName;
        }

        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
        {
            var signatureFormatter = new RsaPssSignatureFormatter();
            signatureFormatter.SetKey(key);
            signatureFormatter.SetHashAlgorithm(this.DigestAlgorithm);
            return signatureFormatter;
        }

        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
        {
            var signatureDeformatter = new RsaPssSignatureDeformatter();
            signatureDeformatter.SetKey(key);
            signatureDeformatter.SetHashAlgorithm(this.DigestAlgorithm);
            return signatureDeformatter;
        }

        public class RsaPssSignatureFormatter : AsymmetricSignatureFormatter
        {
            private RSA Key { get; set; }
            private string HashAlgorithmName { get; set; }

            public override void SetKey(AsymmetricAlgorithm key)
            {
                this.Key = (RSA)key;
            }

            public override void SetHashAlgorithm(string strName)
            {
                // Verify the name
                Oid.FromFriendlyName(strName, OidGroup.HashAlgorithm);

                this.HashAlgorithmName = strName;
            }

            public override byte[] CreateSignature(byte[] rgbHash)
            {
                return this.Key.SignHash(rgbHash, new HashAlgorithmName(this.HashAlgorithmName), RSASignaturePadding.Pss);
            }
        }

        public class RsaPssSignatureDeformatter : AsymmetricSignatureDeformatter
        {
            private RSA Key { get; set; }
            private string HashAlgorithmName { get; set; }

            public override void SetKey(AsymmetricAlgorithm key)
            {
                this.Key = (RSA)key;
            }

            public override void SetHashAlgorithm(string strName)
            {
                // Verify the name
                Oid.FromFriendlyName(strName, OidGroup.HashAlgorithm);

                this.HashAlgorithmName = strName;
            }

            public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature)
            {
                return this.Key.VerifyHash(rgbHash, rgbSignature, new HashAlgorithmName(this.HashAlgorithmName), RSASignaturePadding.Pss);
            }
        }
    }
}
Другие вопросы по тегам