2017-03-01 8 views
1

서명 된 XML 요청이 있는데, 이는 유효하지 않은 서명으로 인해 제 3자가 거부합니다. 따라서 잘못된 내용을 확인하기 위해 자체 서명 확인 코드를 작성했습니다. 그러나 방금 만든 XML 서명의 유효성을 검사하는 동안 NPE가 표시됩니다. 다음은 XML이 (필자는 관련이없는 부분을 제거) 모습입니다 :자체 XML 유효성을 검사하는 동안 Java NPE

<?xml version="1.0" encoding="UTF-8"?> 
<envelope xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation="some_third_party.xsd"> 
    <header>...</header> 
    <body>...</body> 
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="MySignature"> 
     <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>AaV+ejxBF8GjJvIZA9Bonw81Z1Y=</DigestValue> 
      </Reference> 
      <Reference Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties" URI="#SignatureProperties"> 
       <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
       <DigestValue>qcofYVnQ/n7sxKJPT5rG0+UYbjg=</DigestValue> 
      </Reference> 
     </SignedInfo> 
     <SignatureValue>XXX</SignatureValue> 
     <KeyInfo> 
      <X509Data> 
       <X509Certificate>XXX</X509Certificate> 
      </X509Data> 
     </KeyInfo> 
     <Object Id="SignatureProperties"> 
      <SignatureProperties xmlns=""> 
       <SignatureProperty Id="TimeStamp" Target="#MySignature"> 
        <TimeStamp> 
         <Date>2017-03-01</Date> 
         <Time>09:06:36.779+01:00</Time> 
        </TimeStamp> 
       </SignatureProperty> 
      </SignatureProperties> 
     </Object> 
    </Signature> 
</envelope> 

내가 실제 전에 서명을 비 정렬 화시 실제로 발생, 그래서 내가 (주석 줄에 NPE를 얻고이 서명 유효성을 검사 할 검증) :

try { 
    XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM"); 

    Reference ref = xmlSignatureFactory.newReference("", 
      xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null), 
      Collections.singletonList(xmlSignatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), 
      null, 
      null); 

    Reference signatureRef = xmlSignatureFactory.newReference("#SignatureProperties", 
      xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null), 
      null, 
      "http://www.w3.org/2000/09/xmldsig#SignatureProperties", 
      null); 

    SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), 
      xmlSignatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null), 
      Arrays.asList(ref, signatureRef)); 

    XMLObject xmlObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(new DOMStructure(timestamp)), 
      "SignatureProperties", null, null); 

    KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory(); 
    List<Object> x509Content = new ArrayList<>(); 
    x509Content.add(certificate); 
    X509Data xd = keyInfoFactory.newX509Data(x509Content); 
    KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xd)); 

    XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo, 
      Collections.singletonList(xmlObject), SIGNATURE_ID, null); 
    DOMSignContext signContext = new DOMSignContext(privateKey, document.getDocumentElement()); 
    xmlSignature.sign(signContext); 
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException e) { 
    // Handle exception 
} 

어떤 생각 내가 잘못 여기서 뭐하는 거지 : 완성도를 들어

// Omitted: extract the X509 Certificate from the document 
DOMValidateContext valContext = new DOMValidateContext(cert.getPublicKey(), signature); 
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM"); 
XMLSignature xmlSignature; 
try { 
    // Null pointer exception here! 
    xmlSignature = factory.unmarshalXMLSignature(valContext); 
} catch (MarshalException e) { 
    // Handle exception 
} 

, 여기에 내가 서명을 생성하는 방법이다?

편집 :

java.lang.NullPointerException: null 
    at org.jcp.xml.dsig.internal.dom.DOMXMLObject.<init>(DOMXMLObject.java:120) 
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.<init>(DOMXMLSignature.java:171) 
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:193) 
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:150) 

편집 2 : NPE 정확히 발생 위치를 표시하기 위해 스택 트레이스를 추가 나는 또한 SignedValue와 X509Certificate에 콘텐츠를 모두 공백이 언급해야 나에게 이상한 보이는 서명을 생성 한 후 . 예 :

<X509Certificate>MIIG8DCCBdigAwIBAgIUJZSmBORuGuXyx48f04sNGHT+RhwwDQYJKoZIhvcNAQELBQAwWzELMAkG 
    A1UEBhMCQ0gxEzARBgNVBAoTClBvc3QgQ0ggQUcxDTALBgNVBAsTBFBST0QxKDAmBgNVBAMTH1BL 
    SSBTd2lzc1Bvc3QgTWFjaGluZSBBRVAgQ0EgRzMwHhcNMTcwMTI2MTIzMTQ0WhcNMjAwMTI2MTIz 
    MTQ0WjCBsTELMAkGA1UEBhMCQ0gxCzAJBgNVBAgTAkZSMSAwHgYDVQQKExdEaWUgU2Nod2VpemVy 
    ... 
+0

당신이 스택 추적을해야하나요 :이 방법의

private Element createTimestamp(Document doc) { // Use createElementNS instead of createElement, otherwise you will get the aforementioned NPE Element signatureProperties = doc.createElementNS("", "SignatureProperties"); Element signatureProperty = signatureProperties.getOwnerDocument().createElementNS("","SignatureProperty"); signatureProperty.setAttribute("Target", "#" + SIGNATURE_ID); signatureProperty.setAttribute("Id", "TimeStamp"); Element timeStamp = signatureProperty.getOwnerDocument().createElementNS("", "TimeStamp"); ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault()); Element date = timeStamp.getOwnerDocument().createElementNS("", "Date"); date.setTextContent(now.toLocalDate().toString()); Element time = timeStamp.getOwnerDocument().createElementNS("", "Time"); time.setTextContent(now.toLocalTime().toString() + now.getOffset().toString()); timeStamp.appendChild(date); timeStamp.appendChild(time); signatureProperty.appendChild(timeStamp); signatureProperties.appendChild(signatureProperty); return signatureProperties; } 

결과는 다음이 라인에 사용되는 ? –

+0

예, 이제 스택 추적을 추가했습니다. – Egemen

+0

'signature'가 null이 아니 었습니까? –

답변

1

일부 디버깅 후 문제가 발생했습니다. DOMXMLObjectSignatureProperties 노드의 로컬 이름을 가져 오려고 시도하며 null을 반환합니다. 나는 그 요소를 만드는 방법을 약간 수정했고 이제는 잘 작동한다. 내가 경우 코드의 조각을 추가하고

는 다른 나중에 누군가를 위해 유용하다 :

XMLObject xmlObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(new DOMStructure(createTimestamp(doc))), 
       "SignatureProperties", null, null);