반응형
AES256 암호화하는 방법
- 키를 직접 지정해서 암호화, 복호화하는 방법
- 키 스토어에서 생성한 키를 사용해서 암호화, 복호화하는 방법
1번 방법이 일반적으로 많이 사용되고 알려진 방법이다.
방법 1. 키를 직접 지정해서 암호화, 복호화하는 방법
- 샘플 코드
public static byte[] iv = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
// 사용자 지정 키로 AES256 암호화
public static String encByKey(String key, String value) throws Exception {
return encByKey(key.getBytes(), value.getBytes());
}
// 사용자 지정 키로 AES256 복호화
public static String encByKey(byte[] key, byte[] value) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] randomKey = cipher.doFinal(value);
return Base64.encodeToString(randomKey, 0);
}
// 사용자 지정 키로 AES256 복호화
public static String decByKey(String key, String plainText) throws Exception {
return decByKey(key.getBytes(), Base64.decode(plainText, 0));
}
// 사용자 지정 키로 AES256 복호화
public static String decByKey(byte[] key, byte[] encText) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] secureKey = cipher.doFinal(encText);
return new String(secureKey);
}
- 사용 방법
try {
String key = "secretKey1234567";
String plainText = "test1234";
String encText = AES.encByKey(key, plainText);
String decText = AES.decByKey(key, encText);
Log.d(TAG ,"암호화 결과 : " + encText);
Log.d(TAG ,"복호화 결과 : " + decText);
} catch (Exception e) {
e.printStackTrace();
}
- 로그 결과
암호화 결과 : wI8W9C4f6d9/tbnNqpEQBg==
복호화 결과 : test1234
방법2. 키 스토어에서 생성한 키를 사용해서 암호화, 복호화하는 방법
암호화 시, 암호화된 값과 IV 값이 모두 필요하므로 String []으로 리턴한다.
- 샘플 코드
// 키스토어 키 존재 여부 확인
public static boolean isExistKey(String alias) throws Exception {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String nextAlias = aliases.nextElement();
if (nextAlias.equals(alias)) {
return true;
}
}
return false;
}
// 키스토어 키 생성
public static void generateKey(String alias) throws Exception {
final KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
// 키스토어 키 조회
public static SecretKey getKeyStoreKey(String alias) throws Exception {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(alias, null);
return secretKeyEntry.getSecretKey();
}
// 키스토어 키로 AES256 암호화
public static String[] encByKeyStoreKey(SecretKey secretKey, String plainText) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] enc = cipher.doFinal(plainText.getBytes());
byte[] iv = cipher.getIV();
String encText = Base64.encodeToString(enc, 0);
String ivText = Base64.encodeToString(iv, 0);
String[] result = new String[2];
result[0] = encText;
result[1] = ivText;
return result;
}
// 키스토어 키로 AES256 복호화
public static String decByKeyStoreKey(SecretKey secretKey, String encText, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, Base64.decode(iv, 0));
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
byte[] dec = cipher.doFinal(Base64.decode(encText, 0)); // 확인 필요
return new String(dec);
}
- 사용 방법
String alias = "com.test.alias";
try {
if (!AES.isExistKey(alias)) {
AES.generateKey(alias);
}
SecretKey secretKey = AES.getKeyStoreKey(alias);
String[] enc = AES.encByKeyStoreKey(secretKey, "test1234");
String dec = AES.decByKeyStoreKey(secretKey, enc[0], enc[1]);
Log.d(TAG, "암호화 결과 : " + enc[0]);
Log.d(TAG, "암호화 IV : " + enc[1]);
Log.d(TAG, "복호화 결과 : " + dec);
} catch (Exception e) {
e.printStackTrace();
}
- 로그 결과
암호화 결과 : QYVP3waFyEUU8erV+zZoT4Lh7qmpYrqG
암호화 IV : ILdpQTINl5SXuMSK
복호화 결과 : test1234
주의사항
1. 1번 방법을 사용할 때는 키 길이를 잘 맞춰서 사용해야한다.
만약 키 길이를 맞추기 어렵다면, SHA256 해시를 사용해서 길이를 맞추는 방법도 있다.
2. 2번 방법을 사용할 때 암호화 시 나오는 IV 값을 가지고 있다가 복호화 시 사용해야 한다.
그러므로, IV를 파일 등에 저장해서 가지고 있어야 한다.
전체 소스코드
1. AES
public class AES {
public static byte[] iv = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
// 키스토어 키 존재 여부 확인
public static boolean isExistKey(String alias) throws Exception {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String nextAlias = aliases.nextElement();
if (nextAlias.equals(alias)) {
return true;
}
}
return false;
}
// 키스토어 키 생성
public static void generateKey(String alias) throws Exception {
final KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
// 키스토어 키 조회
public static SecretKey getKeyStoreKey(String alias) throws Exception {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(alias, null);
return secretKeyEntry.getSecretKey();
}
// 키스토어 키로 AES256 암호화
public static String[] encByKeyStoreKey(SecretKey secretKey, String plainText) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] enc = cipher.doFinal(plainText.getBytes());
byte[] iv = cipher.getIV();
String encText = Base64.encodeToString(enc, 0);
String ivText = Base64.encodeToString(iv, 0);
String[] result = new String[2];
result[0] = encText;
result[1] = ivText;
return result;
}
// 키스토어 키로 AES256 복호화
public static String decByKeyStoreKey(SecretKey secretKey, String encText, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, Base64.decode(iv, 0));
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
byte[] dec = cipher.doFinal(Base64.decode(encText, 0)); // 확인 필요
return new String(dec);
}
// 사용자 지정 키로 AES256 암호화
public static String encByKey(String key, String value) throws Exception {
return encByKey(key.getBytes(), value.getBytes());
}
// 사용자 지정 키로 AES256 복호화
public static String encByKey(byte[] key, byte[] value) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] randomKey = cipher.doFinal(value);
return Base64.encodeToString(randomKey, 0);
}
// 사용자 지정 키로 AES256 복호화
public static String decByKey(String key, String plainText) throws Exception {
return decByKey(key.getBytes(), Base64.decode(plainText, 0));
}
// 사용자 지정 키로 AES256 복호화
public static String decByKey(byte[] key, byte[] encText) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] secureKey = cipher.doFinal(encText);
return new String(secureKey);
}
}
2. MainActivity
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
public static String alias = "com.test.alias";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
// 방법1. 키를 직접 지정해서 암호화, 복호화 하는 방법
String key = "secretKey1234567";
String plainText = "test1234";
String encText = AES.encByKey(key, plainText);
String decText = AES.decByKey(key, encText);
Log.d(TAG ,"암호화 결과 : " + encText);
Log.d(TAG ,"복호화 결과 : " + decText);
// 방법2. 키스토어에서 생성한 키를 사용해서 암호화, 복호화 하는 방법
if (!AES.isExistKey(alias)) {
AES.generateKey(alias);
}
SecretKey secretKey = AES.getKeyStoreKey(alias);
String[] enc = AES.encByKeyStoreKey(secretKey, "test1234");
String dec = AES.decByKeyStoreKey(secretKey, enc[0], enc[1]);
Log.d(TAG, "암호화 결과 : " + enc[0]);
Log.d(TAG, "암호화 IV : " + enc[1]);
Log.d(TAG, "복호화 결과 : " + dec);
} catch (Exception e) {
e.printStackTrace();
}
}
}
반응형
'IT > 안드로이드+JAVA' 카테고리의 다른 글
[Android] 내부 저장소 경로 가져오기 (0) | 2021.05.04 |
---|---|
[Android] Play스토어 앱 업로드 절차 (0) | 2021.03.11 |
[Android] EditText showSoftInput 작동 안할 때 해결 방법 (0) | 2021.01.09 |
[Android Studio] 원격 디버깅, 로그 출력 (adb) (4) | 2020.12.20 |
[안드로이드] SHA256 해시 알고리즘 예제 (0) | 2020.12.08 |