2012-04-17 43 views
5

Vì vậy, tôi đã nhìn thấy rất nhiều ví dụ và đã thực hiện rất nhiều việc googling và xem các ví dụ về Stack Overflow ... và tôi cần trợ giúp. Tôi đã có một ứng dụng Android và tôi đang lưu trữ tên người dùng và mật khẩu trên thiết bị và tôi cần mã hóa chúng AES 256. Từ xem ví dụ, đây là những gì tôi có cho đến thời điểm này:Dữ liệu mã hóa AES 256 bit của Android

public class Security { 
    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 
    }; 

    // Iteration count 
    int iterationCount = 19; 

    public Security (String passPhrase) { 
     try { 
      // Create the key 
      KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 
      SecretKey key = SecretKeyFactory.getInstance(
       "PBEWithSHAAndAES").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 (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    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 Base64.encodeToString(enc, Base64.DEFAULT); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public String decrypt(String str) { 
     try { 
      // Decode base64 to get bytes 
      byte[] dec = Base64.decode(str, Base64.DEFAULT); 

      // Decrypt 
      byte[] utf8 = dcipher.doFinal(dec); 

      // Decode using utf-8 
      return new String(utf8, "UTF8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
} 

I ' m cố gắng đặt mật khẩu, vì vậy người dùng sẽ tạo tài khoản lần đầu tiên bằng tên người dùng và mật khẩu cần thiết để liên lạc lại với máy chủ và tạo mã PIN sẽ được sử dụng làm khóa cho các thông tin đăng nhập này được lưu trữ trong cơ sở dữ liệu.

Điều tôi lo ngại nhất là điều này có an toàn không? Tôi biết một muối cố định là xấu, làm cách nào để khắc phục điều đó?

Tôi biết có được như một tỷ câu hỏi về điều này, nhưng tôi muốn ai đó chỉ đi ra và nói "đây là an toàn" hoặc "NÀY KHÔNG BẢO ĐẢM, sự thay đổi này"

Cảm ơn!


EDIT:

Vì vậy, đây là đoạn code tôi có cho đến nay, và có vẻ như được làm việc ...

public class Security { 

    Cipher ecipher; 
    Cipher dcipher; 
    byte[] salt = new byte[8]; 
    int iterationCount = 200; 

    public Security(String passPhrase) { 
     try { 
      // generate a random salt 
      SecureRandom random = new SecureRandom(); 
      random.nextBytes(salt); 

      // Create the key 
      KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 
      SecretKey key = SecretKeyFactory.getInstance(
       "PBEWithSHA256And256BitAES-CBC-BC").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 (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    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 Base64.encodeToString(enc, Base64.DEFAULT); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public String decrypt(String str) { 
     try { 
      // Decode base64 to get bytes 
      byte[] dec = Base64.decode(str, Base64.DEFAULT); 

      // Decrypt 
      byte[] utf8 = dcipher.doFinal(dec); 

      // Decode using utf-8 
      return new String(utf8, "UTF8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public int getIterationCount() { 
     return iterationCount; 
    } 

    public String getSalt() { 
     return Base64.encodeToString(salt, Base64.DEFAULT); 
    } 
} 

tôi đã sử dụng mã này để kiểm tra nó:

Security s = new Security(pinBox.getText().toString()); 
      String encrypted = s.encrypt(passwordBox.getText().toString()); 
      String decrypted = s.decrypt(encrypted); 
      builder.setMessage("pin: " + pinBox.getText().toString() + "\n" + 
        "password: " + passwordBox.getText().toString() + "\n" + 
        "encrypted: " + encrypted + "\n" + 
        "decrypted: " + decrypted + "\n" + 
        "salt: " + s.getSalt()); 

Vì vậy, tôi không cần phải lo lắng về vectơ khởi tạo? Hoặc đặc biệt hardcode một thuật toán mã hóa?

Cảm ơn bạn lần nữa!

+0

Cảm ơn bạn đời đã giúp đỡ này .. :) – Noman

+0

bạn có thể giúp tôi với điều này không? http://stackoverflow.com/questions/34061675/convert-ios-encryption-to-android :( – MetaSnarf

Trả lời

4

EDIT: Trong khi mã bên dưới là chính xác, những gì bạn đang làm về cơ bản giống nhau, với IV bắt nguồn từ mật khẩu, vì vậy bạn không phải lưu trữ riêng biệt.

Mã của bạn có hoạt động như mong đợi không? Để mã hóa/giải mã thực tế, bạn sẽ muốn sử dụng AES, hầu hết có thể ở chế độ CBC. Sau đó, bạn sẽ cần một IV, do đó, nó sẽ trở thành một cái gì đó như thế này:

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
byte[] iv = new byte[IV_LENGTH]; 
SecureRandom random = new SecureRandom(); 
random.nextBytes(iv); 
ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); 
byte[] enc = ecipher.doFinal(utf8); 

Cho dù nó là an toàn phụ thuộc vào những gì bạn đang sử dụng này cho. Mục đích của muối là làm cho khó khăn hơn để gây sức mạnh cho cụm từ mật khẩu: nếu ngẫu nhiên kẻ tấn công không thể sử dụng các bảng mật khẩu được tạo trước (cụm từ mật khẩu->). Nếu bạn không quá lo lắng về loại tấn công này, bạn có thể để nó cố định. Nếu bạn quyết định làm cho nó ngẫu nhiên, chỉ cần lưu trữ nó với các dữ liệu được mã hóa. Cùng với IV.

+0

Tôi giả sử tôi sẽ mã hóa muối và iv trước khi lưu trữ chúng bằng tên người dùng và mật khẩu được mã hóa? Tôi sẽ không có muối và iv để thiết lập decrypter, vì vậy có lẽ tôi là sự hiểu lầm? – Josh

+0

Muối không phải là chính nó là một bí mật, nó không cần phải được mã hóa, cũng không phải là IV –

+0

Ok. Điều đó có ý nghĩa Cảm ơn bạn đã giúp tôi hiểu Tôi sẽ chỉnh sửa mã của tôi và đăng lại nó Tôi muốn đảm bảo rằng tôi đang nhận được giải pháp tốt nhất có thể. Tôi nghĩ rằng tôi đã đọc nó nếu nó cao hơn, mã sẽ mất nhiều thời gian hơn để thực thi, nhưng tôi giả sử cao hơn là tốt hơn?Tôi đoán đó là một cái gì đó để có hiệu lực của chạy iteration_count thuật toán lần trước khi trở về một giá trị cuối cùng? – Josh

Các vấn đề liên quan