On 9/5/12 6:55 AM, Hariprasath wrote:
> Hi,
> I have applied signature in my XML which already contains a
> signature.
> The problem is when i try to verify the applied signature i get the error
> saying
> that the signature is bad. Pls help.
>
How are you creating the signature? You should be signing the existing
SignatureValue element, and then inserting the 2nd signature as a
SignatureProperty. See the attached example (using JSR 105) as an example that
might be helpful and you can adapt to your needs.
--Sean
import javax.xml.crypto.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.*;
import java.util.Collections;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This is a simple example of counter-signing an XML Signature using the
* JSR 105 API. The resulting counter-signature will be added as a
* SignatureProperty object of the existing XML Signature that has been
* counter-signed.
*/
public class CounterSign {
//
// Synopis: java CounterSign [input] [output]
//
// where "input" is the name of a file containing a signature that
// is to be counter-signed, and "output" is the name of a file that will
// contain the generated counter-signature. If output is not specified,
// standard output will be used.
//
public static void main(String[] args) throws Exception {
// Instantiate the document containing the signature
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc =
dbf.newDocumentBuilder().parse(new FileInputStream(args[0]));
// Find Signature element
NodeList nl =
doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
throw new Exception("Cannot find Signature element");
}
Element sig1Elem = (Element) nl.item(0);
// First, create the DOM XMLSignatureFactory that will be used to
// unmarshal and generate the counter XMLSignature
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
// Create a DOMValidateContext
DOMValidateContext valContext = new DOMValidateContext(sig1Elem);
// unmarshal the XMLSignature
XMLSignature signature1 = fac.unmarshalXMLSignature(valContext);
// Now we are going to create the counter signature
// First, create a Reference to the unmarshalled SignatureValue
Reference ref = fac.newReference("#" + signature1.getSignatureValueId(),
fac.newDigestMethod(DigestMethod.SHA1, null));
// Create the SignedInfo
SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod
(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, null),
fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),
Collections.singletonList(ref));
// Create a DSA KeyPair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();
// Create a KeyValue containing the DSA PublicKey that was generated
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
// Create a KeyInfo and add the KeyValue to it
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
// Create the XMLSignature (but don't sign it yet)
XMLSignature signature = fac.newXMLSignature(si, ki);
// insert to-be-signed counter-signature in a SignatureProperties elem
// find insertion point
Element objElem = null;
Element propsElem = null;
Element propElem = doc.createElementNS
(XMLSignature.XMLNS, "SignatureProperty");
propElem.setAttributeNS
(XMLSignature.XMLNS, "Target", "#" + signature1.getId());
nl = sig1Elem.getElementsByTagNameNS(XMLSignature.XMLNS, "Object");
if (nl.getLength() == 0) {
objElem = doc.createElementNS(XMLSignature.XMLNS, "Object");
propsElem = doc.createElementNS
(XMLSignature.XMLNS, "SignatureProperties");
propsElem.appendChild(propElem);
objElem.appendChild(propsElem);
sig1Elem.appendChild(objElem);
} else {
objElem = (Element) nl.item(0);
nl = objElem.getElementsByTagNameNS
(XMLSignature.XMLNS, "SignatureProperties");
if (nl.getLength() == 0) {
propsElem = doc.createElementNS
(XMLSignature.XMLNS, "SignatureProperties");
propsElem.appendChild(propElem);
objElem.appendChild(propsElem);
} else {
propsElem = (Element) nl.item(0);
propsElem.appendChild(propElem);
}
}
// Create a DOMSignContext and specify the DSA PrivateKey for signing
// and the document location of the XMLSignature
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), propElem);
// Lastly, generate the enveloping signature using the PrivateKey
signature.sign(dsc);
// output the resulting document
OutputStream os;
if (args.length > 1) {
os = new FileOutputStream(args[1]);
} else {
os = System.out;
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os));
}
}