Как я могу подписать ha sh из xml файла и интегрировать подпись в исходный файл - PullRequest
0 голосов
/ 03 августа 2020

Есть ли способ подписать ha sh файла xml, а затем интегрировать этот подписанный ha sh в исходный файл.

Для подписи PDF я использую iText, и он работает очень хорошо.

ОБНОВЛЕНИЕ 1: Подпишите оригинал XML ФАЙЛ

public class SignXML {

static String fileToSign = "B:/tmp/client/032936.xml";
static String signedFile = "B:/tmp/client/Signed-032936.xml";
static String certificate = "C:/lp7command/tools/certificate.p12";
static String password = "123456";

public static void main(String[] args) throws Exception{
    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");       
    Transform exc14nTranform = fac.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", 
            (TransformParameterSpec) null);
        Transform envTransform = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);

        List<Transform> transformList = new ArrayList();
        transformList.add(exc14nTranform);
        transformList.add(envTransform);

        Reference ref = fac.newReference("#evidence", fac.newDigestMethod(DigestMethod.SHA1, null), transformList,null, null);

        SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                (C14NMethodParameterSpec) null),fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));

        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(new FileInputStream(certificate), password.toCharArray());
        KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry ("mykey", 
                new KeyStore.PasswordProtection(password.toCharArray()));     
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

        KeyInfoFactory kif = fac.getKeyInfoFactory();
        List x509Content = new ArrayList();

        X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerDN().toString(), cert.getSerialNumber());
        //System.out.println(cert.getSubjectAlternativeNames().toString());
        x509Content.add(cert.getSubjectX500Principal().getName());
        x509Content.add(issuer);
        x509Content.add(cert);

        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(fileToSign));
        XMLStructure content = new DOMStructure(doc.getDocumentElement());
        
        XMLObject obj = fac.newXMLObject(Collections.singletonList(content), "evidence", null, null);

        DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc);
        XMLSignature signature = fac.newXMLSignature(si, ki, Collections.singletonList(obj), null, null);
        
        signature.sign(dsc);

        OutputStream os = new FileOutputStream(signedFile);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));
}
}

то, что я хочу сделать, это вычислить ha sh исходного XML файла и отправить его для подпись на другой сервер (B), который подпишет ha sh и вернет подписанный ha sh, который я затем интегрирую в исходный файл, который находится на сервере A.

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

XML цифровая подпись - это стандартный Java API, который отличается от классического c метода переваривания | шифрование | расшифровка значения ha sh. Суть в том, чтобы канонизировать | ссылка (URI) | встроить алгоритм подписи, а затем получатель проверяет как ссылка , так и подпись .

Успешно ли KeyValue созданный из массива в ваших кодах?

        List x509Content = new ArrayList();

        X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerDN().toString(), cert.getSerialNumber());
        //System.out.println(cert.getSubjectAlternativeNames().toString());
        x509Content.add(cert.getSubjectX500Principal().getName());
        x509Content.add(issuer);
        x509Content.add(cert);

        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

KeyValue является эквивалентом Publi c Key. Код очень прост:

            KeyInfoFactory kif = fac.getKeyInfoFactory();
            KeyValue kv = kif.newKeyValue(kp.getPublic());

            // wrap the value in the KeyInfo
            KeyInfo ki = kif.newKeyInfo(List.of(kv));

ПРИМЕЧАНИЕ. Each element of the XML signature result is required to canonicalise the signature and algorithm.

После создания действительной цифровой подписи XML он выглядит так:

<national-treasure>
.......
    </Banff-highlights>
      <Banff-revenue>CAD$6 billion per annum
    </Banff-revenue>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
        <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
        <Reference URI="">
            <Transforms>
                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
            <DigestValue>3tiwE7fdQxZ.....lU99kmkHAg/Bi6fESM=</DigestValue>
        </Reference>
    </SignedInfo>
    <SignatureValue>AZMlxFBjoZxmy8.....YOO3qINqG/wHoJPg==
    </SignatureValue>
    <KeyInfo>
        <KeyValue>
            <RSAKeyValue>
                <Modulus>sLQ+W9fT18Okqf.....tQ==
                </Modulus>
                <Exponent>AQAB</Exponent>
            </RSAKeyValue>
        </KeyValue>
    </KeyInfo>
</Signature>
</national-treasure>

Нетронутая XML подпись должна соответствовать следующим требованиям:

  • Подписанный элемент не был манипулируют
  • Метод дайджеста | значение | алгоритм должен совпадать среди этапов канонизации, шифрования и дешифрования.

Поместите это в контекст, метод прямого декодирования байтов ключа и отправки ha sh через серверы приложений полностью сводит на нет цель безопасного получения подписи. Существуют опции для поддержки проверки DS, снижения рисков (изменение конструкции документа) и предотвращения отказа от подписи с помощью Java API:

  • Включить безопасный процесс подписи, который может ограничивать преобразования XSLT document | URI перекрестной ссылки на сервере приложений.
  • Совокупное свойство безопасности для обеспечения соблюдения ограничений. например, увеличенная XML длина ключа подписи для проверки. В области NoSQL / хранилища документов, таких как MarkLogi c, существуют сложные функции безопасности для изучения и защиты данных PII: безопасность элементов, подписанные SSL-сертификаты, редактирование документов.

Если исходный документ, ключ publi c и подпись ВСЕ не скомпрометированы одновременно, крипто-API Java обнаружит подделку. Базовая подпись (заголовок | значение | значение ключа) или ссылочный элемент могут быть легко разупорядочены, а затем проверены.

Суть моего приложения: создать пару ключей, создать XML DOM sign context с закрытым ключом и подписанным XML узлом; DOM signature factory, ссылаясь на конвертированный / преобразованный документ с помощью переваренного алгоритма, затем канонизировал вышеупомянутый reference, наконец, создайте RSA keyvalue / keyinfo и подпишите XML. Logi c - это конкретная реализация Oracle Java XMLSignatureFactory | KeyInfoFactory, который соответствует W3C XML необходимым алгоритмам.

  • Ибо, хотя я поощряю творческое мышление, (не каламбур) я не очень хочу подписывать и бросать hash. (возможно, в этом есть определенная красота: Шифрование короткого сообщения в мобильной связи… et c). Я не понимаю, как вы можете иметь sh тяжелый XML.
  • Во-вторых, очень важно получить Keyvalue / keyinfo при разработке и подключении преобразования и алгоритма X509. Я спрашиваю, было ли получено правильное ключевое значение / информация.
  • В-третьих, в каком контексте вы указали экземпляр подписи DOM и создали ссылку?
0 голосов
/ 04 августа 2020

Да, есть способ сделать это. Взгляните, например, на https://www.w3.org/TR/xmldsig-core/ (один) стандартный способ сделать это. В зависимости от вашей технологии существует несколько библиотек, которые помогут вам в этом. Вы упомянули iText, поэтому для Java он уже некоторое время интегрирован в JRE. См. https://docs.oracle.com/en/java/javase/13/docs/api/java.xml.crypto/javax/xml/crypto/dsig/package-summary.html в качестве отправной точки.

Вы ищете заключенную в конверт XML -Подпись, где подпись не включена в расчет ha sh, чтобы он мог быть включенным в исходный документ.

ОБНОВЛЕНИЕ 1: Итак, вы хотите включить службу удаленной подписи в xml документы. Это также возможно, если это было сделано в предыдущей работе, хотя и немного сложнее.

В общем, вам нужно подключить место, где создается подпись, получить ha sh, отправить его на сервер, чтобы получить значение подписи и включите его в соответствующий узел XML.

Затем мы предоставили собственный Java Crypto Provider, (https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html), который переопределил бы объект закрытого ключа для удаленной подписи magi c. Оглядываясь назад, я бы рекомендовал изучить Apache Santuario http://santuario.apache.org/, который может быть немного более гибким при расширении, или библиотеку EU-DSS https://ec.europa.eu/cefdigital/DSS/webapp-demo/doc/dss-documentation.html#_other_implementations.

...