Vous êtes sur la page 1sur 32

Département Informatique

Master 2 E-Secure

Rapport de Projet Individuel


Signature de document XML

Etudiant : Frédéric Boussemard Année 2012-2013


Encadrant : Jacques Madelaine
Sommaire :

Introduction : .............................................................................................................................. 3
1. Présentation du sujet, état de l’art : .................................................................................... 4
1.1. Sujet du projet : .......................................................................................................... 4
1.2. Standard existant : ...................................................................................................... 4
1.3. Vue d’ensemble de la signature et vérification par XML Dsig : ............................... 5
1.4. Solutions existantes :.................................................................................................. 6
1.5. Solution retenue : ....................................................................................................... 6
2. Signature d’un document ................................................................................................... 7
2.1. Les trois formes de signature : ................................................................................... 7
2.2. Forger une signature en respectant XML Dsig : ........................................................ 8
2.3. Canonisation............................................................................................................. 10
2.4. Programmation de l’action de signature................................................................... 12
2.5. Résultat : signature d’un document XML ................................................................ 13
3. Vérification d’un document signé .................................................................................... 14
3.1. Vérifier une signature selon XML Dsig ................................................................... 14
3.2. Programmation de l’action de vérification............................................................... 15
4. Gestion des certificats ...................................................................................................... 16
4.1. Utilisation du Keystore / Truststore ......................................................................... 16
4.2. Génération du keystore et du truststore :.................................................................. 17
4.3. Validation d’un certificat : ....................................................................................... 17
5. Réalisation d’un prototype et tests ................................................................................... 19
5.1. Prototypage avec le framework Play........................................................................ 19
5.2. Tests ......................................................................................................................... 20
6. Evolutions possibles......................................................................................................... 20
6.1. Amélioration de la gestion des certificats ................................................................ 20
6.2. Complément à la canonisation : ............................................................................... 21
7. Conclusion........................................................................................................................ 21
8. Annexes : Annexe 1: Code Java de signe.class ............................................................. 22
Annexe 2: Code Java de valide.class ................................................................................... 25
Annexe 3: Code Java de TestCert.class ............................................................................... 28
Annexe 4: Lignes de commandes Keytool........................................................................... 31
Annexe 5: HTTPS configuration for play framework.......................................................... 32
Introduction
Le langage XML (eXtended Markup Langage) a été promu en version 1.0 par W3C
en 1998. Il s’ajoute à la famille des langages à balises (GML,HTML…). Les
possibilités de définition infinie d’objets l’ont rendu très populaire et XML est devenu
un standard universel pour la représentation et l’échange de données.

En standardisant la mise en forme des données à échanger, XML facilite les


échanges de données entre machines. Ces données véhiculant sur des réseaux
ouverts à plusieurs machines, il faut veiller à la sécurisation des contenus échangés.
La signature numérique avec authentification par certificat permet d’assurer :
- Authentification / Identification
Qui émet les données ? Peut il le prouver ?

- Intégrité
On est capable de savoir si les données reçues ont été modifiées.

- Non re-jeu
La signature est propre au document. Elle n’est pas valide pour d’autres
usages.

- Non répudiation d'un envoi :


Le document signé porte une empreinte de l’émetteur.

Le sujet de mon projet consiste à étudier les solutions disponibles et réaliser un


prototype capable de signer et valider des documents XML. Il faudra veiller à ce que
des documents ayant une écriture différente mais la même interprétation XML
obtiennent une signature identique.

J’ai choisi ce sujet dans un but d’apprentissage. Ne connaissant pas le langage XML
et n’ayant pas développé en langage objet, j’ai trouvé en ce projet une bonne
opportunité pour enrichir mes connaissances.
Enfin, le sujet devrait me permettre d’appliquer les outils de cryptographie abordés
en cours.
1. Présentation du sujet, état de l’art :
1.1. Sujet du projet :
La signature de document numérique utilisant des principes de cryptographie
asymétrique est un processus bien connu. Ces schémas considèrent généralement
le document comme une simple suite d'octets non structurée de taille quelconque et
produisent à l'aide de la clé secrète du signataire, une signature de quelques
centaines d'octets. Cette dernière doit être adjointe au document. On pourra ensuite
prouver son intégrité et son origine à l'aide d'une procédure de vérification utilisant la
clé publique du signataire.
Le problème est ici de signer des documents XML dont il est licite de modifier leur
présentation sans pour autant constituer un autre document XML au sens de la
norme. En effet, l'ordre d'écriture des sous éléments de même nom d'un élément ou
l'ordre d'apparition des attributs d'un élément dans sa balise ouvrante ne sont pas
significatifs. Il faut donc que la signature ne soit pas dépendante de ces ordres. Nous
souhaitons aussi pouvoir ajouter cette signature au document. De plus comme nous
voulons appliquer ce schéma à de « petits » documents, il faudra expérimenter des
schémas à bas coûts.

1.2. Standard existant :


W3C a émis une recommandation destinée à l’utilisation de signatures numériques
pour les documents XML. Il s’agit de la recommandation ‘XML Signature Syntax &
Processing’ aussi nommée XML Dsig1.
Les processus de génération et de validation de signature y sont détaillés.

Concernant la signature, XML Dsig s’appuie sur la souplesse du langage XML et


permet de « limiter » la signature à plusieurs parties d’un document.
Cela est utile dans le cas où l’on souhaite faire signer différentes parties d’un
document par différents utilisateurs.

<dossier medical>

<patient>
pat ient
...
</patient>
m edecin
<medecin>
...
</medecin>
Radiologue
<radio>
Scanner ...
</radio>
.....
pharm acien .....
.....
.....
laborat oire .....
d'analyse
</dossier medical>

Fig.1 : Multiples signataires d’un document


1
http://www.w3.org/TR/xmldsig-core
Il peut également être intéressant d’exclure de la signature des parties d’un
document signé. Considérons le cas de la transmission d’un formulaire signé que
doit remplir un utilisateur :
• la partie à compléter est exclue des données à signer
• L’utilisateur remplit la partie du formulaire qui lui est propre
Ainsi, la signature du document reste valide puisqu’elle ne tient volontairement pas
compte de la zone modifiée par l’utilisateur.

Les éléments obligatoires et optionnels faisant partie de la signature sont spécifiés


par la recommandation. L’essentiel des mécanismes et éléments de la signature sont
d’avantage détaillés dans le paragraphe 2.2.

Concernant la validation, XML Dsig définit également en détails les mécanismes à


mettre en œuvre. La validation est faite en deux phases : validation de la référence
puis de la signature. Nous traitons ce processus dans la partie 3.1.

1.3. Vue d’ensemble de la signature et vérification par XML


Dsig :

Fig.2 : Vue globale des processus de Signature et Validation


1.4. Solutions existantes :
L’implémentation de XML Dsig est disponible sous différentes formes.

Microsoft propose une version de SDK sous .net.


Egalement des groupes de travail se sont constitués dans le domaine « Libre ».
Différentes bibliothèques sont mises à dispositions, citons par exemple :
• JSR 105 API (Java XML Digital Signature)
• Apache XML Security Java
• IBM alphaWorks XML Security Suite
• XML Security C Library

1.5. Solution retenue :


Lors de la recherche de solutions existantes, la majorité des exemples et des
discussions de forums que j’ai trouvées sont basées sur l’utilisation de
bibliothèques Java.
La disponibilité de nombreux exemples m’ont permis de me mettre le pied à
l’étrier pour générer les premiers prototypes. En effet, j’ai pu partir de codes
sources existants, les comprendre et les modifier pour rapidement obtenir des
premiers résultats.

La bibliothèque Java XML Digital Signature est structurée en six paquets :


• javax.xml.crypto : contient les classes pour réaliser les opérations de
cryptographie (génération de la signature XML et chiffrage du code XML).
Contient également la classe KeySelector nécessaire à l’extraction de la
clé publique adéquate pour valider la signature.

• javax.xml.crypto.dsig : inclut les interfaces des éléments composants la


signature (SignedInfo, CanonicalizationMethod, SignatureMethod,
Reference, Transform, DigestMethod, …) excepté l’interface pour
concernant les informations relatives aux clés/ certificats. Contient
également la classe XMLSignatureFactory utilisée pour créer des objets de
type signature implémentant ces interfaces.
javax.xml.crypto.dsig.dom est la version pour traiter les objets DOM.

• javax.xml.crypto.dsig.keyinfo : Inclut les interfaces relative aux éléments


composant l’élément KeyInfo (KeyValue, X509Data,X509IssuerSerial,…).
Contient également la class permettant de forger les objets implémentant
ces interfaces.
javax.xml.crypto.dsig.keyinfo.dom est la version pour traiter les objets
DOM.

• javax.xml.crypto.dsig.spec : Interfaces et classes pour les paramètres


d’entrée des algorithmes utilisés pour le calcul de signature (hachage,
transformation et canonisation).

Des exemples de codes Java sont également fournis pour générer la signature et
la valider. Je me suis appuyé sur ces exemples que j’ai pu compléter.
2. Signature d’un document

2.1. Les trois formes de signature :

Suivant la position de la signature dans le document, on distingue trois cas :

• la signature 'enveloppée' (enveloped signature) : lorsque la signature est


enveloppée dans le document. Elle porte sur les données qui l'entourent
dans le reste du document.

• la signature 'enveloppante' (enveloping signature) : lorsque les données


signées forment un sous-élément de la signature

• la signature 'détachée' (detached signature) : lorsque la signature


concerne des ressources extérieures au document qui la contient.

Dans le cadre du projet, il s’agit de signer intégralement le document XML et d’y


joindre sa signature. Nous allons donc utiliser la signature enveloppée.
2.2. Forger une signature en respectant XML Dsig :

La recommandation XML Dsig permet de standardiser la construction et la


validation de signatures. Pour le projet, il m’a paru évident de respecter ces
recommandations adaptées à notre cas d’usage.
La signature intègre deux éléments obligatoires et des éléments optionnels.

Les éléments obligatoires sont :


• SignedInfo qui intègre lui-même ces trois éléments

o Élément SignedMethod : spécification de l’algorithme de signature à


appliquer.
Dans notre cas :
Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"

o Elément CanonalizationMethod : méthode à utiliser pour la


canonisation.
Dans notre cas : Algorithm="http://www.w3.org/2001/10/xml-exc-
c14n#WithComments"

o Élément Référence : (voir Fig.3)


 [ID de l'objet à signer]
Dans notre cas : URI= "" <=> l’intégralité du document lui-
même.
 [éléments de transformation] Transforms
exemple : Canonisation, XSLT, encodage, décodage, etc…
 DigestMethod : Algorithme utiliser pour calculer le condensé
Dans notre cas :
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"
 DigestValue : représente la valeur du condensé de l’objet
résultant des transformations décrites à l’objet à signer (le
condensé est calculé suivant la méthode DigestMethod ; encodé
en base64)
SignedInfo est canonisé en suivant la méthode décrite qu’il contient.

• SignatureValue représente la valeur calculée de la forme canonisée de


SignedInfo (suivant la méthode SignatureMethod). A noter que la signature
est calculée sur le condensé du document à signer et des éléments
décrivant ses paramètres propres.
Les éléments optionnels sont :

• [KeyInfo] : contient éléments qui vont permettre au destinataire de valider


le document signé. Peut contenir des clés , certificats, informations de
gestion de clés publiques.
• [Objets] : contient l’objet à signer, utile dans le cas de code de type MIME.
• [Manifest] : contient une liste d’éléments Référence à considérer lors de la
validation. Utile dans le cas de multiples signataires.
• [SignatureProperties] : informations complémentaires telles que tampon
date/heure ou numéro de série de l’équipement cryptographique physique
utilisé pour générer la signature.
Dans notre cas, nous utiliserons uniquement l’élément Keyinfo qui porte
les éléments permettant d’inclure un certificat X509.

Les éléments Reference et Signature sont les clés de voûtes de la génération de


signature et de sa validation. Il est important de bien en saisir le paramétrage utilisé
pour leurs constructions.
A cet effet, voilà le parallèle entre le code XML correspondant à l’élément référence
et l’algorithme conduisant à sa construction (Fig. 3).

Fig. 3 : l’élément Reference

Dans notre cas, on applique les transformations spécifiées à l’ensemble du


document lui-même (URI= " "). Le document transformé est ensuite considéré pour le
calcul du condensé en suivant la méthode définie.
Pour l’élément Signature, le parallèle entre le code XML correspondant et sa
construction est donné dans la figure ci-dessous (Fig. 4).

Fig. 4 : l’élément signature

2.3. Canonisation
Les algorithmes d’empreintes cryptographiques utilisés pour générer une signature
considèrent les données à signer au niveau binaire. Le moindre changement
entraîne un résultat complètement différent.

La transformation du document en sa forme canonique et en signant celle-ci, permet


de rendre la signature indépendante de différentes représentations XML ayant la
même signification (avec des limites).

Il existe un standard pour la canonisation des documents XML : canonical XML2.

2
http://www.w3.org/TR/xml-c14n
La canonisation c14n effectue principalement ces transformations :

o Suppression des espaces inutiles dans les balises

o Utilisation codage UTF-8 pour les caractères

o Tri lexicographique imposé sur attributs et déclarations des espaces de noms


de chaque élément

o Suppression éventuelle des commentaires

o Suppression des références DTD

o Normaliser l'ouverture et fermeture des balises

o Interprète les entités internes

Fig. 5 : exemple de transformations obtenues par c14n

Toutefois, c14n ne répond pas complètement à nos besoins. En effet, les opérations
de tri réalisées ne sont pas suffisantes. Le tri est effectué sur les attributs dans une
balise ouvrante est réalisé et vérifié. Par contre, le tri des éléments de mêmes noms
n’est pas réalisé. Il faudra donc ajouter une transformation complémentaire
consistant à effectuer ce tri en complément à c14n.
2.4. Programmation de l’action de signature
L’action Signature est remplie par la classe Signe.class (voir Annexe).
Les principales étapes de cette fonction sont décrites ci-dessous (la gestion des
exceptions n’est pas renseignée ici pour en alléger la représentation ; les
fonctions intégrées par la bibliothèque réalisent plusieurs opérations induites).

fichier XML d oc : Docum ent


Cr…at ion docum ent XML

Cr…at ion d'une fabriq ue de signat ure

Ref : Reference

D…finit ion du noeud Reference

Ref si : SignedInfo

D…finit ion du noeud SignedIn fo

fichier key st ore


kp:keypair
R…cup…rat ion de la paire d e cl…s
(Kpriv ,cert )

kp ki : KeyInfo

D…finit ion du noeud KeyInfo

signat ure

D…finit ion du noeud signat ure

si,ki dsc: Dom SignCont ext

D…finit ion du cont ext e de signat ure

doc , kp signed : Docum ent

g…n…rat ion de la signat ure

signed
fichier XML
Ecrit ure dans fichier XML

Fig. 6 : signe.class
2.5. Résultat : signature d’un document XML

Fig. 7 : exemple d’une signature


3. Vérification d’un document signé

3.1. Vérifier une signature selon XML Dsig


La validation s’effectue en trois principales phases :

• Valider le certificat (voir paragraphe 4).

• Vérifier la référence :

o Obtenir l’objet signé (URI fournie dans l'élément Reference)


o Appliquer les transformations à l’objet signé
o Condenser l’objet transformé par la méthode DigestMethod
o Comparer avec l'élément stocké DigestValue

• Valider la signature :

o Obtenir le certificat de keyInfo

o Canoniser SignedInfo par l'algo indiqué CanonalizationMethod

o Confirmer la valeur stockée dans SignatureValue sur l'élément


SignedInfo
3.2. Programmation de l’action de vérification
La vérification est effectuée par la classe Valide.class (voir Annexe).
Les principales étapes de cette fonction sont décrites ci-dessous.

Fig. 8 : valide.class
4. Gestion des certificats

4.1. Utilisation du Keystore / Truststore

Java permet de stocker des clés, paires de clés ou certificats dans des Keystore.
Ces entrées sont associées à un alias afin d’en faciliter la gestion pour les ranger,
utiliser, supprimer.

Signataire Recepteur

XML signé

(Kpriv_i,Cert_i) puis je faire confiance en cert_i ?

Certificats importé
dans le trustore

(Kpriv1,Cert1) Cert1
(Kpriv2,Cert2) Cert3
.... ...
(Kpriv-n,Cert_n) Cert_i
KEYSTORE Liste de TRUSTSTORE ....
révocation (Kpriv-n,Cert_n)

Fig. 9 : Architecture pour le keystore et le truststore

Le certificat du signataire est importé dans le truststore.

Pour la signature :
• Le signataire récupère sa paire de clés dans le keystore.
• Le chiffrement est réalisé avec sa clé privée.
• Son certificat est joint dans l’élément signature.

Pour la vérification :
• Le destinataire valide le certificat du signataire en consultant le
truststore et la liste de révocation.
• Dans le cas où le certificat est valide, le destinataire peut vérifier la
signature en utilisant la clé publique contenue dans le certificat.
4.2. Génération du keystore et du truststore :

Les principaux logiciels libres pour générer les paires de clés et certificats sont
OpenSSL et Keytool.

Keytool permet également l’interfaçage avec les keystore. Cela se fait en trois
étapes :
• Générer un Keystore Java et une paire de clef
• Exporter un certificat autosigné à partir de la clé publique
• Importer un certificat dans un truststore
Lignes de commandes et détails fournies dans l’Annexe 4.

4.3. Validation d’un certificat :

La validation du certificat est effectuée par la classe TestCert.class (voir Annexe).


Dans le cas où le certificat est valide, il faudra ensuite vérifier le document signé
grâce à la classe validate (cf paragraphe 3.2).

La récupération du certificat dans le document XML signé me pose des difficultés.


Je ne parviens pas à l’extraire correctement. Aussi, le prototype réalisé
n’embarque pas la vérification du certificat incluse dans le XML signé.
J’ai testé le bon fonctionnement de la vérification dans le cas où je récupère le
certificat à partir du fichier généré par Keytool.
Une piste serait d’extraire le certificat dans la même veine de ce qui est réalisé
pour l’extraction de la clé publique nécessaire à la validation de la signature.
Fig. 10 : TestCert.class
5. Réalisation d’un prototype et tests
5.1. Prototypage avec le framework Play

Afin d’améliorer la présentation d’un prototype de génération et de vérification de


signature, j’ai utilisé l’outil Play ! framework.
L’utilisation des classes Signe et Valide est ainsi rendue plus interactive. La
consultation d’une page web permet de configurer le fichier XML d’entrée à signer
ou vérifier.

Play permet une décomposition Modèle - Vue – Contrôleur.

La vue correspond à une page web en langage http dont le rendu est le suivant :

Fig. 11 : Interface web du prototype

Les classes Signe, Valide sont intégrées comme modèles.


Le contrôleur est codé en Java. Il assure l’interaction entre la vue et l’appel aux
modèles.
5.2. Tests
Les tests ont consisté à valider le bon fonctionnement des fonctions Signe et
Valide.

Pour les deux premiers cas, la signature remplit son rôle. Les altérations de données
ou la valeur de signature sont détectées : la vérification indique que la signature n’est
pas correcte.
A noter que la signature d’un même fichier réalisé plusieurs fois donnera une valeur
de signature différente dues à un aléa ajouté dans l’algorithme de chiffrement de
celle-ci. La vérification à l’aide de la clé publique commune correspondant confirme
que toutes ces valeurs sont correctes.
Enfin, les quatre derniers tests montrent l’efficacité de la canonisation c14n sauf dans
les cas d’apparition dans différents ordres des nœuds éléments. Il est nécessité de
compléter par une transformation de type tri d’éléments.

6. Evolutions possibles

6.1. Amélioration de la gestion des certificats

D’abord, il faudrait résoudre le problème que j’ai rencontré consistant à extraire le


certificat inclut dans le document XML (voir 4.3).
Enfin, pour vérifier le certificat de façon complète, il faut intégrer le contrôle de
liste de révocations. Cela suppose le chargement d’une liste de révocations et le
balayage de celle-ci lors pour le certificat testé.
6.2. Complément à la canonisation :

L’algorithme de canonisation ne tient pas compte de l’ordre d’apparition des


éléments de mêmes noms.
Il faut donc ajouter un algorithme de transformation supplémentaire pour trier les
éléments. Ce tri pourrait être réalisé par instanciation du document en objet DOM
puis balayage des différents niveaux de hiérarchie pour effectuer un tri des
éléments de mêmes noms.

7. Conclusion
L’objectif du projet est partiellement atteint. En effet, la signature et la vérification
fonctionnent. La réalisation d’un prototype via une page web est également
disponible et sera présenté lors de la soutenance. Toutefois, la transformation
consistant au tri des éléments (complément à la canonisation standard) n’a pas été
codée. Suite à la présentation à mi-parcours, j’ai préféré concentrer mon travail pour
inclure la couche de sécurisation d’échanges de données par l’utilisation de
certificats.
J’estime mon temps passé sur ce projet à un peu plus de soixante-dix heures. Mes
difficultés ont essentiellement résidé dans la programmation pour laquelle j’ai
consommé plus de 30% du temps.

Concernant les apports pédagogiques de ce projet, j’ai apprécié la richesse du sujet


et la possibilité qui m’a été donnée de choisir différentes voies d’études.
Là, je remercie Jacques Madelaine pour ses « Jeudi support » qui ont permis
d’améliorer ma compréhension de différents points et de passer certaines difficultés.

J’ai développé mes connaissances concernant le langage XML. Partant de zéro, cela
m’a paru simple de premier abord. Mais, de sorte à comprendre les transformations
opérées par la canonisation standard, il m’a fallu aller plus loin et d’avantage
comprendre des principes qui en font la richesse.
J’ai également découvert ce qu’offre Java pour le développement. Les bibliothèques
contiennent l’essentiel des composants nécessaires pour répondre aux besoins :
génération et vérification de signature, gestion des clés cryptographiques.
Mon travail a consisté pour l’essentiel à rechercher, comprendre et adapter ces
briques. D’avantage de temps m’aurait été nécessaire pour mieux maîtriser ce
langage et améliorer mon efficacité.
8. Annexes :

Annexe 1: Code Java de signe.class

public class Signe {

public static void main(String[] args) throws NoSuchAlgorithmException, KeyStoreException,


CertificateException, IOException {
String fichierOriginal = args[0];
String fichierSigne ="./FichierSigne.XML";

// Conversion du XML en document


Document doc = LectureXML(fichierOriginal);

// Genère le document signé


Document signed = signatureEnveloppe(doc);

// Sauvegarde le document signé en XML signé


EcritureXML(signed,fichierSigne);
}

/**
* signatureEnveloppe ouvre le fichier XML à signer, effectue sa canonisation,
* signe le fichier et créé un nouveau fichier signé
* NOTE a compléter avec transformation pour le tri d'éléments
*/
public static Document signatureEnveloppe(Document doc){
String fichierKeystore ="D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\keystore.jks";
String ks_keypair ="selfsigned";

try {
//Creation d'une factory signature
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

//définition du noeud Reference


Reference ref = fac.newReference("",
fac.newDigestMethod(DigestMethod.SHA1, null),

Collections.singletonList(fac.newTransform(Transform.ENVELOPED,
(TransformParameterSpec) null)),
null, null);
//Collections.singletonList(fac.newTransform(Transform.ENVELOPED,
(TransformParameterSpec) null)),

//Collections.singletonList(fac.newTransform(CanonicalizationMethod.EXCLUSIVE_WITH_CO
MMENTS,
// (C14NMethodParameterSpec) null))
//définition du noeud SignedInfo
SignedInfo si =
fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE_WITH_CO
MMENTS,
(C14NMethodParameterSpec)
null),fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),Collections.singletonList(ref));
//Creation du noeud KeyInfo contenant le certificat
//Chargement du KeyStore, Extraction de la clé priv et du certificat
char[] password1 = "pwd_ks".toCharArray();
char[] password2 = "pwd_kpriv".toCharArray();
KeyStore kstore = KeyStore.getInstance("JKS");
kstore.load(new FileInputStream(fichierKeystore), password1);
KeyPair kpair = getKeyPair(kstore, ks_keypair, password2);

// définition du noeud KeyInfo (qui contient le certificat)


KeyStore.PrivateKeyEntry keyEntry =(KeyStore.PrivateKeyEntry)
kstore.getEntry(ks_keypair,new KeyStore.PasswordProtection(password2));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
KeyInfoFactory kif = fac.getKeyInfoFactory();
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

//définition du noeud Signature


XMLSignature signature = fac.newXMLSignature(si, ki);

//Création du contexte de signature


DOMSignContext dsc = new DOMSignContext(kpair.getPrivate(),
doc.getDocumentElement());

//Signature du Document
signature.sign(dsc);

return doc;
} catch(Exception e){
e.printStackTrace();
}

return null;
}

/**
*Creation d'un Document à partir d'un fichier XML
*/
public static Document LectureXML(String FileInput){
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new FileInputStream(FileInput));
return doc;
}catch(Exception e){
e.printStackTrace();
}
return null;
}

/**
*Creation d'un fichier XML à partir d'un document
*/
public static void EcritureXML(Document doc,String FileOutput){
try {
OutputStream os;
if (FileOutput.length() !=0) {
os = new FileOutputStream(FileOutput);
} else {
os = System.out;
}

TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os));
}catch(Exception e){
e.printStackTrace();
}
}

public static KeyPair getKeyPair(KeyStore keystore, String alias, char[] password) {


try {
// Get private key
Key key = keystore.getKey(alias, password);
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);

// Get public key


PublicKey publicKey = cert.getPublicKey();

// Return a key pair


return new KeyPair(publicKey, (PrivateKey)key);
}
} catch (UnrecoverableKeyException e) {
} catch (NoSuchAlgorithmException e) {
} catch (KeyStoreException e) {
System.err.println("key error: " + e.getMessage());
e.printStackTrace();
}
return null;
}

}
Annexe 2: Code Java de valide.class
public class Validate {

//
// Synopsis: java Validate [document]
//
// where "document" is the name of a file containing the XML document
// to be validated.
//
public static void main(String[] args) throws Exception {

//Chargement du document à valider


DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new
FileInputStream(args[0]));

//Config du Truststore à considérer


//System.setProperty("javax.net.ssl.trustStore",
"D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\keystoreR.jks");
//System.out.println(System.getProperty("javax.net.ssl.trustStore"));

//Recherche des Certificats


NodeList nl1 = doc.getElementsByTagNameNS(XMLSignature.XMLNS,
"X509Certificate");
if (nl1.getLength() == 0) {
throw new Exception("Certificat X509 non trouvé");
}
//Conversion du certificat en String
StringWriter writer = new StringWriter();
Transformer transformer =
TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(nl1.item(0)), new StreamResult(writer));
String certString = writer.toString();
System.out.println(certString);
// voir http://www.sauronsoftware.it/projects/javabase64/manual.php
FileOutputStream fout = new
FileOutputStream("D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\mydomain2.crt");
try (ObjectOutputStream oos = new ObjectOutputStream(fout)) {
oos.writeObject(certString);
}

//Import du certificat
CertificateFactory cf = CertificateFactory.getInstance("X509");
// Certificate myCert2=cf.generateCertificate(
// // string encoded with default charset
// new ByteArrayInputStream(certString.getBytes())
// );
FileInputStream in = new
FileInputStream("D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\mydomain.crt");
Certificate myCert = cf.generateCertificate(in);

//Validation du certificat
valCert=TestCert(doc)

//Recherche des signatures


NodeList nl =
doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
throw new Exception("Cannot find Signature element");
}

//Creation d'un DOM XMLSignatureFactory qui va permettre d'extraire


//la signature du document XML
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

// Création du DOMValidateContext, spécification de KeySelector


DOMValidateContext valContext = new DOMValidateContext(new
Validate.X509KeySelector(), nl.item(0));

//Séparation(unmarshal) de la signature du XML


XMLSignature signature = fac.unmarshalXMLSignature(valContext);

//Validation de la signature
boolean valsig = signature.validate(valContext);

//Affichage du resultat de la validation


if (valsig == false) {
System.err.println("Signature défaillante");
} else {
System.out.println("Signature correcte");
}
}

private static class X509KeySelector extends KeySelector {


public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose,
AlgorithmMethod method,
XMLCryptoContext context)
throws KeySelectorException {
Iterator ki = keyInfo.getContent().iterator();
while (ki.hasNext()) {
XMLStructure info = (XMLStructure) ki.next();
if (!(info instanceof X509Data))
continue;
X509Data x509Data = (X509Data) info;
Iterator xi = x509Data.getContent().iterator();
while (xi.hasNext()) {
Object o = xi.next();
if (!(o instanceof X509Certificate))
continue;
final PublicKey key = ((X509Certificate)o).getPublicKey();
// Make sure the algorithm is compatible
// with the method.
if (algEquals(method.getAlgorithm(), key.getAlgorithm())) {
return new KeySelectorResult() {
public Key getKey() { return key; }
};
}
}
}
throw new KeySelectorException("No key found!");
}

static boolean algEquals(String algURI, String algName) {


if ((algName.equalsIgnoreCase("DSA") &&
algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) ||
(algName.equalsIgnoreCase("RSA") &&
algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1))) {
return true;
} else {
return false;
}
}

}
}
Annexe 3: Code Java de TestCert.class
//--- Valide le certificat contenu dans le document XML en se basant sur le truststore ----

public class TestCert {

public static void main(String[] args) throws FileNotFoundException,


ParserConfigurationException, SAXException, IOException, Exception {

//Chargement du document contenant le certificat


DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(args[0]));

//Import du Certificat
NodeList nl1 = doc.getElementsByTagName("X509Certificate");
if (nl1.getLength() == 0) {
throw new Exception("Certificat X509 non trouvé");
}
String certPart = nl1.item(0).getFirstChild().getNodeValue();
System.out.println(certPart);
InputStream is = new ByteArrayInputStream(certPart.getBytes());
// debug...
// voir http://www.sauronsoftware.it/projects/javabase64/manual.php
FileOutputStream fout = new
FileOutputStream("D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\mydomain2.crt");
try (ObjectOutputStream oos = new ObjectOutputStream(fout)) {
oos.writeObject(is);
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);

//Validité du certificat
try{
cert.checkValidity();
}
catch(CertificateExpiredException | CertificateNotYetValidException e){
System.out.println("Certificat non valide :"+ e.toString());
System.exit(0) ;
}

//Vérification du certificat par rapport au contenu truststore


// String CERTFILE =
"D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\mydomain.crt" ;
String KEYSTORE = "D:\\DATA\\DEVELOPPEMENT\\JAVA\\Essais\\truststore.ts"
;
if( !(new File(KEYSTORE)).exists())
{
System.out.println("Truststore non trouvé!") ;
System.exit(0) ;
}

try
{
//------ récupération du nom lié au certificat ------------------
// InputStream inStream = new FileInputStream(CERTFILE);
// CertificateFactory cf = CertificateFactory.getInstance("X.509");
// X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
// inStream.close();
String issuerdn = cert.getIssuerDN().getName() ;
// System.out.println("\nIssuerName:\r\n" + issuerdn) ;

// -- Verifie dans le Truststore du certificat correspondant, si trouve, vérification de la


signature du certificat ----
System.out.println("Recherche dans le Truststore du certificat correspondant...") ;
//Chargement du keystore
char[] pwd = "pwd_ts".toCharArray();
KeyStore keystore = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream(KEYSTORE) ;
keystore.load(fis, pwd);
fis.close();

Enumeration en = keystore.aliases();
String ALIAS = "" ;

boolean verCert = false;


while (en.hasMoreElements())
{
X509Certificate storecert = null;
String ali = (String)en.nextElement() ;
if(keystore.isCertificateEntry(ali))
{
storecert = (X509Certificate)keystore.getCertificate(ali);
if( (storecert.getIssuerDN().getName()).equals(issuerdn))
{
try{
System.out.println("Certificat trouvé dans le TrustStore,
validation en cours...") ;
cert.verify(storecert.getPublicKey()) ;
System.out.println("Cerfificat correct") ;
verCert = true;
break;
}
catch(Exception exc){
System.out.println("Certificat faux");
}
}
}
}

if(! verCert)
System.out.println("Certificat non valide");
}
catch (Exception e)
{
System.err.println("Caught exception " + e.toString());
}

}
Annexe 4: Lignes de commandes Keytool

• Générer un Keystore Java et une paire de clef


keytool -genkey -alias mydomain -keyalg RSA -validity 360 -keystore
keystore.jks

keystore.ks : contient 1 paire de clé d’alias « mydomain » , valide 360 jours


password du keystore : pwd_ks (idem pour la clé)

• Exporter un certificat autosigné à partir de la clé publique


correspondant à l’alias « mydomain »
keytool -export -keystore keystore.jks –storepass pwd_ks -alias mydomain -
rfc -file mydomain.crt

mydomain.crt:fichier contenant le certificate autosigné

• Importer un certificat dans un truststore


keytool -import -trustcacerts -alias mydomain -file mydomain.crt -keystore
truststore.jks

trustore.ts : contient 1 certificat trusted « mydomain »


password du truststore : pwd_ts (idem pour la clé)
Annexe 5: HTTPS configuration for play framework

The built-in server supports the HTTPS protocol, which you can use it in production.
It supports certificate management, either via the classical Java keystore or simple
cert and key files. To start an HTTPS connector for your application, just declare the
https.port configuration property in your application.conf file:

http.port=9000
https.port=9443

You need to put your certificates in the conf directory. Play supports X509 certificates
and keystore certificates. The X509 certificates must be named as follows:
host.cert for the certificate and host.key for the key. If you are using keystore, then,
by default it should be named certificate.jks.

If you are using X509 certificates, then the following parameters can be configured in
your application.conf file:

# X509 certificates
certificate.key.file=conf/host.key
certificate.file=conf/host.cert
# In case your key file is password protected
certificate.password=secret
trustmanager.algorithm=JKS

If you are using keystore:

keystore.algorithm=JKS
keystore.password=secret
keystore.file=conf/certificate.jks

Note that the values above are the default values.

You can generate self-signed certificates using openssl:

openssl genrsa 1024 > host.key


openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert

If you are using the Java keystore mechanism, then the following properties can be
configured in your application.conf file:

# Keystore
ssl.KeyManagerFactory.algorithm=SunX509
trustmanager.algorithm=JKS
keystore.password=secret
keystore.file=certificate.jks

The values above are the default values.