2014-09-05 20 views
1

我簽署了XML文檔,並根據此文檔計算簽名。簽名中的空格是什麼意思?

  • 簽名算法:這是用於簽名http://www.w3.org/2000/09/xmldsig#rsa-sha1
  • 散列算法:下面我的代碼 http://www.w3.org/2000/09/xmldsig#sha1

部分。

... 
initKeyAndCertificate(); 
Document signedXmlDoc = getSignXML(signMethod, 
    digestMethod, decodeXmlDocAsString); 
String signedXMLAsString = getSignedXMLAsString(signedXmlDoc); 

org.jsoup.nodes.Document document = Jsoup.parse(signedXMLAsString); 
Element signatureValueTag = document.select("SignatureValue").first(); 
String signatureValueAsString = signatureValueTag.text(); 

System.out.println("======================================="); 
System.out.println(signedXMLAsString); 
System.out.println("======================================="); 
System.out.println(signatureValueAsString); 
System.out.println("======================================="); 
... 

initKeyAndCertificate方法:

private void initKeyAndCertificate() throws Exception { 
    String jksFileName = "C:/Java/keys/testkey.jks"; 
    FileInputStream fileInputStream = null; 

    try { 
     fileInputStream = new FileInputStream(new File(jksFileName)); 
    } catch (FileNotFoundException fe) { 
     fe.printStackTrace(); 
    } 

    final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    char[] KeyStorePass = null; 
    keyStore.load(fileInputStream, KeyStorePass); 

    key = 
     keyStore.getKey("testkey", new char[]{'t', 'e', 's', 't', 'k', 'e', 'y'}); 
    certificate = keyStore.getCertificate("testkey"); 

    try { 
     fileInputStream.close(); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

getSignXML方法:

public Document getSignXML(String signMethod, 
     String digestMethod, String XmlDocAsString) throws Exception { 
    final DocumentBuilderFactory documentBuilderFactory = 
      DocumentBuilderFactory.newInstance(); 
    documentBuilderFactory.setIgnoringElementContentWhitespace(true); 
    documentBuilderFactory.setCoalescing(true); 
    documentBuilderFactory.setNamespaceAware(true); 

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 
    InputSource is = new InputSource(new StringReader(XmlDocAsString)); 

    Document doc = builder.parse(is); 

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

    List<Transform> transformList = new ArrayList<Transform>(); 
    Transform transformC14N = 
      xmlSignatureFactory.newTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, 
        (XMLStructure) null); 
    transformList.add(transformC14N); 

    Reference reference = xmlSignatureFactory.newReference("", 
      xmlSignatureFactory.newDigestMethod(digestMethod, null), 
       transformList, null, null); 
    SignedInfo signedInfo = 
      xmlSignatureFactory.newSignedInfo(
        xmlSignatureFactory.newCanonicalizationMethod(
          CanonicalizationMethod.EXCLUSIVE, 
        (C14NMethodParameterSpec) null), 
      xmlSignatureFactory.newSignatureMethod(signMethod, null), 
      Collections.singletonList(reference)); 

    KeyInfoFactory keyInfoFactory = 
      xmlSignatureFactory.getKeyInfoFactory(); 
    X509Data x509Data = 
      keyInfoFactory.newX509Data(Collections.singletonList(certificate)); 
    KeyInfo keyInfo = 
      keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data)); 

    final Node node = doc.getDocumentElement(); 

    javax.xml.crypto.dsig.XMLSignature xmlSignature = 
      xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo); 
    DOMSignContext signContext = new DOMSignContext(key, node); 
    xmlSignature.sign(signContext); 

    return doc; 
} 

getSignedXMLAsString方法:

private String getSignedXMLAsString(Document signedDocument) { 
    DOMSource domSource = new DOMSource(signedDocument); 
    StringWriter stringWriter = new StringWriter(); 
    StreamResult streamResult = new StreamResult(stringWriter); 
    TransformerFactory transformerFactory = TransformerFactory.newInstance(); 
    Transformer transformer = null; 

    try { 
     transformer = transformerFactory.newTransformer(); 
    } catch (TransformerConfigurationException e) { 
     e.printStackTrace(); 
    } 

    try { 
     transformer.transform(domSource, streamResult); 
    } catch (TransformerException e) { 
     e.printStackTrace(); 
    } 
    return stringWriter.toString(); 
} 

signatureValueAsString:

i0Ws4MjH7AfPcbHEDCzrMjV+e4O41l43ZXEMHbcCjTmP4WKl7iVH3IcoM6ugS4qMejOHctntH41w 8niOxnCMcjDEnwM6kZtMIJyjrTxMVjSUDyFcKB79Yc/v5hC3dH5deX59W4oxM6Fg72W23s3zcMDD rdRCM5wHqMZW0WvBMoM= 

簽名包含空格。這些空間在簽名中的含義是什麼?我可以刪除它們並連接子字符串嗎?

回答

1

這可能是一個新行,而不是一個空格,它是二進制簽名數據的Base64 encoding的一部分(XML不能處理二進制數據,特別是0字節是不允許的)。

Base64通過電子郵件發送二進制數據的根源限制爲每行76個字符,以避免觸發郵件軟件中的自動換行。