验证由xml-crypto节点模块生成的xml签名

Issue validating xml signature generated by xml-crypto node module

本文关键字:xml 签名 模块 xml-crypto 节点 验证      更新时间:2023-09-26

我正在实现SAML 2.0 node.js身份提供程序。作为概念的证明,我想展示该服务对于。net消费者或服务提供者是可用的。我正在使用node- sample库。我遇到的问题是xml SAMLResponse是由npm包签名的,我正在尝试使用。net web应用程序验证xml签名。验证失败…

这是我写的javascript,以服务于身份提供程序片:

function postSuccess(req,res,next,userId){
    return ms.call('ms.ip.claims.getClaims').then(function(claims){
      return samlp.auth({
        cert: fs.readFileSync('c:''temp''test.pem').toString(),
        key: fs.readFileSync('c:''temp''test.key').toString(),
        signatureAlgorithm: 'rsa-sha1',
        digestAlgorithm:'sha1',
        getPostURL: function(wtrealm,wreply,req,callback){
          callback(null,req.samlRequest.AssertionConsumerServiceURL);
        },
        profileMapper: profileMapper,
        issuer: '<my-company>'
      })(req,res,next);
    });
}

这将生成SAMLResponse并成功地将其发送回我的。net web应用程序,但是当我试图验证xml文件的签名时,我遇到了问题。

下面是。net端验证代码:

            public bool IsValid(XmlDocument xmlDoc)
            {
                var cert = new X509Certificate2();
                cert.Import("c:''temp''test.pfx", "password", X509KeyStorageFlags.DefaultKeySet);
                var manager = new XmlNamespaceManager(xmlDoc.NameTable);
                manager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
                var nodeList = xmlDoc.SelectNodes("//ds:Signature", manager);
                var signedXml = new SignedXml(xmlDoc);
                signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
                signedXml.LoadXml((XmlElement)nodeList[0]);
                return signedXml.CheckSignature(cert, true);
            }

节点端使用的pem和key是从。net端使用的pfx证书生成的。我没有得到任何错误消息,只是signedXml.CheckSignature(cert,true)的错误结果。

请多多指教。

为了验证签名,您不需要提供密码并从.pfx加载私钥。这意味着您可以通过简单地加载与节点样本端相同的.pem来消除错误公钥的任何潜在问题。

我拿了你的样本代码并改变了这些行:

var cert = new X509Certificate2();
cert.Import("c:''temp''test.pfx", "password", X509KeyStorageFlags.DefaultKeySet);

:

var cert = new X509Certificate2(@"C:'temp'samlp.test-cert.pem");

(该文件提供了node- sample的测试工具)。

使用下面的示例节点Idp(也主要是从node-samlp的测试工具中窃取的):

var express = require('express');
var fs = require('fs');
var path = require('path');
var app = express();
var samlp = require('samlp');
var fakeUser = {
  id: '12345678',
  displayName: 'John Foo',
  name: { familyName: 'Foo', givenName: 'John' },
  emails: [ { type: 'work', value: 'jfoo@gmail.com' } ]
};
var options = {
  issuer:     'http://myidp',
  cert:       fs.readFileSync(path.join(__dirname, 'samlp.test-cert.pem')),
  key:        fs.readFileSync(path.join(__dirname, 'samlp.test-cert.key')),
  signatureAlgorithm: 'rsa-sha1',
  digestAlgorithm:'sha1',
  RelayState: 'test',
  getPostURL: function (wtrealm, wreply, req, cb) { 
    return cb( null, 'http://localhost:2181/AuthServices/Acs')
  },
  getUserFromRequest: function(req){ 
    return fakeUser 
  }
};
app.get('/samlp', samlp.auth(options));
var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;
  console.log('Listening at http://%s:%s', host, port);
});

警告以后阅读的任何人:问题中的。net代码只是一个概念证明。在现实生活中,要验证SAML断言并防止XML签名包装攻击,您需要的远远不止这些。使用已建立的。net SAMLP组件,如KentorIT。建议使用AuthServices或商业产品。披露:我是AuthServices的贡献者(但不是所有者)。