본문 바로가기

알고리즘/문제풀이 - JAVA

Base64 Encoder & Decoder (암호화, 복호화)

ktko.tistory.com/entry/JAVA-BASE64-%EC%9D%B8%EC%BD%94%EB%94%A9-%EB%94%94%EC%BD%94%EB%94%A9%ED%95%98%EA%B8%B0

 

fruitdev.tistory.com/79

 

 

출처 위키
출처 위키

Base 64에는 어떤 문자와 기호를 쓰느냐에 따라 여러 변종이 있지만, 잘 알려진 것은 모두 처음 62개는 알파벳 A-Z, a-z와 0-9를 사용하고 있으며 마지막 두 개를 어떤 기호를 쓰느냐의 차이만 있다.

 

인코딩된 문자열은 알파벳 대소문자와 숫자, 그리고 "+", "/" 기호 64개로 이루어지며, "="는 끝을 알리는 코드로 쓰인다.

 

우선 24비트 버퍼에 위쪽(MSB)부터 한 바이트씩 세 바이트를 집어넣는다.

그리고 남은 바이트가 3바이트 미만이라면, 버퍼의 남은 부분은 0으로 채워넣게 된다.

그리고, 버퍼의 위쪽부터 6비트씩 잘라 그 값을 읽어,

다음에 정렬된 64개 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"의 문자 중에서 읽은 값 번째 문자를 골라 출력한다.

만약 입력된 바이트가 하나라면 출력 중 두 개만이 사용되고 나머지 둘은 "="으로 패딩되며,

입력된 바이트가 둘이라면 출력 중 세 개 만이 사용되고 나머지 하나는 "="으로 패딩되게 된다.

이것은 원본으로 되돌릴 때 원본에는 없던 비트가 생기는 것을 방지하기 위함이다.

이 과정을 입력 데이터가 끝날 때까지 반복하면 인코딩이 된다.

 

 Incoder 

import java.util.Scanner;
import java.util.StringTokenizer;

public class Base64_Incoder_Scanner {
	public static void main(String[] args) {
		String[] base64=new String[64];
		String base="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		for (int i=0;i<base64.length;i++) {
			base64[i]=base.substring(i, i+1);
		}
		
		Scanner sc = new Scanner(System.in);
		int T; // 케이스 반복 횟수
		//T = sc.nextInt();
		String inputs; // 입력받은 문자열
		char c; // 입력받은 문자열을 한글자씩 분리할때 담는 char
		// (int) c; c를 아스키 코드로 변환
		String code; // c를 2진수로 변환한 값(c를 아스키 코드로 변환한 것을 2진수로 변환한 것!)
		String total_code = ""; // c를 모아 만든 것으로 최종적으로 입력받은 문자열을 2진수로 변환한 값이 저장됨
		int bitode; // total_code(2진수)를 6자리씩 끊어 10진수로 계산한 수, binary to decimal
		char atoword; // 2진수를 6자리씩 끊어 만든 10진수(아스키코드)를 char 타입으로 변환
		String outputs; // 출력해줄 문자열
		// T = Integer.parseInt(br.readLine().trim());
		for (int test_case = 0; test_case < 1; test_case++) {
			inputs = sc.nextLine();
			//System.out.println("inputs="+inputs);
			for (int i = 0; i < inputs.length(); i++) {
				int j = 0;
				c = inputs.charAt(i); // 입력받은 문자열중 한 글자를 의미
				code = Integer.toBinaryString((int) c);
				for (int cc=0;cc<8-code.length();cc++) {
					total_code +=0;
				}
				total_code +=code; // 2진수로 변환된 코드!
				//total_code+=" ";
			}

			int t=0; outputs="";
			for (int i=t;i<inputs.length()*8/6;i++) {
				bitode=0;
				bitode+=Integer.parseInt(total_code.substring(t, t+1))*32;
				bitode+=Integer.parseInt(total_code.substring(t+1, t+2))*16;
				bitode+=Integer.parseInt(total_code.substring(t+2, t+3))*8;
				bitode+=Integer.parseInt(total_code.substring(t+3, t+4))*4;
				bitode+=Integer.parseInt(total_code.substring(t+4, t+5))*2;
				bitode+=Integer.parseInt(total_code.substring(t+5, t+6))*1;
				outputs+=base64[bitode];
				t+=6;
				
			}
			System.out.print("#" + (test_case + 1) + " ");
			System.out.println(outputs);
		}

	}
}

 

Sweet dreams are made of this. Who am I to disagree? I traveled the world and the seven seas. Everybody's looking for something

인코딩⇓         ⇑디코딩

U3dlZXQgZHJlYW1zIGFyZSBtYWRlIG9mIHRoaXMuIFdobyBhbSBJIHRvIGRpc2FncmVlPyBJIHRyYXZlbGVkIHRoZSB3b3JsZCBhbmQgdGhlIHNldmVuIHNlYXMuIEV2ZXJ5Ym9keSdzIGxvb2tpbmcgZm9yIHNvbWV0aGluZ 

 

 

 Encoder 

import java.util.Scanner;

public class  Base64_Encoder_Scanner {

	public static void main(String[] args) {
		char[] base64=new char[64];
		String base="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		for (int i=0;i<base64.length;i++) {
			base64[i]=base.charAt(i);
		}
		
		Scanner sc = new Scanner(System.in);
		int T; // 케이스 반복 횟수
		//T = sc.nextInt();
		String inputs; // 입력받은 문자열
		char c; // 입력받은 문자열을 한글자씩 분리할때 담는 char
		int cnum=-1; // base64에 담겨있는 c의 index 번호
		String code; //  
		String total_code;  
		int bitode; //  
		char atoword; //  
		
		String outputs; // 출력해줄 문자열
		T = sc.nextInt();
		for (int test_case = 0; test_case < T; test_case++) {
			inputs = sc.next(); // 문자열 입력받음
			//System.out.println("inputs="+inputs);
			total_code="";
			for (int i = 0; i < inputs.length(); i++) {
				int j = 0;
				c = inputs.charAt(i); // 입력받은 문자열중 한 글자를 의미
				for (int cc=0;cc<base64.length;cc++) {
					if(c==base64[cc]) {
						cnum=cc;
					}
				}
				
				code = Integer.toBinaryString(cnum);
				for (int cc=0;cc<6-code.length();cc++) {
					total_code +=0;
				}
				
				total_code +=code; // 2진수로 변환된 코드!
				//total_code+=" ";
			}
			//System.out.println("total_code="+total_code);
			//System.out.println("total_code길이="+total_code.length());
			int t=0; outputs="";
			for (int i=t;i<total_code.length()/8;i++) {
				bitode=0;
				bitode+=Integer.parseInt(total_code.substring(t, t+1))*128;
				bitode+=Integer.parseInt(total_code.substring(t+1, t+2))*64;
				bitode+=Integer.parseInt(total_code.substring(t+2, t+3))*32;
				bitode+=Integer.parseInt(total_code.substring(t+3, t+4))*16;
				
				bitode+=Integer.parseInt(total_code.substring(t+4, t+5))*8;
				bitode+=Integer.parseInt(total_code.substring(t+5, t+6))*4;
				bitode+=Integer.parseInt(total_code.substring(t+6, t+7))*2;
				bitode+=Integer.parseInt(total_code.substring(t+7, t+8))*1;
				//System.out.println(bitode+" ");
				atoword=(char)bitode;
				outputs+=Character.toString(atoword);
				t+=8;
				
			}
			System.out.print("#" + (test_case + 1) + " ");
			System.out.println(outputs);
			//System.out.println(total_code);
		}
	}
}

 

 Java Util 

import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;

public class Base64_java_util {
	public static void base64() {
		String text="Sweet dreams are made of this.";
		byte[] textBytes=text.getBytes();
		
		// Base64 인코딩
		Encoder encoder=Base64.getEncoder();
		byte[] encodedBytes=encoder.encode(textBytes);
		
		// Base64 디코딩
		Decoder decoder=Base64.getDecoder();
		byte[] decodedBytes=decoder.decode(encodedBytes);
		
		System.out.println("원문\t : "+text);
		System.out.println("인코딩 후\t : "+new String(encodedBytes));
		System.out.println("디코딩 후\t : "+new String(decodedBytes));
	}
	public static void main(String[] args) {
		base64();
	}
}

 

 + 아파치에서 제공하는 라이브러리도 있음