Hello, I'm having a problem with xml signature. I need to build a 2 way communication system using webservices. Each request/response should be signed with RSA+SHA1. So the problem is that I can validate xml signature from other party, but when I create my signature with my private key, I'm unable to validate it with associated public key. I'm not fluent in cryptography, nor in java 2. So any help will be very appreciated.
here's the code:
public static void sign(PrivateKey expectedKey, Document doc) throws Exception{
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null));
CanonicalizationMethod canonicalizationMethod =
fac.newCanonicalizationMethod(
CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null);
SignatureMethod signatureMethod = fac.newSignatureMethod(
SignatureMethod.RSA_SHA1, null);
SignedInfo si = fac.newSignedInfo(
canonicalizationMethod, signatureMethod,
Collections.nCopies(1, ref));
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(getPeerPublicKey());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
XMLSignature signature = fac.newXMLSignature(si, ki);
DOMSignContext sc = new DOMSignContext(getPeerPrivateKey(), doc.getDocumentElement());
signature.sign(sc);
}
public static Node validateSignature(PublicKey expectedKey, Document doc) throws Exception{
XMLSignatureFactory signatureFactory = XMLSignatureFactory
.getInstance("DOM");
Node signatureNode;
signatureNode = getSignatureNode(doc);
XMLSignature sign = unmmarshalXMLSignature(signatureFactory,
signatureNode);
DOMValidateContext dvc = new DOMValidateContext(expectedKey,
signatureNode);
System.out.println(signatureNode.getTextContent());
try {
if (!sign.validate(dvc)) {
throw new Exception();
} else {
System.err.println("Signature is OK!");
}
} catch (XMLSignatureException e) {
throw e;
}
@SuppressWarnings("unchecked")
List<XMLObject> lst = sign.getObjects();
for (XMLObject obj : lst) {
@SuppressWarnings("unchecked")
List<DOMStructure> xmlStrList = obj.getContent();
for (DOMStructure struct : xmlStrList) {
return struct.getNode();
}
}
return null;
}
private static XMLSignature unmmarshalXMLSignature(
XMLSignatureFactory factory, Node signatureNode)
throws Exception {
DOMStructure struct = new DOMStructure(signatureNode);
XMLSignature sign;
try {
sign = factory.unmarshalXMLSignature(struct);
} catch (MarshalException e) {
throw new Exception(e);
}
return sign;
}
this is xml which should be generated
<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="#PAYMENTS"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>AK0WluLqklZJz3UObTDZ4lOtTrg=</DigestValue></Reference></SignedInfo><SignatureValue>Ct+x8gB4gm9PYi9fRg7ZzdCUSFbeHuhG3gL3wObQ+45dRLB3idWdJIPTE5rnSYSadLguyuW0PWtqy/BKWUfTyfcEKRZrmQpxxxY8RfyCS8GP4aWxUFXqolx0ewd9G5jef6ElKECOhYHK0sXHEEopBOsxVrP8LZMJ9779lqPlXUM=</SignatureValue><Object Id="PAYMENTS"><q1:PAYMENTS xmlns:q1="http://www.mof.ge/webservices/payservice/"><q1:Payment><q1:PaymentIdA>id_a</q1:PaymentIdA><q1:PaymentIdB>id_b</q1:PaymentIdB><q1:SrcBank>bankcode</q1:SrcBank><q1:SrcAccount>bankaccount</q1:SrcAccount><q1:PayerId>payerident</q1:PayerId><q1:PayerName>asdasd</q1:PayerName><q1:TaxPayerId>206322102</q1:TaxPayerId><q1:TaxPayerName>aa</q1:TaxPayerName><q1:ReceiverName>receivername</q1:ReceiverName><q1:AdditinalInfo>adasdasddsasd</q1:AdditinalInfo><q1:Amount>556</q1:Amount><q1:TreasuryCode>100771004</q1:TreasuryCode><q1:PaymentTime>9/7/2009 12:28:24 PM</q1:PaymentTime><q1:PaymentChannel>ATM</q1:PaymentChannel></q1:Payment></q1:PAYMENTS></Object></Signature>
I receive xml in this format from remote server, but my code generates slightly different xml, so i'm doing some parsing/reworking on the xml string, but anyway, the method validateSignature always fails with my generated signature.
the sign method generates xml in this format:
<?xml version="1.0" encoding="UTF-16"?>
<Object Id="PAYMENTS"><PAYMENTS xmlns=""><Payment><PaymentIdA/><PaymentIdB>aa</PaymentIdB><SrcBank>bb</SrcBank><SrcAccount>cc</SrcAccount><PayerId>dd</PayerId><PayerName>Dato</PayerName><TaxPayerId>00022023</TaxPayerId><TaxPayerName/><ReceiverName>mof</ReceiverName><AdditinalInfo>racxa</AdditinalInfo><Amount>521</Amount><TreasuryCode>hello</TreasuryCode><PaymentTime>hi</PaymentTime><PaymentChannel>ib</PaymentChannel></Payment></PAYMENTS><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=""><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>IXgHx5ioixsJ13jyg767D8UCU9s=</DigestValue></Reference></SignedInfo><SignatureValue>DO+Fngf3h0Q5iDoMq2mZFL+bxL3vY1i1fyqzBbKRPhHlzqWrW2wP3SFHjVzPLXdj92W8hMx9I8Jq
QBV/D+pUKa32aZB7kPwOGZqR63X+d6Hca58jnTK7+zq8Fzi2DPlE+omQhgT3xeXp/lQpKI8vAgVT
eX+eylRYTAZDSfDw7qk=</SignatureValue></Signature></Object>
as I said above, I'm doing some rework on the generated xml to change it scheme.
anyone has any idea why validation doesn't work on xml signatures generated by sign method?
thanks