2015-11-05 52 views
0

我一直在研究SAML2 SP,並且正在嘗試將簽名添加到我的請求中。使用XMLSignature正確簽署XML

我已經通過創建自簽名證書:

OpenSSL的REQ -x509 -newkey RSA:2048 -keyout key.pem退房手續cert.pem -days 3650 -nodes

protected X509Certificate getCertificate() throws IOException, CertificateException 
{ 
    Path x509crtfile = dataDir.resolve("cert.pem"); 
    PEMParser pem = new PEMParser(Files.newBufferedReader(x509crtfile, Charset.forName("UTF8"))); 
    return new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)pem. readObject()); 
} 

protected RSAPrivateKey getKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException 
{ 
    Path x509keyfile = dataDir.resolve("key.pem"); 
    PEMParser pem = new PEMParser(Files.newBufferedReader(x509keyfile, Charset.forName("UTF8"))); 
    JcaPEMKeyConverter kc = new JcaPEMKeyConverter().setProvider("BC"); 
    return (RSAPrivateKey)kc.getPrivateKey((PrivateKeyInfo)pem.readObject()); 
} 

protected void signRequest(Document request) throws IOException, InvalidAlgorithmParameterException,  NoSuchAlgorithmException, CertificateException, InvalidKeySpecException, MarshalException, XMLSignatureException 
{ 
    DOMConfiguration docConfig = request.getDomConfig(); 
    docConfig.setParameter("infoset", Boolean.TRUE); 
    request.normalizeDocument(); 
    String id = request.getDocumentElement().getAttributeNS("urn:oasis:names:tc:SAML:2.0:protocol", "ID"); 
    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); 
    Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null), Collections.  singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), 
      null, null); 
    SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(
       CanonicalizationMethod.INCLUSIVE, 
       (C14NMethodParameterSpec) null), 
      fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); 
    KeyInfoFactory kif = fac.getKeyInfoFactory(); 
    List x509Content = new ArrayList(); 
    x509Content.add(getCertificate()); 
    X509Data xd = kif.newX509Data(x509Content); 
    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd)); 
    DOMSignContext dsc = new DOMSignContext(getKey(), request.getDocumentElement()); 
    dsc.setIdAttributeNS(request.getDocumentElement(), "urn:oasis:names:tc:SAML:2.0:protocol", "ID"); 
    XMLSignature signature = fac.newXMLSignature(si, ki); 
    signature.sign(dsc); 
} 

//片段的調用代碼:我用下面的代碼生成一個XML簽名

  signRequest(doc); 

      TransformerFactory tf = TransformerFactory.newInstance(); 
      Transformer t = tf.newTransformer(); 
      DOMSource source = new DOMSource(doc); 
      StringWriter sw = new StringWriter(); 
      StreamResult result = new StreamResult(sw); 
      t.transform(source, result); 
      byte[] encodedBytes = Base64.encodeBase64(sw.toString().getBytes()); 

示例輸出: 簽名驗證在測試IdP和使用在線工具都失敗。

<?xml version="1.0" encoding="UTF-8" standalone="no"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" samlp:AssertionConsumerServiceURL="http://inferno.dunlop-lello.uk:8080/plugins/saml-authentication/sp/acs" samlp:Destination="https://shibboleth.dunlop-lello.uk/idp/profile/SAML2/POST/SSO" samlp:ID="3368168774849506" samlp:IssueInstant="2015-11-05T08:57:51" samlp:ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" samlp:Version="2.0"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://inferno.dunlop-lello.uk:8080/plugins/saml-authentication/</saml:Issuer><samlp:NameIDPolicy/><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>sai05O1Ug2BbxFg25WHST29rF0E=</DigestValue></Reference></SignedInfo><SignatureValue>nj6CX1wtYZf20rXKiY7qD5vtiOUc8S7zNYMkXa1ZyhcZs62V92O8rjOi0u/JZaLq7w2Fvwh/T5GQ 
+Wvkz+XCJoZgNqv2DmJOZcwZkhZ5acoZM90tFWQPLptJj7IqS7T/egNTC7nXD0L61Ifn2DMhzliC qfT77SHpn5zieSKy20GoEaHYW9ucoDyON62Amghm5x1r7IKz8DoOqI19Au0ahOheIXjus7NqgLgJ eVgSOpoTpmyhZXa0c06+z1aYg+f0yMr91typYoFS3/IxMs4N7VRVVzX+O3/DbgqhVcM90N5bPgKd B/vQ61SMbYNRj5NRmedaaxCDkLDMQv+6LHahxQ==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIID3TCCAsWgAwIBAgIJAM3u0P2WViTzMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYDVQQGEwJHQjEU MBIGA1UECAwLV2VzdCBTdXNzZXgxFzAVBgNVBAcMDkhheXdhcmRzIEhlYXRoMSQwIgYDVQQKDBtE dW5sb3AtTGVsbG8gQ29uc3VsdGluZyBMVEQxIDAeBgNVBAMMF2luZmVybm8uZHVubG9wLWxlbGxv LnVrMB4XDTE1MTEwNDE3MjEyOFoXDTI1MTEwMTE3MjEyOFowgYQxCzAJBgNVBAYTAkdCMRQwEgYD VQQIDAtXZXN0IFN1c3NleDEXMBUGA1UEBwwOSGF5d2FyZHMgSGVhdGgxJDAiBgNVBAoMG0R1bmxv cC1MZWxsbyBDb25zdWx0aW5nIExURDEgMB4GA1UEAwwXaW5mZXJuby5kdW5sb3AtbGVsbG8udWsw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9nCCGd3Ikin15EkE2iMFUZx5C29CqZJjI RVxwPXBN+0SpPZBjiM30zAr4yeIg2YiMx9VfQsxprGUX2vpDzkR6yzgg+6LSACsoTB628pqqq4XH t5z1tKgpeRhef1Y+HA5AHT5ODI5YH4CyPxMXVdrjSfvvOe3mqCSHdkD2R0uPko5ZYzuxV/sQM3ZO wZmDvdLAj1W/16Z2v+l5CEbftI4wIbvRU6hwU7/ylA+gdAQdiIxlRf3mgzG6GW7sh9OK6A8pquBw YVZ7zLtAoV0QMb4r04nBF/N3wyMAdM8YSb3sio/2IxBkE4Osx2J2dH2V6sjBBnzkTZTQCLSuiO82 h6hFAgMBAAGjUDBOMB0GA1UdDgQWBBSJ7UW4/0xrutfCA4IBUp5esoyrADAfBgNVHSMEGDAWgBSJ 7UW4/0xrutfCA4IBUp5esoyrADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAXiu0E Z/A+YaqKrmm193rPJYCQrhl71P1OCBQysrYJIyygUZu3tXONaO/JvloNYLToFRO24kKdqf9WC7oh l2knIhPqoIc5/zsjiTsR9qQzNPHuhTA0GRquFvinR0rqdPBMuSfU+UjzOzXqkOxqr+X8L/e1IT5B 9Y66lGjJQcgzf71+C9m29aG+L4zzAYJURVwuljDYqVic6XmB5dUKdZn+7sNsuXkZp4u6QyyL7yEH rBbFF1tbPb7VXFroknbsUTIM5/Y36RzHWobS9LfYnwye8YyNP098UMWR5UalUCaityW6H6nUduge Du1z0L8uosGzsQr46KcBl038wi53ilzd</X509Certificate></X509Data></KeyInfo></Signature></samlp:AuthnRequest> 

任何指向哪裏/爲什麼這是錯誤的不勝感激。

回答

0

看來上面的代碼可能正常工作;我的發現在這裏發佈,希望他們能夠幫助下一個人遇到簽署SAML的問題。

我現在使用的是OpenSAML,而不是滾動我自己的解決方案,但是碰到了同樣的磚牆,結果是IdP上的誤導性錯誤消息。

具體而言,IdP上沒有SP的元數據,Shibboleth IdP使用元數據進行簽名驗證,而不是嵌入式證書。我試圖用於驗證的在線工具失敗,因爲它無法識別根CA,但又誤導了錯誤消息。