Est-ce Java code de cryptage "thread-safe"?
Je veux utiliser le code suivant pour un haut-simultanéité de l'application où certaines données doivent être chiffrées et déchiffrées. J'ai donc besoin de savoir quelle est la partie de ce code doit être synchronisé, le cas échéant, pour éviter imprévisible questions.
public class DesEncrypter {
Cipher ecipher;
Cipher dcipher;
//8-byte Salt
byte[] salt = {
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
};
int iterationCount = 19;
DesEncrypter(String passPhrase) {
try {
//Create the key
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance( "PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
dcipher = Cipher.getInstance(key.getAlgorithm());
//Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
//Create the ciphers
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
} catch (...)
}
public String encrypt(String str) {
try {
//Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
//Encrypt
byte[] enc = ecipher.doFinal(utf8);
//Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
} catch (...)
}
public String decrypt(String str) {
try {
//Decode base64 to get bytes
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
//Decrypt
byte[] utf8 = dcipher.doFinal(dec);
//Decode using utf-8
return new String(utf8, "UTF8");
} catch (...)
}
}
Si je crée un nouveau chiffrement dans le encrypt() et decrypt() méthodes pour chaque invocation, alors je peux éviter les problèmes de simultanéité, je ne sais pas si il y a beaucoup de frais généraux pour obtenir une nouvelle instance d'un chiffre pour chaque invocation.
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 (...)
OriginalL'auteur user646584 | 2011-03-15
Vous devez vous connecter pour publier un commentaire.
Choses seulement besoin d'être thread-safe si elles sont utilisées par plusieurs threads à la fois. Étant donné que chaque instance de cette classe va sans doute être utilisé par un seul thread, il n'y a pas besoin de s'inquiéter de savoir si c'est thread-safe ou pas.
Sur une autre note, ayant une codé en dur le sel, le nonce ou IV est jamais une bonne idée.
À l'aide d'une constante de sel (même si elle est protégée) défaites beaucoup de l'usage du sel dans la première place.
Vous dites que le sel devrait être obtenus de manière aléatoire au moment de l'exécution? Je suis confus, clairement le mot de passe ne peut pas changer une fois que les données ont été chiffrées avec elle, de sorte que ce qui doit être généré à l'avant et stockées dans un fichier sécurisé, le sel et le mot de passe, juste le mot de passe, etc?
Le point de l'utilisation d'un sel lors du chiffrement est donc qu'une combinaison donnée de texte en clair&phrase de passe ne sont pas toujours chiffrer pour le même texte chiffré. L'exemple le plus classique est Unix fichier de mots de passe de cryptage: le sel est utilisé de sorte que même si 2 utilisateurs ont le même mot de passe, les valeurs chiffrées sont différents (ce qui fait en vrac des attaques de dictionnaire plus difficile). Le sel est généré de façon aléatoire lorsque le mot de passe est crypté et stocké avec la valeur chiffrée.
Je vois, mais le stockage du sel avec la valeur chiffrée signifie que le sel ne peut pas être chiffré lors de l'entreposage, droit? C'est ok, puisque le hasard sel découple le chiffrement de toutes les autres données chiffrées. Statique sel de tout compromettre s'il a été découvert. Merci pour l'info
OriginalL'auteur Nick Johnson
La norme, la règle est - à moins que la Javadoc stipule explicitement que la classe dans les bibliothèques Java est thread-safe, vous devriez assumer qu'il ne l'est pas.
Dans ce cas particulier:
La
Cipher.getInstance(...)
etSecretKeyFactory.getInstance(...)
méthodes SONT décrites comme retour de nouveaux objets; c'est à dire pas de références à des objets existants que d'autres threads peut avoir des références à l'.Mise à JOUR - Le javadoc dit ceci:
En outre, la le code source clairement confirme qu'un nouvel objet est créé et retourné.
En bref, cela signifie que votre
DesEncryptor
classe n'est actuellement pas thread-safe, mais vous devriez être en mesure de le faire thread-safe en synchronisant les opérations pertinentes (par exemple,encode
etdecode
), et de ne pas exposer les deux Chiffrement des objets. Si les méthodes de synchronisation est susceptible de créer un goulot d'étranglement, puis créer une instance séparée deDesEncryptor
pour chaque thread.1) Voir la mise à jour. 2) Le premier appel est probablement le déclenchement de chargement de classe, et l'initialisation qui peut impliquer l'obtention de "l'entropie" de l'OS. Dans certaines circonstances, cela peut prendre un important quantité de temps réel.
Juste assez, il n'a pas beaucoup de sens d'être un singleton tbh. Pourquoi serait-il seulement de recueillir de l'entropie la première fois? Sûrement, il devrait être fait chaque fois que vous avez appelé la getInstance?
Je soupçonne que l'entropie est recueillie par quelque chose d'autre qui est chargé / initialisé de la part du fournisseur. Mais ce n'est qu'une conjecture. Si vous êtes sérieux au sujet de l'identification de la cause réelle, lire le code source, de profil, de débogage, et cætera.
OriginalL'auteur Stephen C
La
Cipher
objet n'est pas thread-safe, parce qu'il conserve l'état interne sur le processus de chiffrement. Qui s'applique à votreDesEncrypter
classe ainsi - chaque thread aurez besoin d'utiliser sa propre instance deDesEncrypter
, à moins que vous synchonize laencode
etdecode
méthodes.Oui, mais dans votre exemple, vous utilisez les variables d'instance
ecipher
etdcipher
pour stocker le Chiffrement des cas, donc si 2 threads appel encrypt() sur le mêmeDesEncrypter
instance simultanément, ils vont tabasser les uns des autres (sauf si vous synchronisez leencrypt()
appel). Pour éviter cela, vous pourriez faireecipher
etdcipher
être des variables locales (au sein de la encrypt ()) au lieu de variables d'instance, de cette façon, chaque invocation de encrypt() aurait sa propre valeur.OriginalL'auteur David Gelhar