IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Crypter/Décrypter un objet avec RSA.


Sujet :

Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2015
    Messages : 4
    Par défaut Crypter/Décrypter un objet avec RSA.
    Bonjour les amis,

    Étant sur notre projet de synthèse, nous sommes bloqués sur la première partie de celui-ci.

    Pour commencer, notre but était de construire un client/serveur.
    On considère que le serveur possède une paire de clé RSA et que le client possède la clé publique du serveur.

    Notre but dans une première étape était de :
    - créer un objet « login_mdp» en java qui contient deux String (login, mdp)coté client.
    - de crypter cet objet « login_mdp» avec la clé publique du serveur coté client
    - d’envoyer cet objet crypté du client au serveur
    - de décrypter d’objet coté serveur pour récupérer les deux String.

    Nous avons du mal à crypter et décrypter l’objet.
    Pouvez-vous nous aider à crypter et décrypter un objet.

    Merci de votre aide,

    Ci-dessous notre code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    //L'objet
    public class Login_MDP {
     
        String login = "Toto";
        String mdp = "Toto";
     
        public Login_MDP(String s1, String s2){
            this.login = s1;
            this.mdp = s2;
        }
     
        public String getlogin() {
            return login;
        }
     
        public String getmdp() {
            return mdp;
        }
     
    }
    Le main:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    public class Client {
        public static void main(String[] args) throws NoSuchAlgorithmException, Exception {
            KeyPair kp = generateRSAKeyPair(); //Création de la paire de clé, on considere que c'est la pair de clé du serveur.
            Login_MDP lm = new Login_MDP("Patate","Bouch"); //Notre objet
     
            /*
            Crypter notre objet lm avce la clé publique de kp (kp.getPublic())
            */
     
            /*
            Décrypter l'objet avec la clé privée de kp (kp.getPrivate())
            */
        }
     
        //Générateur de paire de clé RSA
        public static KeyPair generateRSAKeyPair() throws Exception {
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
            kpGen.initialize(512, new SecureRandom());
            return kpGen.generateKeyPair();
        }
     
        //fonction qui chiffrer une donnée avec une clé privée
        public static byte[] encrypt(PublicKey key, byte[] data) throws IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA"); 
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] text = cipher.doFinal(data);
            return text;
        }
     
        //fonction qui déchiffre une donnée avec une clé privée
        public static byte[] decrypt(PrivateKey key, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] text = cipher.doFinal(data);
            return text;
        }
    }

  2. #2
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 209
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 209
    Billets dans le blog
    52
    Par défaut
    Bonjour,

    Il t'est possible d'utiliser la stérilisation sur celui-ci.

    Pour savoir, comment faire de la sérialisation, regarde la FAQ Java et la javadoc (exemple de sérialisation) :
    http://java.developpez.com/faq/java/..._serialisation
    http://docs.oracle.com/javase/7/docs...ializable.html
    http://stackoverflow.com/questions/2...-to-byte-array

    Sinon, il t'est aussi possible de prendre chaque attribut et les transformer en [c]byte[][c] et de faire la somme de ceux-ci.

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 577
    Par défaut
    Citation Envoyé par kolodz Voir le message
    Il t'est possible d'utiliser la stérilisation sur celui-ci.
    Pour être sûr qu'il n'y ait plus de microbes qui espionnent ?

    La sérialisation peut marcher et, pour un expert, serait assez simple, je suppose. Mais deux choses me chiffonnent :
    - son contenu est plutôt prévisible. C'est souvent une mauvaise idée de fournir des données chiffrées dont n'importe qui connaît de gros bouts déchiffrés.
    - Pour les habitués je veux bien, mais pour ceux qui y auraient même pas pensé... C'est pas franchement plus simple que de faire soi-même une conversion en bytes.

    Suffirait par exemple de décider que le caractère NUL est interdit dans le login et donc que ça n'arrivera jamais (pas très restrictif comme condition.)
    On concatène le login, puis NUL, puis le mot de passe, et on obtient une String qui représente l'objet Login_MDP sans ambiguïté. Plus qu'à transformer en byte[] avec s.getBytes(StandardCharsets.UTF_8) et on obtient une représentation de l'objet sous forme de byte[], prête à être chiffrée.
    L'opération inverse n'est pas franchement compliquée. Au final ce me semble plus sûr et plus simple.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 209
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 209
    Billets dans le blog
    52
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Pour être sûr qu'il n'y ait plus de microbes qui espionnent ?

    La sérialisation peut marcher et, pour un expert, serait assez simple, je suppose. Mais deux choses me chiffonnent :
    - son contenu est plutôt prévisible. C'est souvent une mauvaise idée de fournir des données chiffrées dont n'importe qui connaît de gros bouts déchiffrés.
    - Pour les habitués je veux bien, mais pour ceux qui y auraient même pas pensé... C'est pas franchement plus simple que de faire soi-même une conversion en bytes.

    Suffirait par exemple de décider que le caractère NUL est interdit dans le login et donc que ça n'arrivera jamais (pas très restrictif comme condition.)
    On concatène le login, puis NUL, puis le mot de passe, et on obtient une String qui représente l'objet Login_MDP sans ambiguïté. Plus qu'à transformer en byte[] avec s.getBytes(StandardCharsets.UTF_8) et on obtient une représentation de l'objet sous forme de byte[], prête à être chiffrée.
    L'opération inverse n'est pas franchement compliquée. Au final ce me semble plus sûr et plus simple.
    Après, même si ton message est prévisible, la méthode de chiffrage peu compenser cela. L'une des solutions connu à l’unicité de l'encryptage, c'est ajouter un hash.
    Mais, je ne sais pas si cela entre dans la question initiale qui est de transformer un objet en un quelque chose de chiffrage.

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2015
    Messages : 4
    Par défaut
    Nous vous remercions pour vos réponses.
    Nous avons essayé la sérialisation comme vous nous avez conseillés et nous avons fait un test avec un objet appelé Person.

    Voici le code source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package serialize;
     
    import java.io.Serializable;
     
    public class Person implements Serializable {
     
        int age;
        String prenom;
     
        public Person(int age, String prenom) {
            this.age = age;
            this.prenom = prenom;
        }
     
        public int getAge() {
            return age;
        }
     
        public String getPrenom() {
            return prenom;
        }
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    package serialize;
     
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.security.InvalidKeyException;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.Security;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
     
    public class SerializePerson {
     
        static {
            Security.addProvider(new BouncyCastleProvider());
        }
     
        public static KeyPair generateRSAKeyPair() throws Exception {
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
            kpGen.initialize(512, new SecureRandom());
            return kpGen.generateKeyPair();
        }
     
        public static byte[] encrypt(PublicKey key, byte[] data) throws IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] text = cipher.doFinal(data);
            return text;
        }
     
        //fonction qui déchiffre une donnée avec une clé privée
        public static byte[] decrypt(PrivateKey key, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] text = cipher.doFinal(data);
            return text;
        }
     
        public static byte[] serialize(Person obj) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream(out);
            os.writeObject(obj);
            return out.toByteArray();
        }
     
        public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
            ByteArrayInputStream in = new ByteArrayInputStream(data);
            ObjectInputStream is = new ObjectInputStream(in);
            return is.readObject();
        }
     
        public static void main(String args[]) throws Exception {
     
            KeyPair kp = generateRSAKeyPair();
     
            Person person = new Person(12, "toto");
            byte[] ser = serialize(person);
            byte[] enc = encrypt(kp.getPublic(), ser);
     
            byte[] deser = decrypt(kp.getPrivate(), enc); 
            Object o = deserialize(deser);
            Person obj = (Person) o;
            System.out.println(obj.getPrenom());
     
        }
    }
    Et voici l'erreur qui apparait :
    Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 53 bytes
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2121)
    at serialize.SerializePerson.encrypt(SerializePerson.java:50)
    at serialize.SerializePerson.main(SerializePerson.java:90)

    Cependant ceci fonctionne avec une clé symetrique, nous avons trouvé cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public static void main(String args[]) throws Exception {
     
            String filename = "serial.txt";
            KeyPair kp = generateRSAKeyPair();
            SecretKey key64 = new SecretKeySpec(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, "Blowfish");
     
            Person person = new Person(12, "toto");
            Cipher cipher = Cipher.getInstance("Blowfish");
     
            cipher.init(Cipher.ENCRYPT_MODE, key64);
            //cipher.init(Cipher.ENCRYPT_MODE, kp.getPublic());
            SealedObject sealedObject = new SealedObject(person, cipher);
            CipherOutputStream cipherOutputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(filename)), cipher);
            ObjectOutputStream outputStream = new ObjectOutputStream(cipherOutputStream);
            outputStream.writeObject(sealedObject);
            outputStream.close();
     
            cipher.init(Cipher.DECRYPT_MODE, key64);
            CipherInputStream cipherInputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(filename)), cipher);
            ObjectInputStream inputStream = new ObjectInputStream(cipherInputStream);
            SealedObject sealedObject1 = (SealedObject) inputStream.readObject();
            Person person1 = (Person) sealedObject1.getObject(cipher);
            System.out.println(person1.getPrenom());
            System.out.println(person1.getAge());
     
        }
    Le code fonctionne mais lorsqu'on remplace la clé symétrique par une clé publique RSA, ceci met la même erreur que la précédente.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Le cryptage RSA (et d'autres cryptages assymétriques) sont limités à une taille de données similaire à la taille de la clé. Si tu veux encoder 1000bytes, il faut une clé de plus de 1000 bytes, etc. En général, on n'encrypte pas les données avec la clé publique. On encrypte les données avec un algorithme symétrique et un clé temporaire, qui n'a pas ce genre de limitation, et on encrypte la clé temporaire avec l'algorithme assymétrique. C'est pour ça qu'en général tu trouve des mentions du style RSA / AES. On encrypte avec une clé AES jetable, et on encrypte cette clé AES avec du RSA pour que le destinataire puisse la récupérer.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2015
    Messages : 4
    Par défaut
    D'accord.
    Merci beaucoup. Je clos donc la discussion.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2015
    Messages : 4
    Par défaut
    Bonjour,

    Tout d'abord, je vous remercie énormément de votre aide. (Je suis l'autre binôme du projet, on se partage un compte a deux! )

    Donc si j'ai bien compris, pour résumer:
    -On peut transformer un objet en tableau de byte (byte[]) par serialisation
    -On peut crypter le byte[] avec RSA (le byte[] ne doit pas dépassé la taille de la clé RSA)
    -Le byte[] crypté avec RSA peut aussi être un byte[]
    -On peut envoyer un byte[] du client au serveur

    Donc :
    -On crée l'objet,
    -On le sérialise pour avoir un byte_1[] (byte_1[] ne doit pas dépassé la taille de la clé RSA)
    -On crypte ce byte_1[] avec la clé privée (ou publique) RSA pour obtenir un autre byte_2[],
    -On envoie ce byte_2[] du client au serveur,
    -Le serveur récupère le byte_2[],
    -Le serveur décrypte ce byte_2[] avec la clé publique (ou privée) pour obtenir le byte_1[] initiale
    -On desérialise le byte_1[] pour obtenir l'objet

    Dans le cas ou on veut envoyer un objet dont la taille est très grande(donc la taille du byte[] après serialisation sera aussi très grande), on crée un clé symétrique temporaire qu'on envoie crypter par la clé RSA, et on utilise cette clé symétrique temporaire pour crypter l'objet.

    Notre raisonnement est elle correcte? Il y a t il des éléments qu'on a oublié de prendre en compte?

    Merci d'avance de vos réponse,

  9. #9
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 209
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 209
    Billets dans le blog
    52
    Par défaut
    Citation Envoyé par M2INFO Voir le message
    Bonjour,

    -On le sérialise pour avoir un byte_1[] (byte_1[] ne doit pas dépassé la taille de la clé RSA)
    Non, justement, c'est ce que t'explique tchize_ !
    Le cryptage RSA (et d'autres cryptages assymétriques) sont limités à une taille de données similaire à la taille de la clé. Si tu veux encoder 1000bytes, il faut une clé de plus de 1000 bytes, etc. En général, on n'encrypte pas les données avec la clé publique. On encrypte les données avec un algorithme symétrique et un clé temporaire, qui n'a pas ce genre de limitation, et on encrypte la clé temporaire avec l'algorithme assymétrique. C'est pour ça qu'en général tu trouve des mentions du style RSA / AES. On encrypte avec une clé AES jetable, et on encrypte cette clé AES avec du RSA pour que le destinataire puisse la récupérer.
    Si tu as une limite sur ton byte_1[], c'est que tu gère mal ton encryptage.
    Normalement, celui-ci peut-être d'une longueur n (supérieur à 0, c'est mieux) et peut contenir n'importe quels valeurs dans n'importe quel ordre.

    Pour les détails techniques par rapport à l'encryption, ce la fait un moment que j'en ai pas touché. Donc, je vais laisser tchize_ gérer cette partie technique si besoin.

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par M2INFO Voir le message
    -On peut crypter le byte[] avec RSA (le byte[] ne doit pas dépassé la taille de la clé RSA)
    On peut, mais ce n'est pas recommandé. Tout d'abord parce que cela nécessite de savoir à l'avance la taille des données sérialisées pour avoir une clé RSA qui corresponde. C'est très contraignant. Ensuite, parce que l'encryptage asymétrique est beaucoup plus lent que le symétrique, ce qui rend les chose peu praticables avec de grandes clés. En pratique, on couple presque toujours du symétrique avec de l'asymétrique, pour bénéficier des avantages des deux domaines: secret non partagé de l'asymétrique + performance et taille illimitée du symétrique.

Discussions similaires

  1. Crypter de "long" message avec du RSA ?
    Par Djobird dans le forum Sécurité
    Réponses: 2
    Dernier message: 27/01/2011, 22h53
  2. Crypter de décrypter des données avec Rijndael 256bits
    Par FredericB dans le forum C++Builder
    Réponses: 1
    Dernier message: 12/06/2008, 20h46
  3. [POO] Instancier un objet avec le nom de la classe
    Par shinchun dans le forum Langage
    Réponses: 4
    Dernier message: 08/06/2006, 13h44
  4. nommer un objet avec une variable
    Par fatcat dans le forum C++
    Réponses: 4
    Dernier message: 11/12/2005, 16h16
  5. A propos des modèles d'objet (avec sources)
    Par DevX dans le forum C++Builder
    Réponses: 14
    Dernier message: 01/12/2002, 12h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo