С# эквивалент метода подписи Java XML

Попытался создать подпись с помощью противоположной проблемы (Java-эквивалент метода подписи C# XML), но не повезло. Так может ли кто-нибудь помочь мне подписать XmlDocument на С#? При решении противоположной проблемы я получаю исключение, что в точном месте нет закрытого ключа: signedXml.ComputeSignature();

Итак, как мне реализовать метод подписи на С#, например, я получил:

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?

А что если у меня только приватный ключ и сертификат без KeyStore?

Метод С#:

 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;
        }

person Karlito    schedule 01.02.2020    source источник
comment
Пройдите обзор, чтобы узнать, как работает Stack Overflow, и прочитайте Как спросить о том, как улучшить качество вашего вопроса. Затем отредактируйте свой вопрос, включив исходный код в качестве минимальный воспроизводимый пример, который может быть скомпилирован и протестирован другими. Мы не сможем помочь вам с имеющимся у вас кодом C#, если вы не добавите его в свой вопрос.   -  person Progman    schedule 01.02.2020
comment
В ссылке хранилище ключей создается из строки: new KeyStore.PasswordProtection(password.toCharArray()). Таким образом, вы можете использовать любую строку при создании сертификата, а затем пользователь может использовать ту же строку для проверки сертификата.   -  person jdweng    schedule 01.02.2020