private bool DoVerify()

in net/JetBrains.SignatureVerifier/src/Crypt/BC/SignerInformation.cs [330:552]


    private bool DoVerify(
      AsymmetricKeyParameter key)
    {
      string digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
      IDigest digest = Helper.GetDigestInstance(digestName);

      DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.Algorithm;
      Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters;
      ISigner sig;

      if (sigAlgOid.Equals(PkcsObjectIdentifiers.IdRsassaPss))
      {
        // RFC 4056 2.2
        // When the id-RSASSA-PSS algorithm identifier is used for a signature,
        // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
        if (sigParams == null)
          throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");

        try
        {
          // TODO Provide abstract configuration mechanism
          // (via alternate SignerUtilities.GetSigner method taking ASN.1 params)

          RsassaPssParameters pss = RsassaPssParameters.GetInstance(
            sigParams.ToAsn1Object());

          if (!pss.HashAlgorithm.Algorithm.Equals(this.digestAlgorithm.Algorithm))
            throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
          if (!pss.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1))
            throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");

          IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.Algorithm);
          int saltLength = pss.SaltLength.IntValueExact;

          // RFC 4055 3.1
          // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
          if (!RsassaPssParameters.DefaultTrailerField.Equals(pss.TrailerField))
            throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");

          IAsymmetricBlockCipher rsa = new RsaBlindedEngine();

          if (signedAttributeSet == null && digestCalculator != null)
          {
            sig = PssSigner.CreateRawSigner(rsa, pssDigest, pssDigest, saltLength, PssSigner.TrailerImplicit);
          }
          else
          {
            sig = new PssSigner(rsa, pssDigest, saltLength);
          }
        }
        catch (Exception e)
        {
          throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
        }
      }
      else
      {
        // TODO Probably too strong a check at the moment
//				if (sigParams != null)
//					throw new CmsException("unrecognised signature parameters provided");

        string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid);

        sig = Helper.GetSignatureInstance(signatureName);

        //sig = Helper.GetSignatureInstance(this.EncryptionAlgOid);
        //sig = SignerUtilities.GetSigner(sigAlgOid);
      }

      try
      {
        if (digestCalculator != null)
        {
          resultDigest = digestCalculator.GetDigest();
        }
        else
        {
          if (content != null)
          {
            content.Write(new DigestSink(digest));
          }
          else if (signedAttributeSet == null)
          {
            // TODO Get rid of this exception and just treat content==null as empty not missing?
            throw new CmsException("data not encapsulated in signature - use detached constructor.");
          }

          resultDigest = DigestUtilities.DoFinal(digest);
        }
      }
      catch (IOException e)
      {
        throw new CmsException("can't process mime object to create signature.", e);
      }

      // RFC 3852 11.1 Check the content-type attribute is correct
      {
        Asn1Object validContentType = GetSingleValuedSignedAttribute(
          CmsAttributes.ContentType, "content-type");
        if (validContentType == null)
        {
          if (!isCounterSignature && signedAttributeSet != null)
            throw new CmsException(
              "The content-type attribute type MUST be present whenever signed attributes are present in signed-data");
        }
        else
        {
          /*
                     * We do not care !
           * https://github.com/bcgit/bc-csharp/issues/312
                     */

          // if (isCounterSignature)
          // 	throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute");
          //
          // if (!(validContentType is DerObjectIdentifier))
          // 	throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'");
          //
          // DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType;
          //
          // if (!signedContentType.Equals(contentType))
          // 	throw new CmsException("content-type attribute value does not match eContentType");
        }
      }

      // RFC 3852 11.2 Check the message-digest attribute is correct
      {
        Asn1Object validMessageDigest = GetSingleValuedSignedAttribute(
          CmsAttributes.MessageDigest, "message-digest");
        if (validMessageDigest == null)
        {
          if (signedAttributeSet != null)
            throw new CmsException(
              "the message-digest signed attribute type MUST be present when there are any signed attributes present");
        }
        else
        {
          if (!(validMessageDigest is Asn1OctetString))
          {
            throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'");
          }

          Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest;

          if (!Arrays.AreEqual(resultDigest, signedMessageDigest.GetOctets()))
            throw new CmsException("message-digest attribute value does not match calculated value");
        }
      }

      // RFC 3852 11.4 Validate countersignature attribute(s)
      {
        AttributeTable signedAttrTable = this.SignedAttributes;
        if (signedAttrTable != null
            && signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0)
        {
          throw new CmsException("A countersignature attribute MUST NOT be a signed attribute");
        }

        AttributeTable unsignedAttrTable = this.UnsignedAttributes;
        if (unsignedAttrTable != null)
        {
          foreach (Attribute csAttr in unsignedAttrTable.GetAll(CmsAttributes.CounterSignature))
          {
            if (csAttr.AttrValues.Count < 1)
              throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue");

            // Note: We don't recursively validate the countersignature value
          }
        }
      }

      try
      {
        sig.Init(false, key);

        if (signedAttributeSet == null)
        {
          if (digestCalculator != null)
          {
            if (sig is PssSigner)
            {
              sig.BlockUpdate(resultDigest, 0, resultDigest.Length);
            }
            else
            {
              // need to decrypt signature and check message bytes
              return VerifyDigest(resultDigest, key, this.GetSignature());
            }
          }
          else if (content != null)
          {
            try
            {
              // TODO Use raw signature of the hash value instead
              content.Write(new SignerSink(sig));
            }
            catch (SignatureException e)
            {
              throw new CmsStreamException("signature problem: " + e);
            }
          }
        }
        else
        {
          byte[] tmp = this.GetEncodedSignedAttributes();
          sig.BlockUpdate(tmp, 0, tmp.Length);
        }

        return sig.VerifySignature(this.GetSignature());
      }
      catch (InvalidKeyException e)
      {
        throw new CmsException("key not appropriate to signature in message.", e);
      }
      catch (IOException e)
      {
        throw new CmsException("can't process mime object to create signature.", e);
      }
      catch (SignatureException e)
      {
        throw new CmsException("invalid signature format in message: " + e.Message, e);
      }
    }