2011-03-15 25 views
9

Belirli bir veri şifrelenmiş ve şifresi çözülmüş olması gereken yüksek eşzamanlı bir uygulama için aşağıdaki kodu kullanmak istiyorum. Bu nedenle, tahmin edilemeyen sorunlardan kaçınmak için, eğer bu kodun hangi bölümünün senkronize edilmesi gerektiğini bilmem gerekiyor. Ben şifrelemek (yeni şifre oluşturma) ve her ayin için) (yöntemleri deşifre olursa yükü bir sürü yeni almakla varsaBu Java şifreleme kodu iş parçacığı güvenli mi?

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 (...) 
    } 
} 

, o zaman ben emin değilim sadece, eşzamanlılık sorunları önleyebilirsiniz Her bir çağrı için bir şifre örneği.

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 (...) 

cevap

3

Her şey aynı anda birden fazla iş parçacığı tarafından kullanılıyorsa iş parçacığı için güvenli olmalıdır. Bu sınıfın her bir örneği yalnızca tek bir iş parçacığı tarafından kullanılacağından, iş parçacığı olup olmadığı konusunda endişelenmenize gerek yoktur. İlgisiz bir notta, şifrelenmemiş bir tuzu, nonce veya IV olan hiçbir zaman iyi bir fikir değildir.

+0

Bunu bilmiyordum, teşekkürler. Salt ve pass deyimini, yalnızca uygulama için mevcut olan katı işletim sistemi izinleri altında ayrı dosyalarda depolamayı planlıyorum. – user646584

+0

Sabit bir tuz kullanmak (korumalı olsa bile) ilk etapta bir tuz kullanma noktasını büyük ölçüde bozar. –

+0

Tiyatronun çalışma zamanında rastgele elde edilmesi gerektiğini mi söylüyorsunuz? Kafam karıştı, açık bir şekilde veri şifreli bir kez bir kez değişmez, öyleyse neyin güvenli bir dosya, tuz ve parola, sadece parola, vb. – user646584

10

standart kural - Java kütüphanelerde bir sınıf parçacığı güvenli olduğunu açıkça o Javadoc devletler sen o olmadığını üstlenmesi gerektiğini sürece. Böyle bir durumda,

:

  • çeşitli sınıflar iplik güvenli olarak belgelenmiştir.
  • Cipher.getInstance(...) ve SecretKeyFactory.getInstance(...) yöntem, yeni nesnelerin dönen olarak belgelenmiştir; diğer konuların referans aldığı mevcut nesneler referans değildir.

    "Belirtilen algoritma döndürülür destekleyen ilk Sağlayıcısından SecretKeyFactorySpi uygulanmasını enkapsüle yeni SecretKeyFactory nesne": -

    GÜNCELLEMEjavadoc bu diyor

    Ayrıca, source code açıkça yeni bir nesne oluşturulur ve geri olduğunu doğrular. Kısacası

, bu DesEncryptor sınıf şu anda iş parçacığı güvenli olmadığı anlamına gelir, ancak ilgili işlemleri (örn encode ve decode) senkronize ve teşhir etmeyerek onu evreli yapmak mümkün olmalıdır iki Cipher nesnesi. Yöntemlerin senkronize edilmesinin bir tıkanıklık yaratması olasıysa, her iş parçacığı için ayrı bir DesEncryptor örneği oluşturun.

+0

Böyle eski bir konuyu yayınladığım için üzgünüm, ama bir fabrikası olduğu için her zaman SecretKeyFactory.getInstance() öğesi yeni bir nesne döndürdüğünden şüpheliyim. Ayrıca, şu anda test ediyorum ve ilk çağrı 2.5s alırken, her çağrı 0s alır. – andrewktmeikle

+0

1) Güncellemeye bakın.2) İlk çağrı büyük olasılıkla işletim sisteminden "entropi" almayı gerektirebilecek sınıf yüklemesini ve başlatmayı tetikliyor olabilir. Bazı durumlarda, bu, * önemli miktarda gerçek zaman alabilir. –

+0

Yeterince adil, tek kişilik bir tbh olmak pek anlamlı gelmedi. Neden sadece ilk kez entropiyi toplar? Elbette getInstance dediğin zaman yapılması gerekecek mi? – andrewktmeikle

1

Cipher nesne şifreleme süreci hakkında iç durumunu korur, çünkü iş parçacığı güvenli olacak değildir. Bu, DesEncrypter sınıfınıza da uygulanır - encode ve decode yöntemlerini senkronize etmediğiniz sürece her bir iş parçacığının kendi örneğini DesEncrypter kullanması gerekir.

+0

Yukarıdaki örneğime bakın ... neden sadece her bir encrypt()/decrypt() için yeni bir Cipher örneği oluşturmuyorsunuz? – user646584

+2

Evet, ancak örneğinizde, Cipher örneklerini depolamak için örnek değişkenleri 'ecipher' ve 'dcipher' kullanacaksınız, böylece aynı anda 2 iş parçacığı aynı DesEncrypter örneğinde şifrelemek() çağırırsa, birbirlerini görmezden gelirler ('encrypt()' çağrısını senkronize etmediğiniz sürece. Bundan kaçınmak için, örnek değişkenler yerine "ecipher" ve "dcipher" yerel değişkenler (encrypt() fonksiyonu içinde) olabilir, bu şekilde her bir encrypt() kodunun kendi değeri olacaktır. –

İlgili konular