[JAVA] Signer XML à l'aide d'Apache Santuario

Apache Santuario (Sécurité XML) (http://santuario.apache.org/) semble être de facto la signature de XML en Java.

1. Préparez votre certificat et votre clé privée

Tout d'abord, vous avez besoin d'un certificat et d'une clé privée pour signer. Veuillez préparer à l'avance. Lorsque j'ai préparé la clé privée avec pem, elle n'a pas été reconnue, je vais donc laisser la clé privée au format pkcs # 8. Il peut y avoir un moyen de lire directement le pem, mais ici nous allons convertir la clé.

$ openssl pkcs8 -in xxx.pem -topk8 -nocrypt -outform DER -out mypriv.key

2. Lire le certificat et la clé privée

Lisez le certificat et la clé privée comme suit: Oh, le code utilise également lombok.

public static X509Certificate loadCert(InputStream certFile) throws CertificateException {
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    return (X509Certificate)cf.generateCertificate(certFile);
}

public static PrivateKey loadPrivateKey(InputStream privateKey) throws IOException, GeneralSecurityException {
    val buf = readPrivateKey(privateKey);
    val keySPec = new PKCS8EncodedKeySpec(buf);
    	
    return KeyFactory.getInstance("RSA").generatePrivate(keySPec);
}

private static byte[] readPrivateKey(InputStream in) throws IOException {
    byte[] data = new byte[in.available()];
    in.read(data);
		
    return data;
}

3. Signer

Maintenant que vous avez votre certificat et votre clé privée prêts, signez le XML.

Créez d'abord un objet à signer. Spécifiez l'URI et l'algorithme de signature de l'objet Document XML à traiter lors de la création de l'objet et de son fichier. Et après cela, j'ajoute un élément pour signer le XML d'origine.

val sig = new XMLSignature(doc, "file:/test.xml", XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256);
doc.getDocumentElement().appendChild(sig.getElement())

Au fait, test.xml

<?xml version="1.0" encoding="UTF-8"?>
<elem1>
  <elemt2>xxx</elem2>
</elem1>

Ensuite, enregistrez le résolveur de ressources. Il s'agit du ResourceResolver, qui est alors l'objet pour obtenir les éléments à digérer et le contenu d'un autre fichier. Le code ResourceResolver sera expliqué plus tard.

Après cela, l'objet des transformations est défini. ResourceResolver est uniquement responsable de la récupération du contenu sous forme de chaîne d'octets. Vous devez canoniser pour obtenir le résumé des éléments XML. Les transfomrs sont les personnes qui analysent le XML à partir d'octets et le canonisent.

La première question que je me posais lors de la signature du XML était de savoir comment le normaliser, ou s'il n'était pas normalisé, le résumé ne serait pas correct. C'est [Standardized as Canonical XML](https: / /www.w3.org/TR/xml-c14n11/), et transfomrs en est responsable.

Spécifiez ces transformations avec uri dans addDocument. Spécifiez null pour les fichiers qui n'ont pas besoin d'être convertis.

sig.getSignedInfo().addResourceResolver(new MyResolver());

val transforms = new Transforms(kouseiBase);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_OMIT_COMMENTS);

sig.addDocument("#elem2", transforms, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256);
sig.addDocument("somefile.txt", null, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256);

Après cela, spécifiez le certificat et la clé privée à signer. Les informations de signature sont maintenant ajoutées au premier document.

```java` sig.addKeyInfo(certificate); sig.addKeyInfo(certificate.getPublicKey()); sig.sign(privateKey);


 4. ResourceResolverSpi

 Utilisez REsourceResolverSpi pour résoudre l'URI. Il existe deux méthodes à mettre en œuvre, engineCanResolveURI et engineResolveURI. Le premier vérifie si l'URI spécifié par addDocument peut être résolu par ce résolveur. Ce dernier est une méthode pour obtenir du contenu à partir de cet uri. Renvoie un objet appelé XMLSignatureInput.
 Je lance une ResourceResolverException lorsqu'une exception se produit, mais je ne sais pas comment la faire correctement. Le constructeur de code ici est obsolète.

```java
class MyResolver extends ResourceResolverSpi {
    @override
    public XMLSignatureInput engineResolveURI(ResourceResolverContext context) throws ResourceResolverException {
        val uri = context.attr.getValue();
        try {
            if (uri.equals("#elem2")) {
                val result = new XMLSignatureInput(new ByteArrayInputStream("<elemt2>xxx</elem2>".getBytes("utf-8")));
                result.setSourceURI(uri);
                result.setMIMEType("text/xml");

                return result;
            }
            if (uri.equals("somefile.txt")) {
                val result = new XMLSignatureInput(new ByteArrayInputStream(new FileInputStream(uri)));
                result.setSourceURI(uri);
                result.setMIMEType("application/octet-stream");
 
                return result;
            }
        } catch (Exception e) {
            throw new ResourceResolverException("generic.EmptyMessage", e, uri, context.baseUri);
        }
        return null;
    }

    @override
    public boolean engineCanResolveURI(ResourceResolverContext context) {
        val uri = context.attr.getValue();
        if (uri.equals("#elem2")) return true;
        if (uri.equals("somefile.txt")) return true;

        return false;
    }
}

5. Fin

Vous pouvez signer XML avec un code comme celui-ci. La signature XML est assez déroutante, mais il est assez facile de signer avec une bibliothèque. Cependant, il semble qu'il y ait peu de documents ...

Dewadewa

Recommended Posts

Signer XML à l'aide d'Apache Santuario
Traitement des données avec Apache Flink
J'ai essayé d'utiliser Apache Wicket
Sortie vers Excel en utilisant Apache POI!