
오늘은 AES-256 암호화 방식을 이용하여 간단한 보안 프로그램을 구현해보도록 하겠습니다.
개념 다지기
일단 코드를 짜기전에 개념을 살펴보도록 하겠습니다.
첫번째는 AES입니다.
우리가 만들 보안 프로그램은 AES기반의 암호화 방식을 이용한 프로그램입니다.
"그럼 AES가 뭘까요??"
바로.. AES는 Advanced Encryption Standard의 약자로 고급 암호화 표준이란 뜻을 가지고 있습니다.
AES는 암호화 및 복호화에 동일한 키를 사용하는 대칭키 알고리즘으로
높은 안전성과 빠른 속도로 인해 양방향 암호화에서 가장 많이 사용되는 방식입니다.
AES 암호화의 종류는 AES-128, AES-192, AES-256이 있으며 뒤에 붙은 숫자는 키의 길이를 의미합니다.
우리가 사용할 암호화는 AES-256입니다.
AES-128 : 128bit = 16byte
AES-192 : 192bit = 24byte
AES-256 : 256bit = 32byte
"
음.. 그렇다면!
여기서 궁금한거!!
우리가 사용할 암호화 방식은 AES-256인데 이 AES-256은 양방향 암호화라고 했었지..
그럼 단방향 암호화는 없을까??
당연히 있지!!
"
단방향 암호화는 복호화을 할 수 없는 암호화 방식으로
패스워드 암호화에 사용되며 대표적으로 SHA-256이 있습니다.
다시 본론으로 돌아와서..
AES-256의 암호화 과정과 복호화 과정을 살펴보겠습니다.
일단 암호화
plain text -> pain bytes -> encrypt -> encrypted bytes -> encrypted base64 test
다음 복호화
encrypted base64 text -> encrypted bytes -> decrypt -> plain bytes -> plain text
일단 이정도로만 개념을 잡겠습니다.
그럼 바로 소스코드 보러가봅시다!!
소스코드
AES.java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
class AES {
//알고리즘
public static String algorithms = "AES/CBC/PKCS5Padding";
// AES/CBC/PKCS5Padding -> AES, CBC operation mode, PKCS5 padding scheme 으로 초기화된 Cipher 객체
//키
private final static String AESKey = "abcdefghabcdefghabcdefghabcdefgh"; //32byte
// 초기화 벡터
private final static String AESIv = "0123456789abcdef"; //16byte
// AES 암호화
String encrypt_AES(String ID){
try {
String result; // 암호화 결과 값을 담을 변수
// 암호화/복호화 기능이 포함된 객체 생성
Cipher cipher = Cipher.getInstance(algorithms);
// 키로 비밀키 생성
SecretKeySpec keySpec = new SecretKeySpec(AESKey.getBytes(), "AES");
// iv 로 spec 생성
IvParameterSpec ivParamSpec = new IvParameterSpec(AESIv.getBytes());
// 매번 다른 IV를 생성하면 같은 평문이라도 다른 암호문을 생성할 수 있다.
// 또한 IV는 암호를 복호화할 사람에게 미리 제공되어야 하고 키와 달리 공개되어도 상관없다
// 암호화 적용
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec);
// 암호화 실행
byte[] encrypted = cipher.doFinal(ID.getBytes(StandardCharsets.UTF_8)); // ID 암호화(인코딩 설정)
result = Base64.getEncoder().encodeToString(encrypted); // 암호화 인코딩 후 저장
return result;
}
catch (Exception e) {
System.out.println("암호화 중 오류 발생하였습니다. ");
e.printStackTrace();
}
return "";
}
// AES 복호화
String decrypt_AES(String ID){
try {
// 암호화/복호화 기능이 포함된 객체 생성
Cipher cipher = Cipher.getInstance(algorithms);
// 키로 비밀키 생성
SecretKeySpec keySpec = new SecretKeySpec(AESKey.getBytes(), "AES");
// iv 로 spec 생성
IvParameterSpec ivParamSpec = new IvParameterSpec(AESIv.getBytes());
// 매번 다른 IV를 생성하면 같은 평문이라도 다른 암호문을 생성할 수 있다.
// 또한 IV는 암호를 복호화할 사람에게 미리 제공되어야 하고 키와 달리 공개되어도 상관없다
// 암호화 적용
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec);
//암호 해석
byte[] decodedBytes = Base64.getDecoder().decode(ID);
byte[] decrypted = cipher.doFinal(decodedBytes);
return new String(decrypted, StandardCharsets.UTF_8);
}
catch (Exception e) {
System.out.println("복호화 중 오류 발생하였습니다. ");
e.printStackTrace();
}
return "";
}
}
AES_tool.java
import java.util.Scanner;
class AES_tool {
static AES aes = new AES();
static Scanner sc = new Scanner(System.in);
static final int listMAX = 100;
static String[] list = new String[listMAX];
static int cnt = 0;
static int listSave(String s, String result){
if (s.equals("y") || s.equals("Y")) {
if (cnt < listMAX) {
list[cnt] = result;
System.out.println("저장 성공");
cnt+=1;
return 1;
}
else {
System.out.println("리스트가 꽉 차있어 암호화 결과를 저장할 수 없습니다.");
return 0;
}
}
else if (s.equals("n") || s.equals("N")) {
return 0;
}
return -1;
}
static void encrypt(){
String input;
String temp;
String select;
System.out.print("암호화할 텍스트를 입력하세요 >");
input = sc.next();
temp = aes.encrypt_AES(input);
System.out.println("[암호화]\n" + "입력:" + input + "\n결과:" + temp);
while(true) {
System.out.print("암호화 결과를 리스트에 저장하시겠습니까? [y/n] >");
select = sc.next();
int res = listSave(select, temp);
if (res > -1) {
break;
}
}
}
static void decrypt(){
String input;
System.out.print("복호화할 텍스트를 입력하세요 >");
input = sc.next();
System.out.println("[복호화]\n" + "입력:" + input + "\n결과:" + aes.decrypt_AES(input));
}
static void listDelete(int index){
list[index] = null;
for(int i = index; i < cnt-1; i++) {
list[i] = list[i+1];
}
cnt -= 1;
}
static int listEdit(int index) {
int select;
while (true) {
System.out.println("1.복호화 2.삭제 3.나가기");
System.out.print("명령 번호를 입력하세요 >");
select = sc.nextInt();
if (select == 1) {
System.out.println("[복호화]\n" + "입력:" + list[index] + "\n결과:" + aes.decrypt_AES(list[index]));
}
else if (select == 2) {
listDelete(index);
break;
}
else if (select == 3) {
break;
}
}
return 0;
}
static void listSelect(){
int number;
int index;
while (true) {
listView();
System.out.print("리스트 번호를 입력하세요 >");
number = sc.nextInt();
if (number > 0 && number <= cnt) {
index = number-1;
System.out.println("[선택 완료] " + list[index]);
if(0 == listEdit(index) || cnt == 0) {
break;
}
}
else {
System.out.println("리스트에 없는 번호입니다.");
}
}
}
static void listView(){
System.out.println("---------------------------------list---------------------------------");
if(cnt != 0) {
for (int i = 1; i <= cnt; i++) {
System.out.println(" [" + i + "] " + list[i - 1]);
}
}
else {
System.out.println(" 리스트가 비었습니다. ");
}
System.out.println("----------------------------------------------------------------------");
}
static int list_back(String s) {
if (s.equals("y") || s.equals("Y")) {
return 1;
}
return 0;
}
static void list() {
int select;
while(true) {
listView();
if(cnt == 0) {
while(true) {
System.out.print("나가시겠습니까?[y/n]");
String s = sc.next();
if(1 == list_back(s)) {
return;
}
}
}
System.out.println("1.리스트 선택 2.나가기");
System.out.print("번호를 입력하세요 >");
select = sc.nextInt();
if (select == 1) {
listSelect();
}
else if (select == 2) {
break;
}
}
}
void help() {
System.out.println("----------------------------------------------------------");
System.out.println("1.암호화 2.복호화 3.암호화된 리스트 보기 4.프로그램 정보 5.종료");
System.out.println("----------------------------------------------------------");
}
static void information() {
System.out.println("--------------------");
System.out.println("Name : AES-256\n");
System.out.println("Version : 1.0.0\n");
System.out.println("made by GUJAHYUN");
System.out.println("--------------------");
while(true) {
System.out.println("1. 나가기");
System.out.print("번호를 입력하세요. >");
int num = sc.nextInt();
if(num == 1){
break;
}
}
}
int start(int select) {
switch (select) {
case 1:
encrypt();
break;
case 2:
decrypt();
break;
case 3:
list();
break;
case 4:
information();
break;
case 5:
System.out.println("프로그램을 종료중..");
return -1;
default:
System.out.println("명령번호에 없는 번호있니다.");
break;
}
return 0;
}
}
Main.java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
AES_tool aes_tool = new AES_tool();
Scanner sc = new Scanner(System.in);
while(true) {
aes_tool.help();
System.out.print("번호를 입력하세요 >");
int select = sc.nextInt();
if(aes_tool.start(select) == -1) {
System.out.println("종료.");
return;
}
}
}
}
GITHUB
https://github.com/levhyun/JAVA_AES-256
GitHub - levhyun/JAVA_AES-256: AES-256 방식의 암호화/복호화 프로그램 구현
AES-256 방식의 암호화/복호화 프로그램 구현. Contribute to levhyun/JAVA_AES-256 development by creating an account on GitHub.
github.com
'Java' 카테고리의 다른 글
JAVA 간단한 암호화와 복호화 (0) | 2023.01.19 |
---|

오늘은 AES-256 암호화 방식을 이용하여 간단한 보안 프로그램을 구현해보도록 하겠습니다.
개념 다지기
일단 코드를 짜기전에 개념을 살펴보도록 하겠습니다.
첫번째는 AES입니다.
우리가 만들 보안 프로그램은 AES기반의 암호화 방식을 이용한 프로그램입니다.
"그럼 AES가 뭘까요??"
바로.. AES는 Advanced Encryption Standard의 약자로 고급 암호화 표준이란 뜻을 가지고 있습니다.
AES는 암호화 및 복호화에 동일한 키를 사용하는 대칭키 알고리즘으로
높은 안전성과 빠른 속도로 인해 양방향 암호화에서 가장 많이 사용되는 방식입니다.
AES 암호화의 종류는 AES-128, AES-192, AES-256이 있으며 뒤에 붙은 숫자는 키의 길이를 의미합니다.
우리가 사용할 암호화는 AES-256입니다.
AES-128 : 128bit = 16byte
AES-192 : 192bit = 24byte
AES-256 : 256bit = 32byte
"
음.. 그렇다면!
여기서 궁금한거!!
우리가 사용할 암호화 방식은 AES-256인데 이 AES-256은 양방향 암호화라고 했었지..
그럼 단방향 암호화는 없을까??
당연히 있지!!
"
단방향 암호화는 복호화을 할 수 없는 암호화 방식으로
패스워드 암호화에 사용되며 대표적으로 SHA-256이 있습니다.
다시 본론으로 돌아와서..
AES-256의 암호화 과정과 복호화 과정을 살펴보겠습니다.
일단 암호화
plain text -> pain bytes -> encrypt -> encrypted bytes -> encrypted base64 test
다음 복호화
encrypted base64 text -> encrypted bytes -> decrypt -> plain bytes -> plain text
일단 이정도로만 개념을 잡겠습니다.
그럼 바로 소스코드 보러가봅시다!!
소스코드
AES.java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
class AES {
//알고리즘
public static String algorithms = "AES/CBC/PKCS5Padding";
// AES/CBC/PKCS5Padding -> AES, CBC operation mode, PKCS5 padding scheme 으로 초기화된 Cipher 객체
//키
private final static String AESKey = "abcdefghabcdefghabcdefghabcdefgh"; //32byte
// 초기화 벡터
private final static String AESIv = "0123456789abcdef"; //16byte
// AES 암호화
String encrypt_AES(String ID){
try {
String result; // 암호화 결과 값을 담을 변수
// 암호화/복호화 기능이 포함된 객체 생성
Cipher cipher = Cipher.getInstance(algorithms);
// 키로 비밀키 생성
SecretKeySpec keySpec = new SecretKeySpec(AESKey.getBytes(), "AES");
// iv 로 spec 생성
IvParameterSpec ivParamSpec = new IvParameterSpec(AESIv.getBytes());
// 매번 다른 IV를 생성하면 같은 평문이라도 다른 암호문을 생성할 수 있다.
// 또한 IV는 암호를 복호화할 사람에게 미리 제공되어야 하고 키와 달리 공개되어도 상관없다
// 암호화 적용
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec);
// 암호화 실행
byte[] encrypted = cipher.doFinal(ID.getBytes(StandardCharsets.UTF_8)); // ID 암호화(인코딩 설정)
result = Base64.getEncoder().encodeToString(encrypted); // 암호화 인코딩 후 저장
return result;
}
catch (Exception e) {
System.out.println("암호화 중 오류 발생하였습니다. ");
e.printStackTrace();
}
return "";
}
// AES 복호화
String decrypt_AES(String ID){
try {
// 암호화/복호화 기능이 포함된 객체 생성
Cipher cipher = Cipher.getInstance(algorithms);
// 키로 비밀키 생성
SecretKeySpec keySpec = new SecretKeySpec(AESKey.getBytes(), "AES");
// iv 로 spec 생성
IvParameterSpec ivParamSpec = new IvParameterSpec(AESIv.getBytes());
// 매번 다른 IV를 생성하면 같은 평문이라도 다른 암호문을 생성할 수 있다.
// 또한 IV는 암호를 복호화할 사람에게 미리 제공되어야 하고 키와 달리 공개되어도 상관없다
// 암호화 적용
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec);
//암호 해석
byte[] decodedBytes = Base64.getDecoder().decode(ID);
byte[] decrypted = cipher.doFinal(decodedBytes);
return new String(decrypted, StandardCharsets.UTF_8);
}
catch (Exception e) {
System.out.println("복호화 중 오류 발생하였습니다. ");
e.printStackTrace();
}
return "";
}
}
AES_tool.java
import java.util.Scanner;
class AES_tool {
static AES aes = new AES();
static Scanner sc = new Scanner(System.in);
static final int listMAX = 100;
static String[] list = new String[listMAX];
static int cnt = 0;
static int listSave(String s, String result){
if (s.equals("y") || s.equals("Y")) {
if (cnt < listMAX) {
list[cnt] = result;
System.out.println("저장 성공");
cnt+=1;
return 1;
}
else {
System.out.println("리스트가 꽉 차있어 암호화 결과를 저장할 수 없습니다.");
return 0;
}
}
else if (s.equals("n") || s.equals("N")) {
return 0;
}
return -1;
}
static void encrypt(){
String input;
String temp;
String select;
System.out.print("암호화할 텍스트를 입력하세요 >");
input = sc.next();
temp = aes.encrypt_AES(input);
System.out.println("[암호화]\n" + "입력:" + input + "\n결과:" + temp);
while(true) {
System.out.print("암호화 결과를 리스트에 저장하시겠습니까? [y/n] >");
select = sc.next();
int res = listSave(select, temp);
if (res > -1) {
break;
}
}
}
static void decrypt(){
String input;
System.out.print("복호화할 텍스트를 입력하세요 >");
input = sc.next();
System.out.println("[복호화]\n" + "입력:" + input + "\n결과:" + aes.decrypt_AES(input));
}
static void listDelete(int index){
list[index] = null;
for(int i = index; i < cnt-1; i++) {
list[i] = list[i+1];
}
cnt -= 1;
}
static int listEdit(int index) {
int select;
while (true) {
System.out.println("1.복호화 2.삭제 3.나가기");
System.out.print("명령 번호를 입력하세요 >");
select = sc.nextInt();
if (select == 1) {
System.out.println("[복호화]\n" + "입력:" + list[index] + "\n결과:" + aes.decrypt_AES(list[index]));
}
else if (select == 2) {
listDelete(index);
break;
}
else if (select == 3) {
break;
}
}
return 0;
}
static void listSelect(){
int number;
int index;
while (true) {
listView();
System.out.print("리스트 번호를 입력하세요 >");
number = sc.nextInt();
if (number > 0 && number <= cnt) {
index = number-1;
System.out.println("[선택 완료] " + list[index]);
if(0 == listEdit(index) || cnt == 0) {
break;
}
}
else {
System.out.println("리스트에 없는 번호입니다.");
}
}
}
static void listView(){
System.out.println("---------------------------------list---------------------------------");
if(cnt != 0) {
for (int i = 1; i <= cnt; i++) {
System.out.println(" [" + i + "] " + list[i - 1]);
}
}
else {
System.out.println(" 리스트가 비었습니다. ");
}
System.out.println("----------------------------------------------------------------------");
}
static int list_back(String s) {
if (s.equals("y") || s.equals("Y")) {
return 1;
}
return 0;
}
static void list() {
int select;
while(true) {
listView();
if(cnt == 0) {
while(true) {
System.out.print("나가시겠습니까?[y/n]");
String s = sc.next();
if(1 == list_back(s)) {
return;
}
}
}
System.out.println("1.리스트 선택 2.나가기");
System.out.print("번호를 입력하세요 >");
select = sc.nextInt();
if (select == 1) {
listSelect();
}
else if (select == 2) {
break;
}
}
}
void help() {
System.out.println("----------------------------------------------------------");
System.out.println("1.암호화 2.복호화 3.암호화된 리스트 보기 4.프로그램 정보 5.종료");
System.out.println("----------------------------------------------------------");
}
static void information() {
System.out.println("--------------------");
System.out.println("Name : AES-256\n");
System.out.println("Version : 1.0.0\n");
System.out.println("made by GUJAHYUN");
System.out.println("--------------------");
while(true) {
System.out.println("1. 나가기");
System.out.print("번호를 입력하세요. >");
int num = sc.nextInt();
if(num == 1){
break;
}
}
}
int start(int select) {
switch (select) {
case 1:
encrypt();
break;
case 2:
decrypt();
break;
case 3:
list();
break;
case 4:
information();
break;
case 5:
System.out.println("프로그램을 종료중..");
return -1;
default:
System.out.println("명령번호에 없는 번호있니다.");
break;
}
return 0;
}
}
Main.java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
AES_tool aes_tool = new AES_tool();
Scanner sc = new Scanner(System.in);
while(true) {
aes_tool.help();
System.out.print("번호를 입력하세요 >");
int select = sc.nextInt();
if(aes_tool.start(select) == -1) {
System.out.println("종료.");
return;
}
}
}
}
GITHUB
https://github.com/levhyun/JAVA_AES-256
GitHub - levhyun/JAVA_AES-256: AES-256 방식의 암호화/복호화 프로그램 구현
AES-256 방식의 암호화/복호화 프로그램 구현. Contribute to levhyun/JAVA_AES-256 development by creating an account on GitHub.
github.com
'Java' 카테고리의 다른 글
JAVA 간단한 암호화와 복호화 (0) | 2023.01.19 |
---|