Попытка создать подпись по противоположной проблеме (Java эквивалент C# XML метод подписи ), но безуспешно. Так может кто-нибудь помочь мне подписать XmlDocument в C#? Решением в противоположной задаче я получаю исключение, что нет точного закрытого ключа в точном месте: signedXml.ComputeSignature();
Так как мне реализовать метод подписи в C#, например, я получил:
imports...
@SuppressWarnings("restriction")
public abstract class BaseAuthRequestGenerator {
public static final String SIGNED_NODE_ID = "uniqueNodeId";
private static final char[] PASSWORD = "testtest".toCharArray();
private static final XMLSignatureFactory XML_SIGNATURE_FACTORY = XMLSignatureFactory.getInstance("DOM");
protected PrivateKey privateKey = null;
protected PublicKey publicKey = null;
public BaseAuthRequestGenerator() {
try {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(FileUtils.openInputStream(FileUtils.toFile(AuthGenerator.class.getResource("/testKeystore.jks"))), PASSWORD);
for (Enumeration<String> e = keyStore.aliases(); e.hasMoreElements();) {
String alias = e.nextElement();
if (keyStore.isKeyEntry(alias)) {
privateKey = (PrivateKey) keyStore.getKey(alias, PASSWORD);
X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
publicKey = cert.getPublicKey();
break;
}
}
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public Node marshal(Object data) throws JAXBException {
String packageName = data.getClass().getPackage().getName();
JAXBContext jc = JAXBContext.newInstance(packageName);
DOMResult result = new DOMResult();
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(data, result);
return result.getNode();
}
public String getSignedXml(Node node, String referenceUri) throws Exception {
signNode(node, referenceUri);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
final ByteArrayOutputStream output = new ByteArrayOutputStream();
trans.transform(new DOMSource(node), new StreamResult(output));
return new String(output.toByteArray(), Charset.forName("UTF-8"));
}
public void signNode(Node node, String uri) throws Exception {
DOMSignContext dsc = new DOMSignContext(privateKey, node);
XMLSignatureFactory fac = XML_SIGNATURE_FACTORY;
List<String> prefixList = new ArrayList<String>();
prefixList.add(node.getPrefix());
C14NMethodParameterSpec spec = new ExcC14NParameterSpec(prefixList);
List<Transform> transforms = new ArrayList<Transform>();
transforms.add(fac.newTransform(CanonicalizationMethod.ENVELOPED, (TransformParameterSpec) null));
transforms.add(fac.newTransform(CanonicalizationMethod.EXCLUSIVE, spec));
Reference ref = fac.newReference(uri, fac.newDigestMethod(DigestMethod.SHA1, null), transforms, null, null);
SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, spec), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(publicKey);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
}
/**
* Sets ID attribute (named "id") for given node.
* <p>
* Necessary for XML signing/validation when running on JDK 7
*
* @param node node to set ID attribute for
* @see http://stackoverflow.com/questions/17331187/xml-dig-sig-error-after-upgrade-to-java7u25
*/
public void setIdAttribute(Node node) {
Node idAttribute = node.getAttributes().getNamedItem("id");
if (idAttribute != null) {
((Element) node).setIdAttribute("id", true);
}
}
}
Чтобы подписать xml документ, я должен использовать сертификат и закрытый ключ RSA?
А что, если у меня есть только закрытый ключ и сертификат без хранилища ключей?
C# метод:
private static XDocument SignXDocument(XDocument document)
{
XDocument returnDoc = new XDocument();
XmlDocument convertedDoc = DocumentExtensions.ToXmlDocument(document);
convertedDoc.PreserveWhitespace = true;
X509Certificate2 certificate = GetX509Certificate2();
RSACryptoServiceProvider privateKey = GetPrivateKey(KeyPath);
SignedXml signedXml = new SignedXml(convertedDoc) { SigningKey = certificate.PrivateKey };
Reference reference = new Reference { Uri = "#" + ID };
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
signedXml.AddReference(reference);
// embed public key information for signature validation purposes
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data(certificate, X509IncludeOption.ExcludeRoot);
keyInfo.AddClause(keyInfoX509Data);
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement xmldsigXmlElement = signedXml.GetXml();
var changed = xmldsigXmlElement.ToXElement();
document.Add(changed);
return document;
}