11
votes

Est-ce que ce fil de cryptage Java est-il sûr?

Je souhaite utiliser le code suivant pour une application de concurrence élevée dans laquelle certaines données doivent être cryptées et déchiffrées. J'ai donc besoin de savoir quelle partie de ce code doit être synchronisé, le cas échéant, pour éviter des problèmes imprévisibles.

   public String encrypt(String str) {
        try {
            // Encode the string into bytes using utf-8
            byte[] utf8 = str.getBytes("UTF8");
            // Encrypt
            //new cipher instance
            ecipher = Cipher.getInstance(key.getAlgorithm());

            byte[] enc = ecipher.doFinal(utf8);
            // Encode bytes to base64 to get a string
            return new sun.misc.BASE64Encoder().encode(enc);

        } catch (...)


0 commentaires

3 Réponses :


13
votes

La règle standard est - à moins que le Javadoc indique explicitement qu'une classe des bibliothèques Java est thread-coffre-fort, vous devriez supposer que ce n'est pas.

Dans ce cas particulier:

  • Les différentes classes ne sont pas documentées comme du fil de sécurité.
  • Le cipher.getinstance (...) et SecretKeyFactory.getinstance (...) sont documentés comme retournant de nouveaux objets; C'est-à-dire que non des références aux objets existants que d'autres threads pourraient avoir des références.

    update - le Javadoc dit ceci:

    "Un nouvel objet SecretKeyCactory encapsulant l'implémentation SecretKeyFactorySpiPI à partir du premier fournisseur prenant en charge l'algorithme spécifié est renvoyé."

    En outre, le Code source confirme clairement qu'un nouvel objet est créé et renvoyé.

    En bref, cela signifie que votre classe Descryptor n'est pas actuellement sur le thread-coffre-fort, mais vous devriez pouvoir le faire filer-sécurité en synchronisant les opérations pertinentes (par exemple, Encode et décodez ) et n'exposant pas les deux objets de chiffrement. Si la synchronisation des méthodes est susceptible de créer un goulot d'étranglement, créez une instance distincte de Descryptor pour chaque thread.


4 commentaires

Désolé d'avoir affiché sur un tel sujet ancien, mais je doute que SecretkeyFactory.GetInstance () renvoie un nouvel objet à chaque fois parce que c'est une usine. En outre, je le teste en ce moment et le premier appel prend 2,5 ans tandis que chaque appel qui consécutif prend la 0.


1) Voir la mise à jour. 2) Le premier appel déclenche probablement le chargement de la classe et l'initialisation pouvant impliquer de «entropier» du système d'exploitation. Dans certaines circonstances, cela peut prendre une quantité importante quantité de temps réel.


Assez juste, il n'avait pas beaucoup de sens être un singleton tbh. Pourquoi ne rassemblerait-il que l'entropie la première fois? Il faudrait sûrement être fait chaque fois que vous appelez le getinstance?


Je soupçonne que l'entropie est recueillie par quelque chose d'autre qui est chargé / initialisé dans le cadre du fournisseur. Mais ce n'est que des devintes. Si vous êtes sérieux sur l'identification de la cause réelle, lisez le code source, profilez-le, déboguer, etcetera.



3
votes

Les choses ont besoin d'être du thread-sécurité si elles sont utilisées par plusieurs threads à la fois. Étant donné que chaque instance de cette classe sera probablement utilisée uniquement par un seul thread, il n'est pas nécessaire de s'inquiéter de savoir s'il est threadsafe ou non.

sur une note non liée, avoir un sel codé dur, une nonce ou IV est jamais une bonne idée.


6 commentaires

Je ne savais pas que merci. Je prévois de stocker la phrase sel et passe-passe dans des fichiers distincts dans les autorisations de système d'exploitation strictes disponibles uniquement à l'application.


En utilisant un sel constant (même s'il est protégé), défait une grande partie du point d'utiliser un sel en premier lieu.


Vous dites que le sel doit être obtenu au hasard au moment de l'exécution? Je suis confus, il est clair que la phrase-passe ne peut pas changer une fois que les données ont été cryptées avec elle, alors quelle doit être générée à l'avant et stockée dans un fichier sécurisé, le sel et la phrase secrète, juste la phrase secrète, etc.?


Le point d'utiliser un sel lorsque le cryptage est de sorte qu'une combinaison donnée de plainte et de phrase secrète ne crypy pas toujours au même chiffrestext. L'exemple classique de ceci est le cryptage de fichier Unix passwd: un sel est utilisé de sorte que même 2 utilisateurs aient le même mot de passe, les valeurs cryptées sont différentes (ce qui rend les attaques de dictionnaires en vrac plus difficiles). Le sel est généré au hasard lorsque le mot de passe est crypté et stocké avec la valeur cryptée.


Je vois, mais le stockage du sel avec la valeur cryptée signifie que le sel ne peut pas être crypté lors de la stocker, non? C'est bon, car le sel aléatoire découle le cryptage de toutes les autres données cryptées. Un sel statique compromettrait tout s'il était découvert. Merci pour l'info


@ user646584 @David Cela n'aide pas que les gens confondent les termes «sel» et «iv». Un sel est utilisé pour faciliter la recherche du prétimage d'un mot de passe haché plus difficile. Un IV est utilisé pour assurer diverses propriétés de sécurité sur un chiffrement, notamment que le même message crypté deux fois n'entraînera pas le même CIPHERText. Ce que vous voulez ici, c'est un IV, qui devrait être unique pour chaque message que vous créez. Vous n'avez pas besoin de sel, car vous ne pouvez pas stocker le mot de passe comme hachage.



2
votes

L'objet COPHER CIphER ne sera pas en sécurité, car il conserve l'état interne sur le processus de cryptage. Qui s'applique à votre classe Descrypeter également - chaque thread devra utiliser sa propre instance de Descrypeter , à moins que vous ne synchronisez le code et et Décode Méthodes.


2 commentaires

Voir mon exemple ci-dessus ... Pourquoi ne pas simplement créer une nouvelle instance de chiffrement pour chaque invocation de chiffrement () / déchiffrer ()?


Oui, mais dans votre exemple, vous utilisez des variables d'instance ecphher et dcipher pour stocker les instances de chiffrement, donc si 2 threads appellent chiffrer () sur le même désencrypeter instance simultanée, ils vont se clobber (à moins que vous ne synchronisez pas le fichier chiffrer () appel). Pour éviter cela, vous pouvez faire ecphher et dcipher être des variables locales (dans la fonction cryptée ()) au lieu des variables d'instance, de cette façon chaque appel de chiffrer () aurait sa propre valeur.