繁体   English   中英

访问Web服务的数字签名验证错误

[英]Digital signature verification error for accessing webservice

我需要将数字签名作为参数之一发送到外部Web服务。

根据文档创建的步骤是:

  1. 创建XML数据的DOM表示
  2. 创建DOM数据的规范化表示。 规范化的表示应遵循http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments中所述的格式;
  3. 创建规范化表示形式的SHA1摘要的签名RSA加密。 签名使用参与者的私钥加密;
  4. 将二进制签名编码为base64编码的字符串
  5. 将签名字符串放置在SOAP消息ReqDigSig元素中;
  6. 存储XML数据,以便以后支持已提交的XML数据的不可否认性。

我使用了以下代码:

private string SignXML(X509Certificate2 Cert, string data)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = false;
        xmlDoc.LoadXml(data);

        XmlDsigC14NWithCommentsTransform t = new XmlDsigC14NWithCommentsTransform();
        t.LoadInput(xmlDoc);
        Stream s = (Stream)t.GetOutput(typeof(Stream));

        SHA1 sha1 = SHA1.Create();
        byte[] hash = sha1.ComputeHash(s);


        RSACryptoServiceProvider rsaKey =
        (RSACryptoServiceProvider)Cert.PrivateKey;
        RSAParameters rsaPrivateParams = rsaKey.ExportParameters(true);
        rsaKey.ImportParameters(rsaPrivateParams);
        byte[] signature =  rsaKey.Encrypt(hash, false);

        return Convert.ToBase64String(signature);
    }

但是,Web服务的响应显示数字签名验证错误。

上面的代码是否按照文档中的说明进行? 我如何验证数字签名是否有效? 有在线工具吗?

[帖子编辑如下]我尝试使用以下内容。 我已经验证了签名,并且它返回true。 但是从Web服务端失败。 signData,signHash和rsaPKCsignatureformatter类的createSignature方法之间有什么区别?

        var document = Encoding.UTF8.GetBytes(Reqdata);

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = false;
        xmlDoc.LoadXml(Reqdata);

        //trial with XmlDsigC14NWithCommentsTransform class
        XmlDsigC14NWithCommentsTransform t = new XmlDsigC14NWithCommentsTransform();
        t.LoadInput(xmlDoc);
        Stream s = (Stream)t.GetOutput(typeof(Stream));

        //trial with SignedXML class
        SignedXml signedXml = new SignedXml(xmlDoc);
        signedXml.SignedInfo.CanonicalizationMethod =
        SignedXml.XmlDsigC14NWithCommentsTransformUrl;
        document = Encoding.UTF8.GetBytes(signedXml.ToString());

        byte[] hashedDocument;

        using (var sha1 = SHA1.Create())
        {
            //hashedDocument = sha1.ComputeHash(document);
            hashedDocument = sha1.ComputeHash(s);
        }

        var digitalSignature = new DigitalSignature();
        digitalSignature.AssignNewKey();

        byte[] signature = digitalSignature.SignData(hashedDocument);
        string finalsignature = Convert.ToBase64String(signature) ;
        byte[] finalSignveri = Convert.FromBase64String(finalsignature);
        bool verified = digitalSignature.VerifySignature(hashedDocument, finalSignveri);

数字签名类如下:

public class DigitalSignature
{
    private RSAParameters publicKey;
    private RSAParameters privateKey;

    public void AssignNewKey()
    {
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.PersistKeyInCsp = false;
            publicKey = rsa.ExportParameters(false);
            privateKey = rsa.ExportParameters(true);
        }
    }

    public byte[] SignData(byte[] hashOfDataToSign)
    {
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.PersistKeyInCsp = false;
            rsa.ImportParameters(privateKey);

            var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
            rsaFormatter.SetHashAlgorithm("SHA1");

            return rsaFormatter.CreateSignature(hashOfDataToSign);
        }
    }

    public bool VerifySignature(byte[] hashOfDataToSign, byte[] signature)
    {
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(publicKey);

            var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
            rsaDeformatter.SetHashAlgorithm("SHA1");

            return rsaDeformatter.VerifySignature(hashOfDataToSign, signature);
        }
    }   
}

您能否让我知道您正在wsdl中专门寻找哪些数据? 抱歉,我无法在此处提供完整的wsdl信息。

返回的错误是我认为用户已处理并指出“数字签名验证错误”

[编辑]

请在下面找到在Java中生成数字签名的代码片段。 此消息已由第三方发送以供参考。 我不是Java开发人员。 有人可以告诉我我编写的C#代码是否与Java代码相对应? 如果没有,请让我知道我要去哪里。

private static String createDigitalSignature(Key key, byte[] data) {

    byte[] signature = null;

    try {
        // Initialize xml-security library
        org.apache.xml.security.Init.init();

        // Build DOM document from XML data
        DocumentBuilderFactory dfactory = DocumentBuilderFactory
                .newInstance();
        dfactory.setNamespaceAware(true);
        dfactory.setValidating(true);
        DocumentBuilder documentBuilder = dfactory.newDocumentBuilder();
        // This is to throw away all validation errors
        documentBuilder
                .setErrorHandler(new org.apache.xml.security.utils.IgnoreAllErrorHandler());
        Document doc = documentBuilder
                .parse(new ByteArrayInputStream(data));

        // Build canonicalized XML from document
        Canonicalizer c14n = Canonicalizer
                .getInstance("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
        byte[] canonBytes = c14n.canonicalizeSubtree(doc);

        // Initialize signing object with SHA1 digest and RSA encryption
        Signature rsa = Signature.getInstance("SHA1withRSA");

        // Set private key into signing object
        rsa.initSign((PrivateKey) key);

        // Generate signature
        rsa.update(canonBytes);
        signature = rsa.sign();
    } catch (Exception ex) {
        System.out.println("Exception occurred in createDigitalSignature: "
                + ex.toString());
        System.exit(-1);
    }

    // Base64 encode signature
    BASE64Encoder b64e = new BASE64Encoder();
    String signatureString = b64e.encode(signature);

    return signatureString;
}

在步骤3中,数字签名与加密摘要并不完全相同。 具有pkcs#1格式的rsa数字签名将digestAlgorithm OID(标识符)与摘要值连接在一起。 因此,您正在生成无效的签名。

所有编程语言都有一种无需处理摘要和密码即可执行数字签名的方法。 我不是C#程序员,但我想您必须使用RSACryptoServiceProvider.SignData

还使用VerifyData来验证签名

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM