Android
암호를 안전하게 저장하는 방법
수색…
암호화 된 암호로 암호화 된 AES 사용
이 예제는 암호를 암호화하기 위해 AES 알고리즘을 사용합니다. 소금 길이는 128 비트까지 가능합니다.
우리는 SecureRandom
클래스를 사용하여 소금을 생성합니다.이 소금은 암호와 결합되어 비밀 키를 생성합니다. 사용 된 클래스는 이미 안드로이드 패키지 인 javax.crypto
와 java.security
합니다.
키가 생성되면이 키를 변수에 보존하거나 저장해야합니다. 우리는 값을 S_KEY
공유 환경 설정에 저장합니다. 그런 다음 암호가 ENCRYPT_MODE
에서 초기화되면 Cipher
클래스의 doFinal
메소드를 사용하여 암호화됩니다. 그런 다음 암호화 된 암호가 바이트 배열에서 문자열로 변환되어 공유 기본 설정간에 저장됩니다. 암호화 된 암호를 생성하는 데 사용되는 키를 사용하여 비슷한 방식으로 암호를 해독 할 수 있습니다.
public class MainActivity extends AppCompatActivity {
public static final String PROVIDER = "BC";
public static final int SALT_LENGTH = 20;
public static final int IV_LENGTH = 16;
public static final int PBE_ITERATION_COUNT = 100;
private static final String RANDOM_ALGORITHM = "SHA1PRNG";
private static final String HASH_ALGORITHM = "SHA-512";
private static final String PBE_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
public static final String SECRET_KEY_ALGORITHM = "AES";
private static final String TAG = "EncryptionPassword";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String originalPassword = "ThisIsAndroidStudio%$";
Log.e(TAG, "originalPassword => " + originalPassword);
String encryptedPassword = encryptAndStorePassword(originalPassword);
Log.e(TAG, "encryptedPassword => " + encryptedPassword);
String decryptedPassword = decryptAndGetPassword();
Log.e(TAG, "decryptedPassword => " + decryptedPassword);
}
private String decryptAndGetPassword() {
SharedPreferences prefs = getSharedPreferences("pswd", MODE_PRIVATE);
String encryptedPasswrd = prefs.getString("token", "");
String passwrd = "";
if (encryptedPasswrd!=null && !encryptedPasswrd.isEmpty()) {
try {
String output = prefs.getString("S_KEY", "");
byte[] encoded = hexStringToByteArray(output);
SecretKey aesKey = new SecretKeySpec(encoded, SECRET_KEY_ALGORITHM);
passwrd = decrypt(aesKey, encryptedPasswrd);
} catch (Exception e) {
e.printStackTrace();
}
}
return passwrd;
}
public String encryptAndStorePassword(String password) {
SharedPreferences.Editor editor = getSharedPreferences("pswd", MODE_PRIVATE).edit();
String encryptedPassword = "";
if (password!=null && !password.isEmpty()) {
SecretKey secretKey = null;
try {
secretKey = getSecretKey(password, generateSalt());
byte[] encoded = secretKey.getEncoded();
String input = byteArrayToHexString(encoded);
editor.putString("S_KEY", input);
encryptedPassword = encrypt(secretKey, password);
} catch (Exception e) {
e.printStackTrace();
}
editor.putString("token", encryptedPassword);
editor.commit();
}
return encryptedPassword;
}
public static String encrypt(SecretKey secret, String cleartext) throws Exception {
try {
byte[] iv = generateIv();
String ivHex = byteArrayToHexString(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher encryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
encryptionCipher.init(Cipher.ENCRYPT_MODE, secret, ivspec);
byte[] encryptedText = encryptionCipher.doFinal(cleartext.getBytes("UTF-8"));
String encryptedHex = byteArrayToHexString(encryptedText);
return ivHex + encryptedHex;
} catch (Exception e) {
Log.e("SecurityException", e.getCause().getLocalizedMessage());
throw new Exception("Unable to encrypt", e);
}
}
public static String decrypt(SecretKey secret, String encrypted) throws Exception {
try {
Cipher decryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
String ivHex = encrypted.substring(0, IV_LENGTH * 2);
String encryptedHex = encrypted.substring(IV_LENGTH * 2);
IvParameterSpec ivspec = new IvParameterSpec(hexStringToByteArray(ivHex));
decryptionCipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
byte[] decryptedText = decryptionCipher.doFinal(hexStringToByteArray(encryptedHex));
String decrypted = new String(decryptedText, "UTF-8");
return decrypted;
} catch (Exception e) {
Log.e("SecurityException", e.getCause().getLocalizedMessage());
throw new Exception("Unable to decrypt", e);
}
}
public static String generateSalt() throws Exception {
try {
SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
byte[] salt = new byte[SALT_LENGTH];
random.nextBytes(salt);
String saltHex = byteArrayToHexString(salt);
return saltHex;
} catch (Exception e) {
throw new Exception("Unable to generate salt", e);
}
}
public static String byteArrayToHexString(byte[] b) {
StringBuffer sb = new StringBuffer(b.length * 2);
for (int i = 0; i < b.length; i++) {
int v = b[i] & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
public static byte[] hexStringToByteArray(String s) {
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte) v;
}
return b;
}
public static SecretKey getSecretKey(String password, String salt) throws Exception {
try {
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), hexStringToByteArray(salt), PBE_ITERATION_COUNT, 256);
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGORITHM, PROVIDER);
SecretKey tmp = factory.generateSecret(pbeKeySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), SECRET_KEY_ALGORITHM);
return secret;
} catch (Exception e) {
throw new Exception("Unable to get secret key", e);
}
}
private static byte[] generateIv() throws NoSuchAlgorithmException, NoSuchProviderException {
SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
byte[] iv = new byte[IV_LENGTH];
random.nextBytes(iv);
return iv;
}
}
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow