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

Sécurité Java Discussion :

Cryptage AES - Java & Javascript


Sujet :

Sécurité Java

  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut Cryptage AES - Java & Javascript
    Bonjour à tous,

    Je me tourne vers vous désespérément afin de trouver des réponses car je n'en peux plus de consulter des forums avec des bouts de réponses qui ne mènent à rien.

    Le principe est simple, je stocke sur une base de données de données cryptés, et je souhaite pouvoir les décrypter =)

    J'utilise CryptoJS en javascript pour encrypter les données avant de les envoyer sur le serveur, et j'ai un service java qui à besoin à un moment donnée de les décrypter ^^.

    Voici le code javascript je j'utilise et qui fonctionne dans les deux sens (crypte et décrypte) :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     var secret = 'phrase a crypter';
    	var key = 'cle';
    	console.log(key + "#");
     
    	// Entré : String Utf8
    	var test = CryptoJS.AES.encrypt(secret, key, { iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // Sortie : Base 64
    	// U2FsdGVkX1+3+hj2N4kPGJRZpeEG1+RQKAKxNahOCiwS1wtOGSe39NEq7FNmwED+
     
    	// Entré : String Base 64
    	var pass = CryptoJS.AES.decrypt(test, key, { iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // Sortie : String HEX
    	console.log(pass.toString(CryptoJS.enc.Utf8) + "#"); // On remet en String Utf8 pour le lire
     
    	// phrase a crypter -> =D
    Niquel je suis super content jusque là. Comme vous pouvez le voir,a fin de simplifier la démarche clé et initial vecteur sont identiques. D'après CryptoJS, c'est une clé de 256 bits qui est générée.

    On rentre dans le vif des problèmes, aucun code que j'ai pu trouver ou bidouillé ne fonctionnent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
                    Security.addProvider(new BouncyCastleProvider());
    		String plainPassword = "";
    		SecretKeySpec key = new SecretKeySpec("cle\0\0\0\0\0\0\0\0\0\0\0\0\0".getBytes(), "AES");
    		IvParameterSpec iv = new IvParameterSpec("cle\0\0\0\0\0\0\0\0\0\0\0\0\0".getBytes());
     
    		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
     
    		cipher.init(Cipher.DECRYPT_MODE, key, iv);
     
    		byte[] encoded = cipher.doFinal(Base64.decodeBase64("U2FsdGVkX1+3+hj2N4kPGJRZpeEG1+RQKAKxNahOCiwS1wtOGSe39NEq7FNmwED+".getBytes()));
    		plainPassword = new String(encoded);
    		System.out.println(plainPassword);
    J'ai une super erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Exception in thread "main" javax.crypto.BadPaddingException: pad block corrupted
    	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
    	at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    	at main.test.main(test.java:77)
    Voili, que dire de plus, j'ai fais attention a prendre les même encodace, padding, clé, iv mais rien n'y fait, je passe a côté de quelque chose.

    Merci d'avance à tous, si vous avez des questions, n'hésitez pas.

    A bientot

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    tu as essayé de décoder ton base64 avec la classe sun.misc.BASE64Decoder ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] encoded = cipher.doFinal(decoder.decodeBuffer("U2FsdGVkX1+3+hj2N4kPGJRZpeEG1+RQKAKxNahOCiwS1wtOGSe39NEq7FNmwED+"));
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    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
    C'est documenté ici:

    https://code.google.com/p/crypto-js/, section cipher output. Ce que tu obtiens, ce n'est pas la version cryptée du code, mais une structure au format open-ssl contenant toutes les informations de l'output. Il s'agit en fait d'un préfixe de 64 bits ("Salted__") suivi du salt (64 bits?) suivi de la clé, le tout ensuite passé à la moulinette base64.

    Donc tu base64.decode() ça, tu sépare préfixe, salt et données cryptée, tu initialise tout comme il faut dans java (ajout du salt dans l'algo de cryptage) et tu décode.

  4. #4
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Bonjour,

    Si c'est bien ça, je pouvais continuer à chercher Oo, j'avais pas du tout compris sa comme ça, en effet sa explique pas mal de choses.

    Je vais tester de splitter le tout et je vous ferais un retour dès que mes tests auront aboutis.

    Merci beaucoup de votre contribution.

  5. #5
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Re bonjour,

    J'ai relu toute la documentation et surtout sur le cipher output. Je comprends un peu mieux comment ils s'y sont pris. Toutefois, j'ai vraiment du mal a donner les informations à Java, a chaque fois, ce n'est pas au bon format et je ne parle meme pas des problèmes de taille de clé.

    J'ai suivis l'exemple sur CryptoJs et est gardé que les informations importantes :

    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
    var JsonFormatter = {
            stringify: function (cipherParams) {
                // create json object with ciphertext
                var jsonObj = {
                    ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)
                };
     
                // optionally add iv and salt
                if (cipherParams.iv) {
                    jsonObj.iv = cipherParams.iv.toString();
                }
                if (cipherParams.salt) {
                    jsonObj.s = cipherParams.salt.toString();
                }
     
                // stringify json object
                return JSON.stringify(jsonObj);
            },
     
            parse: function (jsonStr) {
                // parse json string
                var jsonObj = JSON.parse(jsonStr);
     
                // extract ciphertext from json object, and create cipher params object
                var cipherParams = CryptoJS.lib.CipherParams.create({
                    ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
                });
     
                // optionally extract iv and salt
                if (jsonObj.iv) {
                    cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv)
                }
                if (jsonObj.s) {
                    cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s)
                }
     
                return cipherParams;
            }
        };
     
        var encrypted = CryptoJS.AES.encrypt("mickaffdel", "cle", { format: JsonFormatter, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
    Ce qui me donne un Json comme cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {"ct":"xHNsNd/THByD5Wgg6UdlLQ==","iv":"98b33f6423fc8999f828067299f797a9","s":"e80987d41d610372"}
    En java, j'ai récupéré les informations et voila comment je l'ai exploitent :

    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
    String ct = "xHNsNd/THByD5Wgg6UdlLQ=="; // Base 64
    		String cl = "cle\0\0\0\0\0\0\0\0\0\0\0\0\0"; // Utf 128 bits
    		String iv = "98b33f6423fc8999f828067299f797a9"; // Hex 256 bits
    		String st = "e80987d41d610372"; // Hex 128 bits
     
    		Security.addProvider(new BouncyCastleProvider());
     
    		/* IV */
    		IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
     
    		/* KEY */
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    		KeySpec spec = new PBEKeySpec(cl.toCharArray(), st.getBytes(), 65536, 128);
    		SecretKey tmp = factory.generateSecret(spec);
    		SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
     
    		/* CIPHER */
    		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
    		cipher.init(Cipher.DECRYPT_MODE, secret, ips);
     
    		byte[] decoded_byte = cipher.doFinal(Base64.decodeBase64(ct.getBytes()));
    		String decoded_string = new String(decoded_byte);
    		System.out.println(decoded_string);
    Voila l'erreur que j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Exception in thread "main" java.security.InvalidAlgorithmParameterException: IV must be 16 bytes long.
    	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
    	at javax.crypto.Cipher.init(Cipher.java:1346)
    	at javax.crypto.Cipher.init(Cipher.java:1282)
    	at main.test.main(test.java:89)
    Je comprends bien le type d'erreur, je sais comment la contourner mais je ne peux pas modifier la taille de la clé. Je me demande si j'utilise bien la bonne manière de créer ma clé avec les informations que j'ai.

    Merci d'avance encore à tous.

  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
    tu dois convertir tes string iv et st en byte[] en parsant les charactères hexadecimaux. La tu transforme dans ton code pour le moment chaque caractère en un byte correspondant à son code ascii. Ce n'est pas bon.

  7. #7
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Je me disais bien que sa clochait, mais je sais que je bloque completement sur le jonglage entre hex, byte, base64, decimal...

    En tout cas, voici mon nouveau 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    byte[] json_byte = Base64.decodeBase64("eyJjdCI6InhITnNOZC9USEJ5RDVXZ2c2VWRsTFE9PSIsIml2IjoiOThiMzNmNjQyM2ZjODk5OWY4MjgwNjcyOTlmNzk3YTkiLCJzIjoiZTgwOTg3ZDQxZDYxMDM3MiJ9");
    		String json_string = new String(json_byte, "UTF-8");
    		System.out.println(json_string);
     
    		String ct = "xHNsNd/THByD5Wgg6UdlLQ=="; // Base 64
    		String cl = "cle\0\0\0\0\0\0\0\0\0\0\0\0\0"; // Utf 128 bits
    		String iv = "98b33f6423fc8999f828067299f797a9"; // Hex 256 bits
    		String st = "e80987d41d610372"; // Hex 128 bits
     
    		byte[] iv_byte = DatatypeConverter.parseHexBinary(iv);
    		byte[] st_byte = DatatypeConverter.parseHexBinary(st);
     
    		Security.addProvider(new BouncyCastleProvider());
     
    		/* IV */
    		IvParameterSpec ips = new IvParameterSpec(iv_byte);
     
    		/* KEY */
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    		KeySpec spec = new PBEKeySpec(cl.toCharArray(), st_byte, 65536, 128);
    		SecretKey tmp = factory.generateSecret(spec);
    		SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
     
    		/* CIPHER */
    		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
    		cipher.init(Cipher.DECRYPT_MODE, secret, ips);
     
    		byte[] decoded_byte = cipher.doFinal(Base64.decodeBase64(ct.getBytes()));
    		String decoded_string = new String(decoded_byte);
    		System.out.println(decoded_string);
    Et avec ce nouveau code, nouvelle erreur, que j'ai deja eu dans le passé lorsque la taille de mes clés étaient bonnes, et j'avoue que ce message d'erreur est pour le moins, pas très explicite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Exception in thread "main" javax.crypto.BadPaddingException: pad block corrupted
    	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
    	at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    	at main.test.main(test.java:97)
    Si sa dit quelque chose a quelqu'un ^^ En tout cas merci encore, je s'en qu'on avance et c'est déjà un grand bon en avant

  8. #8
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Bonjour,

    C'est lors du décodage du padding que ça foire.
    Car dans le cas du PCKS#7 on sais que s'il reste 3 bytes à remplir par exemple, la valeur du remplissage sera 3. Dans ton cas l'algo détecte un problème de cohérence sur cette règle simple.
    Tu es sûr de ta clé ? Car là dans le code tu en génères une nouvelle il me semble. Si tu décodes pas avec la clé qui a servit à chiffrer, ça va pas marcher.

    Sinon il faut générer ton iv avec un objet SecureRandom, car un iv fixe est une faille potentiel au niveau de la sécurité, car deux messages identiques seront chiffrés pareil.

  9. #9
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Bonjour,

    Si tu décodes pas avec la clé qui a servit à chiffrer, ça va pas marcher.
    Je n'ai pas codé les données avec Java, je dois donc utilisé les informations fournis par mon appli en javascript et réussir a décrypter.

    Je dois sembler un peu "naze" mais j'ai du mal a comprendre comment sa peut etre aussi compliquer de décrypter le message avec toutes les informations :

    String ct = "xHNsNd/THByD5Wgg6UdlLQ=="; // Base 64
    String iv = "98b33f6423fc8999f828067299f797a9"; // Hex 256 bits
    String st = "e80987d41d610372"; // Hex 128 bits
    A partir de la, je veux juste obtenir le "password" crypté à l'aide de AES-CBC-PCKSPadding7

    A priorie, je n'ai besoin de rien généré, juste j'utilise les infos ci-dessus et l'utilisateur met sa clé :
    String cl = "cle\0\0\0\0\0\0\0\0\0\0\0\0\0"; // Utf 128 bits
    Et Tada =) sauf que pas Tada pour le moment ^^ Sinon coté client, mon javascript genere bien des pass différents pour un meme string en entrée. La je veux juste le décrypter pour le moment.

    Voili, sinon peut etre au niveau de la clé, car sur cryptoJs ils disent que c'est une clé de 256 bits qui est généré, hors la j'ai une clé de 128bits (16 bytes).

    A bientot

  10. #10
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Je dois sembler un peu "naze" mais j'ai du mal a comprendre comment sa peut etre aussi compliquer de décrypter le message avec toutes les informations
    La sécurité c'est pas simple et heureusement il y a tellement de pièges que même les experts se trompent.


    J'avais pas vu ce passage, c'est ça qui ne va pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* KEY */
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    Tu re-fabriques ta clé avec un autre algo, c'est ça la source du problème.

  11. #11
    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
    Cet exampel sera peu être plus simple à suivre pour toi:
    http://tips4all.net/how-to-use-bounc...s-and-pbe.html

    @Jimmy: ce n'est pas une raison pour ne pas créer des APIs simple. Plus les apis sont complexe, plus on risque de se tromper et de mettre en cause la sécurité de l'application. Une sécurité robuste est aussi une sécurité facile à controller. Et de ce coté là, les APIs java ont encore du boulot je trouve

  12. #12
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Citation Envoyé par tchize_ Voir le message

    @Jimmy: ce n'est pas une raison pour ne pas créer des APIs simple. Plus les apis sont complexe, plus on risque de se tromper et de mettre en cause la sécurité de l'application. Une sécurité robuste est aussi une sécurité facile à controller. Et de ce coté là, les APIs java ont encore du boulot je trouve

    Le problème avec AES et les algos de chiffrement symétrique par exemple, c'est que non seulement il te faut bien utilisé l'API, mais en plus si ton IV, ton mode opératoire et ton padding ne sont pas adapté , tu vas créer des failles.

    Alors expliquer toutes les notions qu'il y a derrière le padding ou le mode opératoire, ça se maitrise pas en 5 minutes. Aussi je pense que les API de sécurité en java sont bien, car assez hermétique pour n'être utilisé que par des spécialistes.

  13. #13
    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
    LA sécurité par l'obscurité que tu indique n'est pas non plus acceptable.

  14. #14
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    LA sécurité par l'obscurité que tu indique n'est pas non plus acceptable.
    Ce n'est pas obscure du tout, il faut simplement savoir manipuler des notions complexes pour faire correctement le travail.
    Impossible d'avoir une API 'user friendly' qui fait tout le boulot a ta place ou qui choisi pour toi un mode opératoire ou qui affecte un IV sans te le dire. La pour le coup ça ne serait pas acceptable.

    La sécurité telle que nous la connaissons en informatique est complexe car c'est une disciple très avancée et même considérée comme une arme de guerre.

    Tout ça pour dire , oui l'API java est hermétique, mais c'est un mal nécessaire.

  15. #15
    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
    non je suis désolé. Que le choix des paramètres soit important j'en convie, mais qu'il faille créer autant d'objet dans des classes que je trouve mal documentée, ca n'aboutis qu'à une chose: le copier / coller de code qu'on sais pas trop comment ça marche trouvé sur des forums. Faudra m'expliquer pourquoi java a une api aussi complexe alors que des tonnes d'autres librairies fournissent des api plus claire avec des exemple simples et robustes?

    L'api de crypto est une de ces nobmreuses libraires en java qui ont été créée pour servir de couteau suisse à plein de provider différents qui ont tous des fonctionnements différents ce qui abouti à un truc que je trouve infame

  16. #16
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Bienvenue dans les méandres du Jcp ou tout le monde pense avoir la bonne implémentation des algos ...
    Quand tu colles IBM, Sony etc ... à coté de GNU et Apache voilà le résultat ...


  17. #17
    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
    je ne suis pas sur que l'api de crypto sorte du JCP, elle est vieille

  18. #18
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Re re re bonjour =)

    Désolé pour cette polémique ^^ ce n'était pas le but.

    Quoi qu'il en soit j'y ai bien cru cette fois avec ce petit exemple sur internet.

    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
    	public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeySpecException, UnsupportedEncodingException, InvalidAlgorithmParameterException, DataLengthException, IllegalStateException, InvalidCipherTextException
    	{
    		byte[] json_byte = Base64.decodeBase64("eyJjdCI6InhITnNOZC9USEJ5RDVXZ2c2VWRsTFE9PSIsIml2IjoiOThiMzNmNjQyM2ZjODk5OWY4MjgwNjcyOTlmNzk3YTkiLCJzIjoiZTgwOTg3ZDQxZDYxMDM3MiJ9");
    		String json_string = new String(json_byte, "UTF-8");
    		System.out.println(json_string);
     
    		String ct = "xHNsNd/THByD5Wgg6UdlLQ=="; // Base 64
    		String cl = "cle"; 
    		String iv = "98b33f6423fc8999f828067299f797a9"; // Hex 256 bits
    		String st = "e80987d41d610372"; // Hex 128 bits
     
    		byte[] iv_byte = DatatypeConverter.parseHexBinary(iv);
    		byte[] st_byte = DatatypeConverter.parseHexBinary(st);
     
    		Security.addProvider(new BouncyCastleProvider());
     
    		byte[] result = decrypt(Base64.decodeBase64(ct.getBytes()), cl.getBytes(), st_byte);
    		System.out.println(new String(result));
    	}
     
    	private static byte[] decrypt(byte[] cipherText, byte[] password, byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException
    	{
    	    BlockCipher engine = new AESEngine();
    	    CBCBlockCipher cipher = new CBCBlockCipher(engine);
     
    	    PKCS5S1ParametersGenerator keyGenerator = new PKCS5S1ParametersGenerator(new SHA256Digest());
    	    keyGenerator.init(password, salt, 20);
     
    	    CipherParameters keyParams = keyGenerator.generateDerivedParameters(256);
    	    cipher.init(false, keyParams);
     
    	    byte[] decryptedBytes = new byte[cipherText.length];
    	    int numBytesCopied = cipher.processBlock(cipherText, 0, decryptedBytes, 0);
    	    return decryptedBytes;
    	}
    Sa semble plus digeste, mais je constate qu'a aucun endroit :
    * L'IV n'est demande
    * Le padding

    J'obtiens quand meme un résultat : tEõ§õ{Þ£mD‘Ø'#

    Je me rappelle pas avoir mis sa en entrée =D

    Mais bon, j'en découvre toujours un peu plus, mais aucune des méthodes ne se ressemblent, c'est vraiment dur de recoller les bouts de réponses : un pas en avant, un pas en arrière...

    Merci à tous en tout cas, je reste tout ouïe.

  19. #19
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Revenons à nos moutons.

    La tu t'attaques directement à l'API Bouncy Castle on s'écarte de ce que tu veux faire.

    Comme déjà dit, ce qui ne va pas c'est ce boût de code : je suppose qu'il n'y a pas l'équivalent du coté javascript.

    Remplace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    		/* KEY */
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    		KeySpec spec = new PBEKeySpec(cl.toCharArray(), st.getBytes(), 65536, 128);
    		SecretKey tmp = factory.generateSecret(spec);
    		SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
    par un truc du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            byte raw[] = secretKey.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, algorithm);
    puisque dans ton exemple ta clé est en clair.

    Ensuite on verra pour mettre ta clé dans une structure protégé par un mot de passe comme tu sembles vouloir le faire.

    En principe dans le web on ne procède pas de cette manière, on utilise le protocole SSL qui est bien de plus sûr.
    Un algorithme asymétrique protégeant la clé symétrique utilisé pour la session.

  20. #20
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Par défaut
    Bonjour,

    En effet, la difficulté est de trouver l'équivalent en Javascript, quoi que finalement le code jaavscript me retourne toutes les informations pour décrypter le mot de passe.

    Jusqu'à présent je vous ai présenté la clé version "claire", mais en effet, le code avascript retourne une clé généré a partir de la clé claire et du salt.

    Et pour cause, le problème ne vient pas du jaavscript, une API SOLIDE du C# me décrypte (j'ai mis 15min pour trouver) le mot de passe :
    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
                String ct = "hyFSpYiHtFaWqcqI6OtnKwVVywQKF77l6m+z3MkDiNWRXoBDc0TzY7avGg4t6eaC"; // Base 64
                String iv = "124e0a752a8d83d827273f0ddcc6ccc9"; // Hex 256 bits
                String st = "1885272f8527e341"; // Hex 128 bits
     
    // clé donné par Javascript
                String cl = "19e07b16c18910e7d6e831788aafd384bc2cc09fe3afd88819afc5278e90c3a4";
     
                AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
                aesProvider.BlockSize = 128;
                aesProvider.KeySize = 256;
                aesProvider.Key = StringToByteArray(cl);
                aesProvider.IV = StringToByteArray(iv);
                aesProvider.Padding = PaddingMode.PKCS7;
                aesProvider.Mode = CipherMode.CBC;
     
                string plaintext = null;
                Byte[] bytes = Convert.FromBase64String(ct);
     
                ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
     
     
                using (MemoryStream msDecrypt = new MemoryStream(bytes))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, cryptoTransform, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
     
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
     
                Console.WriteLine(plaintext);
                Console.ReadKey();
    Il ne me reste plus qu'a retrouver la clé crypté en fonction de la clé claire, mais sa c'est pas la mort avec un peu de recherche.

    On en revient à notre Java, avec la modification demandé, on se retrouve avec un probleme de taille de clé :

    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
    String ct = "hyFSpYiHtFaWqcqI6OtnKwVVywQKF77l6m+z3MkDiNWRXoBDc0TzY7avGg4t6eaC"; // Base 64
    		String cl = "19e07b16c18910e7d6e831788aafd384bc2cc09fe3afd88819afc5278e90c3a4";
    		//String cle = "cle\0\0\0\0\0\0\0\0\0\0\0\0\0";
    		String iv = "124e0a752a8d83d827273f0ddcc6ccc9"; // Hex 256 bits
    		String st = "1885272f8527e341"; // Hex 128 bits
     
     
    		byte[] iv_byte = DatatypeConverter.parseHexBinary(iv);
    		byte[] cl_byte = DatatypeConverter.parseHexBinary(cl);
    		byte[] st_byte = DatatypeConverter.parseHexBinary(st);
     
    		Security.addProvider(new BouncyCastleProvider());
     
    		/* IV */
    		IvParameterSpec ips = new IvParameterSpec(iv_byte);
     
    		/* KEY */
            SecretKeySpec secret = new SecretKeySpec(cl_byte, "AES");
     
    		/* CIPHER */
    		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
    		cipher.init(Cipher.DECRYPT_MODE, secret, ips);
     
    		byte[] decoded_byte = cipher.doFinal(Base64.decodeBase64(ct.getBytes()));
    		String decoded_string = new String(decoded_byte);
    		System.out.println(decoded_string);
    >> Illegal key size

    En principe dans le web on ne procède pas de cette manière, on utilise le protocole SSL qui est bien de plus sûr.
    J'utilise déjà le SSL pour le transfert sécurisé entre serveur et client. Mais je ne fais pas les choses a moitié, je tiens à ce que les données enregistrés sur les clients et serveurs ne soient pas lisible. Si un "hacker" récupère la BDD ou un fichier de conf de l'appli Java, je ne veux pas qu'il arrive à lire les données en clair.

    Les données sont en gros crypté sur le serveur, le client les récupère à l'aide du SSL (qui est juste un plus) les décrypte pour la lecture et les réencrypte en local lorsqu'elle s'éteint afin de concerver certaines données (offline). Je m'écarte de certaines contraintes et responsabilité en cryptant de mon coté les données coté BDD. Bref tout sa pour dire, le SSL ne me suffit pas ^^

    Voili, j'espère qu'on trouvera un jour, c'est déconcertant le nombre de ligne en C# quand même.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [PHP 5.4] Cryptage AES <-> Java / PHP
    Par karistote dans le forum Langage
    Réponses: 1
    Dernier message: 22/10/2014, 09h26
  2. [Applet] appel de methodes java en javascript
    Par soulhouf dans le forum Applets
    Réponses: 16
    Dernier message: 06/09/2005, 14h18
  3. Variable Java dans JavaScript
    Par blaiseac dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 01/12/2004, 14h09
  4. [Crypto] Besoin d'aide de cryptage en java
    Par djyb2003 dans le forum Sécurité
    Réponses: 3
    Dernier message: 08/03/2004, 18h13

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