C# эквивалент Java XML метод подписи - PullRequest
0 голосов
/ 01 февраля 2020

Попытка создать подпись по противоположной проблеме (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;
        }
...