Affichage des articles dont le libellé est securite. Afficher tous les articles
Affichage des articles dont le libellé est securite. Afficher tous les articles

mardi 5 août 2008

Howto crypt / uncrypt using JAVA and RSA keys

Problématique :

Dans le cadre d'un bus de données nous souhaitons sécuriser les données en transit. Comme il s'agit d'un bus de transfert asynchrone, lorsque des messages sont stockés sur les files JMS il doivent également être crypté pour n'apparaitre en clair qu'au consommateur. Il n'est pas possible de se servir de SSL puisque le cryptage ne concerne pas que les phase de transport.

Nous allons réaliser le cryptage au niveau des producteurs et consommateurs du bus en nous servant des fonctionnalités venant avec le JDK 5,0.

La principale limitation dans le cryptage JAVA vient de la profusion des différents formats. Pour ce faire nous allons nous servir d'un cryptage à partir de clé publique/clé privée.

La génération des fichiers clé privée et clé publique se fait à l'aide de openssh.


openssl genrsa -aes256 -out /public/cleprivee.pem 2048
openssl rsa -in /public/private.pem -pubout -outform DER -out clepublique.der
openssl pkcs8 -topk8 -inform PEM -in /public/cleprivee.pem -outform DER -nocrypt -out /public/cleprivee.pk8


Le format PK8 est le seul disponible nativement en JAVA, il sert pour la lecture des clés privées


Le format DER est supporté pour les clé publique en JAVA, il sert pour la lecture des clés publique.


Le code suivant crypte et décrypte un message « Mon Cul C'est du poulet » à partir d'une clé publique et privée lue sur dans des fichiers :




// Lecture du fichier de clé publique
File keyFile = new File("clepublique.der");
byte[] encodedKey = new byte[(int) keyFile.length()];
new FileInputStream(keyFile).read(encodedKey);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);

// Encryptage à l'aide de la clé publique
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pk);
byte[] cypherText = cipher.doFinal("Mon Cul C'est du poulet"
.getBytes("UTF8"));

// Affichage du résultat du cryptage
System.out.println("----- Bytes cryptés --------");
System.out.write(cypherText);
System.out.println();
System.out.println("----------------------------");

// Lecture de la clé privée
keyFile = new File("cleprivee.pk8");
encodedKey = new byte[(int) keyFile.length()];
new FileInputStream(keyFile).read(encodedKey);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey);
PrivateKey privateKey = (RSAPrivateKey) kf
.generatePrivate(privateKeySpec);
cipher.init(Cipher.DECRYPT_MODE, privateKey);

// Affichage du résultat décrypté
System.out.println("----- Bytes décryptés ------");
byte[] clearText = cipher.doFinal(cypherText);
System.out.write(clearText);
System.out.println();
System.out.println("----------------------------");



Ce code ne fonctionne pas quand les données sont trop longue car elle dépasse la taille de la clé. Dans ce cas pour des raison de performances, il vaut mieux utiliser des cryptage symétrique à l'aide de mot de passe. Le code qui suit en donne un illustration.

/** Le chiffreur */
Cipher cipher;

/** La cle de cryptage */
SecretKey secretKey;

public void init(String password) throws Exception {
cipher = Cipher.getInstance("DES");
keyFactory = SecretKeyFactory.getInstance("DES");
DESKeySpec privateKeySpec = new DESKeySpec(password.getBytes());
secretKey = keyFactory.generateSecret(privateKeySpec);
}

/**
* Crypte les données
*
* @return
* @throws Exception
*/

public byte[] encrypt(byte[] aCrypter) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(aCrypter);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
CipherOutputStream cis = new CipherOutputStream(baos, cipher);
byte[] buffer = new byte[1024];
int read;
while ((read = bais.read(buffer)) != -1) {
byte[] buffer2 = cipher.update(buffer, 0, read);
baos.write(buffer2);
}
baos.write(cipher.doFinal());
buffer = baos.toByteArray();
return buffer;
}
/**
* Décrypte les données
*
*/

public byte[] decrypt(byte[] aDecripter) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(aDecripter);
cipher.init(Cipher.DECRYPT_MODE, secretKey);

byte[] buffer = new byte[1024];
int read;
while ((read = bais.read(buffer)) != -1) {
byte[] buffer2 = cipher.update(buffer, 0, read);
baos.write(buffer2);
}
baos.write(cipher.doFinal());
buffer = baos.toByteArray();
return buffer;
}

vendredi 27 juin 2008

Sécuriser un service Axis2 avec des certificats

Pour sécuriser un service par une authentification basé sur certificat.


Il faut d'abord créer les magasin de clés pour le serveur et le client. Ces clés serviront pour authentifier les partis.

Ensuite, le serveur fournit un certificat pour le client, il faut considérer ce certificat comme une autorisation de se connecter au serveur (C'est pour cette raison qu'elle doit provenir du serveur). Ensuite, le client l'importe dans son magasin. Ces commandes se passent à laide de keytool.


keytool -genkey -alias serverkey -keystore keystoreserver.jks
keytool -genkey -alias clientkey -keystore keystoreclient.jks
keytool -selfcert -alias serverkey -keystore keystoreserver.jks
keytool -export -alias serverkey -keystore keystoreserver.jks>moncertif
keytool -printcert -file moncertif
keytool -import -keystore keystoreclient.jks -file moncertif


Il ne reste plus qu'à configurer axis2. Copier d'abord, le magasin de clé (keystore du serveur dans le répertoire classes/ de Axis2). Puis, dans le fichier conf/axis2.xml. Modifier les receiver et sender. Dans notre configuration le truststore est confondu avec le keystore. Si le besoin existait de les séparer le truststore doit contenir le certificat importé et le keystore, la clé de signature du serveur.


  <transportReceiver name="https" class="org.apache.axis2.transport.nhttp.HttpCoreNIOSSLListener">
<parameter name="port" locked="false">9002</parameter>
<parameter name="non-blocking" locked="false">true</parameter>
<parameter name="keystore" locked="false">
<KeyStore>
<Location>keystoreserver.jks</Location>
<Type>JKS</Type>
<Password>axis2rules</Password>
<KeyPassword>axis2rules</KeyPassword>
</KeyStore>
</parameter>
<!--parameter name="truststore" locked="false">
<TrustStore>
<Location>keystoreserver.jks</Location>
<Type>JKS</Type>
<Password>axis2rules</Password>
</TrustStore>
</parameter-->
<!--<parameter name="SSLVerifyClient">require</parameter>
supports optional|require or defaults to none -->
</transportReceiver>



    <transportSender name="https" class="org.apache.axis2.transport.nhttp.HttpCoreNIOSSLSender">
<parameter name="non-blocking" locked="false">true</parameter>
<parameter name="keystore" locked="false">
<KeyStore>
<Location>keystoreserver.jks</Location>
<Type>JKS</Type>
<Password>axis2rules</Password>
<KeyPassword>axis2rules</KeyPassword>
</KeyStore>
</parameter>
<parameter name="truststore" locked="false">
<TrustStore>
<Location>keystoreserver.jks</Location>
<Type>JKS</Type>
<Password>axis2rules</Password>
</TrustStore>
</parameter>
<!--<parameter name="HostnameVerifier">DefaultAndLocalhost</parameter>
supports Strict|AllowAll|DefaultAndLocalhost or the default if none specified -->
</transportSender>



Enfin, il faut en fait rajouter deux lignes dans le code client :

System.setProperty("javax.net.ssl.trustStore", "chemin au clientTruststore");
System.setProperty("javax.net.ssl.trustStorePassword", "mot de passe du clientTruststore");

mardi 1 avril 2008

Modifier le niveau de securité sur Mandriva

Ayant installé Mandriva 2008, je me suis retrouvé avec un niveau de sécurité trop élevé pour mes besoins (4).

Concrétement, les répertoire home changeais constamment de droits de sorte qu'il n'était pas possible à plusieurs utilisateur de se lire les fichiers

Pour y remédier le commande :
msec -o log=stderr 2 

effectue le changement de niveau.

Ces informations sont stockée dans le fichier /etc/sysconfig/msec

UMASK_ROOT=022 (Donne les droit d'accès du repertoire root)
SECURE_LEVEL=3 (Donne le niveau de sécurité)
UMASK_USER=022 (Donne les droit d'accès des répertoire utilisateur)
TMOUT=0



msec est lancé quotidiennement, on le trouve dans /etc/cron.daily

http://club.mandriva.com/xwiki/bin/view/KB/SecureSmsec2?language=fr#HQuelniveaudesC3A9curitC3A9choisir3F