2011-11-13 3 views
2

Apache Santuario Java 라이브러리 버전 1.4.6을 사용하여 XML 서명을 확인하는 데 도움이되는 몇 가지 도움을 찾고 있습니다. 클라이언트가 서버에 문서를 보내기 전에 클라이언트가 DOM 문서에 서명하는 클라이언트/서버 솔루션이 있습니다. 그래서 같은 문서에 서명을 적용 다음과 같이Apache Santuario를 사용하여 XML 서명을 확인할 수 없습니다. 1.4.6

public static void applySignature(X509Certificate cert, PrivateKey privateKey, Document doc) 
{ 
    try 
    { 
     XMLSignature sig = new XMLSignature(doc, 
              "", 
              XMLSignature.ALGO_ID_SIGNATURE_RSA); 

     sig.addResourceResolver(new XmlSignatureResolver()); 
     doc.getDocumentElement().appendChild(sig.getElement()); 

     Transforms transforms = new Transforms(doc); 
     transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE); 
     transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS); 

     sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1); 

     sig.addKeyInfo(cert); 
     sig.addKeyInfo(cert.getPublicKey()); 

     sig.sign(privateKey); 
    } 
    catch (XMLSecurityException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

내가 서명을 확인 :

public static boolean verifySignature(X509Certificate cert, Document doc) 
{ 
    boolean validSignature = false; 

    try 
    { 
     Element nscontext = createDSctx(doc, "ds", Constants.SignatureSpecNS); 

     // Remove any attributes of Signed Info 
     Node signInfoNode = XPathAPI.selectSingleNode(doc, "//ds:SignedInfo", nscontext); 

     int numAttributes = signInfoNode.getAttributes().getLength(); 
     if (numAttributes > 0) 
     { 
      for (int i = 0; i < numAttributes; i++) 
      { 
       String attrName = signInfoNode.getAttributes().item(0).getNodeName(); 
       signInfoNode.getAttributes().removeNamedItem(attrName); 
      }  
     } 

     Element sigElement = 
      (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature", nscontext); 
     XMLSignature signature = new XMLSignature(sigElement, ""); 

     signature.setFollowNestedManifests(true); 
     signature.addResourceResolver(new XmlSignatureResolver()); 

     validSignature = signature.checkSignatureValue(cert); 

     // Remove the signature 
     sigElement.getParentNode().removeChild(sigElement);    
    } 
    catch (XMLSignatureException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    catch (XMLSecurityException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    catch (TransformerException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return validSignature;// validSignature; 
} 

내가 가진 문제는 서버의 서명을 검증 할 때 (그것이 작동한다는 것입니다

2011-11-12 18시 30분 27초 참조 [WARN] 검증이 URI 실패 ""
(201) : I)가 서명을 적용한 후 권리를 확인하는 경우 클라이언트, 나는 다음과 같은 경고를 얻을 수 어 + J/jsY8Im2rgjsozBXRxkQjQ =
2011-11-12 18시 30분 27초 기준은 [WARN] 실제 다이제스트 : Y7C0HCjugZbegkZT4E8A7Bd4qm0 =

1-11-12 18시 30분 27초 참조 [WARN]는 다이제스트 예상 도움을

감사합니다,
어니 Burlison

=============

내가 클라이언트에서 서버로 DOM을 전송하는 데 사용하는 코드는 다음과 같습니다

,602,653,210 서버 측에서 DOM을 읽어 코드

이다 다음 서명 (서명을 적용하기 전에 암호화 된 데이터)를 다음과 유사한 적용

   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
       dbf.setNamespaceAware(true); 
       DocumentBuilder db = dbf.newDocumentBuilder(); 

       m_Logger.debug("Parsing Document"); 
       Document doc = db.parse(m_SenderInput); 
       m_Logger.debug("Received DOM"); 

돔 전 :

<?xml version="1.0" encoding="UTF-8"?><SmMessageSet xmlns="urn:ccsds:recommendation:service_management:schema:sccs:R1.0" xmlns:ns2="urn:ccsds:recommendation:navigation:schema:ndmxml:R1.5"><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Content"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/><xenc:CipherData><xenc:CipherValue>VosyFTcuAkzo6WPPLnnM2Nka+gpyD9r2cNy3fbSX8RjGg5dKktK9SGZAar5t3ci2mU6Nw9Ski2Td 
g1WNei+kgns6vFET5Ff8m5/VIO24sBz30DPO5cAwfLax0slTjZWDRu7XXs/ORSK2PrB8B8qaO+me 
W5iPLXjkkL4LnLwZfIvCSdG3JJoOTUhR6CstquTejRBLvTdvry8jB2RncjpV244eng7Bmk7HWcNd 
Mz20DujfX14MTyKAQcVAgUhM9MpisveiDRdKYtXWCkma2NcUhpxqzjyPtyJtHVJQfaPZ2kla2NQV 
DcMPUvmM+V0Y3kI5NBZq1vlIAg1i5JsZRniB+Q==</xenc:CipherValue></xenc:CipherData></xenc:EncryptedKey></ds:KeyInfo><xenc:CipherData><xenc:CipherValue>8UCDr2ZzDvD5JczkPU7UnxRYBdxs6ZgL5s2ksHyn/FZvBVSwYh6o/Rnx41fnN6uygcylW++zoxSq 
a9qcpuS8rFxtw6TtRzZeixJYBgZWVHp9NYiB4WbtZF6iR5EjaGKZdghUgCVtvKKbpbMQTTPRCBym 
7HA2iQzNpGH1tcGegDB8+w3ALDP8QN5q3PG2uFBk880KXRozxAxKZVNKZfEZyat0fnzf6J8bTCac 
n1lxV02jCWyz1/2Gd/jfo8B2BLXVMZWm0WiM7Z/uk4PFsTQjPmb1CD+E+7Oh8TRJzIqC1dyPQVV+ 
kgdoJbM/2sZka1VCuUzEIEQ1fhH+iUE0ymtuw+djwhfqDAow1pfRJOsak2cXzLoYO7mwqmIHoeaM 
hN9IAtI/TfXDHNSL8ledhYT/ZL2gmNSR1Jze6JZPaXgqkmBEGVgqbzLex/5drxOf/DQVcugSnqEw 
uHrikLsjU4jHozNg4PGidJNPCKLPgJaiLX1rgyo9N6pUDMVrNH+Tz1G7EFydzZOrZt+yY8Je17NL 
ah8mBQb/S5zGD7642aDR4UmVQthD3LTMIG/oxbzMIh/OOcC432SZ+ShAvUD+bU+GDDdcOKzemLPB 
EV6QLstFqonyHLSTQqgIMU5z2NxFpJIKRBClX09q5fOytaRVrGIZgJtOfuT4zFwjmwF66yuiQp0H 
gD9O95A+ifmwe8k9KUsAO9Q8alxrXrqhptfsySCYDo2nSXbhSn5cKgsdK4jw5B6zsoQQZxJmzsYT 
ZSbo0DhjAbZVszsU0HeTMRKRNlOABXAJPxSmqz2hT/wgYnWSMZt839swJyOZhaMuOUfShAP1iVo+ 
m5xM+zw7SnsAwFozNw==</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></SmMessageSet> 

XML은 applySignature 이후와 SignedInfo가 verifysignature 메소드 내에서 수정 된 후에 동일합니다. 문제는 소켓을 통해 문서를 보낼 때 SignedInfo 참조 항목이있는 것 같습니다. 어떻게 든 확인하는 동안 발생하는 변환은 46 바이트를 추가하여 검사를 실패하게 만듭니다.

어디에서 발생했는지 확실하지 않습니다. 누구든지 아이디어가 있습니까?

답변

0

오류와 직접 관련이 없지만 나중에 오류가 발생합니다. SignedInfo 요소 내에서 아무 것도 제거하거나 변경하지 않아야합니다. 최종 서명 값은 정규화 된 SignedInfo 요소의 다이제스트를 통해 계산됩니다. 따라서 서명을 검증하기 전에 무언가를 바꾼다면 분명히 깨뜨릴 것입니다.

문서 요약이 유효하지 않은 이유는 여러 가지 이유가있을 수 있습니다. 추측을 분석하기가 어려울 수 있습니다. 여기 서명되지 않은 문서를 게시 할 수 있다면, 적어도 올바른 다이제스트 값이 무엇인지 말할 수 있다면 ...

+0

응답 해 주셔서 감사합니다. 이 코드는 SignedInfo의 속성을 제거합니다. 클라이언트 측의 applysignature에서 나온 것처럼 보이도록 문서를 가져 오려고했기 때문입니다. 소켓을 통해 데이터를 보내기 위해 dom에서 수행하는 변환이 추가 속성을 추가했을 수도 있다고 생각했습니다. –

0

이 문제는 SignedInfo가 아니라 KeyInfo 노드에서 발생했습니다. KeyInfo 노드에는 원래 서명이 적용될 때 없었던 네임 스페이스 특성이 추가되었습니다. 서명 값을 확인하기 전에 KeyInfo 속성을 제거하면 내가보고 있던 문제가 해결됩니다.

0

짧은 답변 : 원래 질문에서 applySignature의 시작 부분에 doc.normalizeDocument();을 추가하십시오. 따라서 서명을 추가하기 전에.

대한 추가 정보 :

나는이 오래된 질문이다 알지만, 답변의 해결되지 않은 비슷한 문제가 있었다. 사실 나는 대답 중 하나가 잘못되었다고 생각합니다. 문제는 확인 과정에 있다고 말합니다. 그러나 나는 그것이 서명에 있다고 믿습니다! 내 경험과 해결책을 여기에 넣으면 비슷한 문제를 가진 누군가가 도움이되기를 바랍니다.

XML 문서를 생성하고 서명했습니다. 나는 아파치 Santuario와 함께 서명을 시도했다. 작동하지 않으면 javax.xml.crypto.dsig로 전환했습니다.

이 두 가지 방법 모두 Santuario와 외부 도구를 사용하여 확인한 경우 올바르게 서명되지 않은 XML 문서를 생성했습니다. 서명 된 XML의 예

우선은 생성하려고 : signed-envelope

<signed-envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="somenamespace" xsi:schemaLocation="someshemelocation"> 
    <object xml:id="object0"> 
     ... 
    </object> 
    <signatures> 
     <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
     ... 
     <SignedInfo> 
      <Reference URI="#object0"> 
      ... 
     </SignedInfo> 
     </Signature> 
    </signatures> 
</signed-envelope> 

네임 스페이스가 중요하다! 모든 것이 네임 스페이스없이 완벽하게 작동했습니다. 그러나 필요한 네임 스페이스를 signed-envelope에 추가하면 서명 할 수없는 XML 파일이 생성되었습니다. 또한 외부 도구가 아닙니다 (즉, 서명이 실패했음을 의미하며 확인이 아닙니다)!

Santuario는 log4j로 훌륭한 디버깅 결과를 제공합니다. 이 출력은 어를 보여 주었다 : 검증 도중, 다음 네임 스페이스가 모두 <object>에 추가되고 <SignedInfo>되었다

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

이 확인하는 올바른 방법입니다! 여기에있는 대답 중 하나는 올바르지 않다고 말하며 문제를 해결하려고 시도하지만 이것이 사실입니다. 여기서 문제는 검증이 아니라 서명하는 것입니다.

문제는 Santuario가 문서에 서명 할 때이 네임 스페이스가 추가되지 않았다는 것입니다. 이로 인해 내가 생성 한 Document 개체가 잘못되었다고 생각하게되었습니다. 내 XML 문서가이 같은 루트 요소에 추가 된 네임 스페이스와 생성되었습니다

rootElement.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:noNamespaceSchemaLocation", "some_namespace"); 

을 검색을 많이 후, 나는 doc.normalizeDocument()이 유사한 문제를 해결할 것을 알아 냈다. 나는 그것을 시도, 모든 작품!
나는 왜 doc.normalizeDocument()이 모든 것을 작동시키는 지 알지 못하지만, 이제는 Apache Santuario와 javax.xml.crypto.dsig 모두에 올바르게 서명 할 수 있습니다. 따라서 두 사람은 올바르게 서명해야합니다.

관련 문제