Skip to content

Latest commit

Β 

History

History
346 lines (298 loc) Β· 12.5 KB

File metadata and controls

346 lines (298 loc) Β· 12.5 KB

νŒ¨μŠ€μ›Œλ“œ 평문 μ €μž₯

μ •μ˜

νŒ¨μŠ€μ›Œλ“œλ₯Ό λΉ„λ‘―ν•œ μ€‘μš”λ°μ΄ν„°λ₯Ό μ•”ν˜Έν™”λ˜μ§€ μ•Šμ€ 평문 ν…μŠ€νŠΈμ˜ ν˜•νƒœλ‘œ μ €μž₯되면 μ•”ν˜Έκ°€ 외뢀에 직접 λ“œλŸ¬λ‚  수 μžˆμ–΄ 기밀성이 보μž₯λ˜μ§€ λͺ»ν•˜κ³  μ•”ν˜Έκ°€ μ €μž₯된 νŒŒμΌμ— μ ‘κ·Όν•  수 μžˆλŠ” μ‚¬λžŒμ΄λ©΄ λˆ„κ΅¬λ‚˜ μ•”ν˜Έλ₯Ό μ•Œμ•„λ‚Ό 수 μžˆμ–΄ 무결성 λ˜ν•œ 보μž₯λ˜μ§€ λͺ»ν•œλ‹€.

  • κΈ°λ°€μ„± : λΉ„μΈκ°€μžλ“€μ€ μ •λ³΄μ˜ λ‚΄μš©μ„ μ•Œ 수 μ—†κ²Œ ν•΄μ•Ό ν•œλ‹€λŠ” λ³΄μ•ˆ 원칙
  • 무결성 : ν—ˆκ°€λ˜μ§€ μ•Šμ€ μžκ°€(λ˜λŠ” ν—ˆκ°€λ˜μ§€ μ•Šμ€ λ°©μ‹μœΌλ‘œ) 정보λ₯Ό λ³€κ²½, μ‚­μ œ, μƒμ„±ν•˜λŠ” 것을 λ³΄ν˜Έν•΄μ•Όν•œλ‹€λŠ” λ³΄μ•ˆ 원칙


μ•ˆμ „ν•œ μ½”λ”© 기법

κ°œμΈμ •λ³΄, κΈˆμœ΅μ •λ³΄, νŒ¨μŠ€μ›Œλ“œ λ“± μ€‘μš”μ •λ³΄λ₯Ό μ €μž₯ν•  λ•ŒλŠ” λ°˜λ“œμ‹œ μ•”ν˜Έν™”ν•˜μ—¬ μ €μž₯ν•œλ‹€. μ€‘μš”μ •λ³΄λ₯Ό 읽고 μ“Έ κ²½μš°μ—λŠ” ν—ˆκ°€λœ μ‚¬μš©μžλ§Œμ΄ μ‚¬μš©μ •λ³΄μ— μ ‘κ·Όν•˜λ„λ‘ 인증 과정을 거쳐야 ν•œλ‹€.



java 예제

νŒ¨μŠ€μ›Œλ“œ μ •λ³΄μ˜ DB μ €μž₯

  • μ•ˆμ „ν•˜μ§€ λͺ»ν•œ μ½”λ“œ : 인증을 ν†΅κ³Όν•œ μ‚¬μš©μžμ˜ νŒ¨μŠ€μ›Œλ“œ 정보가 ν‰λ¬ΈμœΌλ‘œ DB에 μ €μž₯λœλ‹€.
String id = request.getParameter("id");
//외뢀값에 μ˜ν•΄ νŒ¨μŠ€μ›Œλ“œ 정보λ₯Ό μ–»κ³  μžˆλ‹€.
String pwd = request.getParameter("pwd");

// SQLλ¬Έ, ? : λ³€μˆ˜κ°€ λ“€μ–΄κ°ˆ 자리 
String sql = "insert into customer(id, pwd, name, ssn, zipcode, addr)"
+"values(?, ?, ?, ?, ?, ?)"
//μ§€μ •λœ SQL λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜λŠ” PreparedStatement μΈμŠ€ν„΄μŠ€ 생성
PreparedStatement stmt = con.prepareStatement(sql);

//SQL λ¬Έμ—μ„œ ? 값에 λŒ€μ‘λ˜λŠ” 값을 지정함
stmt.setString(1,id);
stmt.setString(2, pwd);
....
//μž…λ ₯받은 νŒ¨μŠ€μ›Œλ“œκ°€ ν‰λ¬ΈμœΌλ‘œ DB에 μ €μž₯λ˜μ–΄ μ•ˆμ „ν•˜μ§€ μ•Šλ‹€. 
stmt.executeUpdate();


  • μ•ˆμ „ν•œ μ½”λ“œ : νŒ¨μŠ€μ›Œλ“œ λ“± μ€‘μš” 데이터λ₯Ό ν•΄μ‰¬κ°’μœΌλ‘œ λ³€ν™˜ν•˜μ—¬ μ €μž₯ν•˜κ³  μžˆλ‹€.
String id = request.getParameter("id"); 
// 외뢀값에 μ˜ν•΄ νŒ¨μŠ€μ›Œλ“œ 정보λ₯Ό μ–»κ³  μžˆλ‹€.
String pwd = request.getParameter("pwd");

// νŒ¨μŠ€μ›Œλ“œλ₯Ό μ†”νŠΈκ°’μ„ ν¬ν•¨ν•˜μ—¬ SHA-256 ν•΄μ‹œλ‘œ λ³€κ²½ν•˜μ—¬ μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•œλ‹€. 
//SHA-256 ν˜•μ‹μœΌλ‘œ μ•”ν˜Έν™”ν•  객체 생성
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.reset();
//salt : ν•΄μ‹œν•¨μˆ˜μ—μ„œ μΆ”κ°€μž…λ ₯으둜 μ‚¬μš©λ˜λŠ” λžœλ€λ°μ΄ν„°  
md.update(salt);

//데이터 μ „μ²˜λ¦¬
byte[] hashInBytes = md.digest(pwd.getBytes()); 
StringBuilder sb = new StringBuilder();
//μ „μ²˜λ¦¬ν•œ 데이터(λ°”μ΄νŠΈ)λ₯Ό ν—₯μ‚¬κ°’μœΌλ‘œ λ³€ν™˜
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b)); }
pwd = sb.toString();
......

// SQLλ¬Έ, ? : λ³€μˆ˜κ°€ λ“€μ–΄κ°ˆ 자리
String sql = " insert into customer(id, pwd, name, ssn, zipcode, addr)"
+ " values (?, ?, ?, ?, ?, ?)";
//μ§€μ •λœ SQL λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜λŠ” PreparedStatement μΈμŠ€ν„΄μŠ€ 생성
PreparedStatement stmt = con.prepareStatement(sql); 
//SQL λ¬Έμ—μ„œ ? 값에 λŒ€μ‘λ˜λŠ” 값을 지정함
stmt.setString(1, id);
stmt.setString(2, pwd);
......
//μž…λ ₯받은 νŒ¨μŠ€μ›Œλ“œκ°€ SHA-256 μ•Œκ³ λ¦¬μ¦˜μ„ 톡해 ν•΄μ‹œκ°’μœΌλ‘œ μ €μž₯λ˜μ–΄μ„œ μ•ˆμ „ν•˜λ‹€. 
stmt.executeUpdate();

πŸ’šμ½”λ“œ μΆ”κ°€ μ„€λͺ…πŸ’š
  • ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ—κ²Œ 무언가λ₯Ό μš”μ²­ν•˜λ©΄ μ„œλ²„λŠ” μš”μ²­μ— ν•΄λ‹Ήν•˜λŠ” 것을 μ‘λ‹΅ν•΄μ£ΌλŠ” κ΅¬μ‘°μž„.

  • ν•΄λ‹Ή μ½”λ“œλŠ” Servlet μˆ˜μ€€μ—μ„œ μ‚¬μš©μžμ˜ μš”μ²­μ— λŒ€ν•΄ νŒŒλΌλ―Έν„°λ₯Ό 톡해 μ‚¬μš©μž 정보λ₯Ό μ–»μ–΄μ„œ DB에 쿼리λ₯Ό λ‚ λ € μ‚¬μš©μž 정보λ₯Ό DB에 μ €μž₯ν•˜κ³  μžˆλ‹€.

  • Servlet : μžλ°” ν”Œλž«νΌμ—μ„œ 동적인 웹을 κ°œλ°œν•  λ•Œ μ‚¬μš©ν•˜λŠ” 클래슀둜, ν΄λΌμ΄μ–ΈνŠΈ μš”μ²­μ„ μ²˜λ¦¬ν•˜κ³  κ·Έ κ²°κ³Όλ₯Ό λ‹€μ‹œ ν΄λΌμ΄μ–ΈνŠΈμ—μ„Έ μ „μ†‘ν•˜λŠ” μ„œλ²„μ˜ κΈ°λŠ₯을 ν•΄μ£ΌλŠ” μžλ°” ν”„λ‘œκ·Έλž¨


πŸ’šμ‚¬μš©λœ ν΄λž˜μŠ€μ™€ λ©”μ†Œλ“œπŸ’š
  • request

  • PreparedStatement : SQL ꡬ문을 μ‹€ν–‰μ‹œν‚€λŠ” μ—­ν• 

    • executeUpdate() : λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 데이터λ₯Ό μΆ”κ°€, μ‚­μ œ, μˆ˜μ •ν•˜λŠ” SQL 문을 μ‹€ν–‰
      PreparedStatement (Java SE 11 & JDK 11 )
  • MessageDigest : μ•”ν˜Έν™”λ₯Ό μœ„ν•œ 클래슀


πŸ’šSHA-256πŸ’š
  • μ•”ν˜Έν™” ν•΄μ‹œ ν•¨μˆ˜μ˜ ν•œ μ’…λ₯˜

  • ν•΄μ‹œ ν•¨μˆ˜ : μž„μ˜μ˜ 길이의 정보λ₯Ό μž…λ ₯으둜 λ°›μ•„, κ³ μ •λœ 길이의 μ•”ν˜Έλ¬Έ(ν•΄μ‹œκ°’)을 μΆ©λ ₯ν•˜λŠ” μ•”ν˜ΈκΈ°μˆ 

  • 데이터 μ „μ²˜λ¦¬, μ΄ˆκΈ°κ°’ μ„€μ •, ν•΄μ‹± μ—°μ‚° λ‹¨κ³„λ‘œ 이루어져 있음

    • μž…λ ₯된 데이터λ₯Ό μ „μ²˜λ¦¬ν•œλ‹€.
    • μ΄ˆκΈ°κ°’μ„ μ„€μ •ν•œλ‹€. (μ΄ˆκΈ°κ°’ : μ•Œκ³ λ¦¬μ¦˜μ˜ 결과둜 λ‚˜μ˜¬ ν•΄μ‹œκ°’μ˜ μ΄ˆκΈ°κ°’)
    • μ΄ˆκΈ°κ°’μ— μž…λ ₯된 데이터λ₯Ό μ΄μš©ν•΄ ν•΄μ‹± 연산을 μˆ˜ν–‰ν•œλ‹€.
  • SHA-256 μ½”λ“œ


C 예제

1. νŒŒμΌμ—μ„œ μ½μ–΄μ˜¨ νŒ¨μŠ€μ›Œλ“œμ™€ DB μ—°κ²°

  • μ•ˆμ „ν•˜μ§€ λͺ»ν•œ μ½”λ“œ : νŒ¨μŠ€μ›Œλ“œλ₯Ό νŒŒμΌμ—μ„œ μ½μ–΄μ„œ 직접 DB 연결에 μ‚¬μš©ν•˜κ³  μžˆλ‹€. 이것은 νŒ¨μŠ€μ›Œλ“œλ₯Ό μ•”ν˜Έν™” ν•˜κ³  μžˆμ§€ μ•ŠμŒμ„ μ˜λ―Έν•œλ‹€.
int dbaccess()
{
  FILE * fp; char* server = "DBserver";
	char passwd[20];
	char user[20];
	SQLHENV henv;
	SQLHDBC hdbc;
	
	//config νŒŒμΌμ„ μ—΄μ–΄μ„œ ν•΄λ‹Ή μŠ€νŠΈλ¦Όμ—μ„œ user, passwd μ½μ–΄μ˜΄
	fp = fopen("config", "r");
	fgets(user, sizeof(user), fp);
	fgets(passwd, sizeof(passwd), fp);
	fclose(fp);
	
	//DB와 μ—°κ²°
	SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
	SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
	SQLConnect(hdbc, (SQLCHAR*)server, (SQLSMALLINT)strlen(server), (SQLCHAR*)user, (SQLSMALLINT)strlen(user),
	/*νŒŒμΌλ‘œλΆ€ν„° νŒ¨μŠ€μ›Œλ“œλ₯Ό ν‰λ¬ΈμœΌλ‘œ 읽어듀이고 μžˆλ‹€*/
	(SQLCHAR*)passwd, 
	(SQLSMALLINT)strlen(passwd));
	return  0;
 }


  • μ•ˆμ „ν•œ μ½”λ“œ : μ™ΈλΆ€μ—μ„œ μž…λ ₯된 νŒ¨μŠ€μ›Œλ“œλŠ” κ²€μ¦μ˜ 과정을 κ±°μ³μ„œ μ‚¬μš©ν•˜μ—¬μ•Ό ν•œλ‹€.
int dbaccess()
{
   FILE * fp;
   char* server = "DBserver";
   char passwd[20];
   char user[20];
   char* verifiedPwd;
   SQLHENV henv;
   SQLHDBC hdbc;

   //config νŒŒμΌμ„ μ—΄μ–΄μ„œ ν•΄λ‹Ή μŠ€νŠΈλ¦Όμ—μ„œ user, passwd μ½μ–΄μ˜΄
   fp = fopen("config", "r");
   fgets(user, sizeof(user), fp);
   fgets(passwd, sizeof(passwd), fp);
   fclose(fp);

   //νŒ¨μŠ€μ›Œλ“œ 검증 κ³Όμ •
   verifiedPwd = verify(passwd);
   SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
   SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
   SQLConnect(hdbc, (SQLCHAR*)server, (SQLSMALLINT)strlen(server), (SQLCHAR*)user, (SQLSMALLINT)strlen(user),
   /*νŒŒμΌλ‘œλΆ€ν„° μ•”ν˜Έν™”λœ νŒ¨μŠ€μ›Œλ“œλ₯Ό 읽어듀이고 μžˆλ‹€.*/ 
   (SQLCHAR*)verifiedPwd,(SQLSMALLINT)strlen(verifiedPwd)); 
   return  0;
}

πŸ’šμ‚¬μš©λœ ν•¨μˆ˜πŸ’š

2. ν‚€λ³΄λ“œλ‘œλΆ€ν„° μ½μ–΄μ˜¨ νŒ¨μŠ€μ›Œλ“œμ™€ DB

  • μ•ˆμ „ν•˜μ§€ λͺ»ν•œ μ½”λ“œ : μ‚¬μš©μžλͺ…κ³Ό νŒ¨μŠ€μ›Œλ“œλ₯Ό ν‚€λ³΄λ“œλ‘œλΆ€ν„° μ½μ–΄μ„œ λ¬Έμžμ—΄μ„ κ·ΈλŒ€λ‘œ DB 연결에 μ‚¬μš©ν•˜κ³  μžˆλ‹€.
const char  * GetParameter(const char  * queryString,  const char  * key);
int main(void)
{
   const  char* COMMAND_PARAM = "command";
   const  char* GET_USER_INFO_CMD = "get_user_info";
   
   char* queryStr;
   queryStr = getenv("QUERY_STRING");
   if (queryStr == NULL)
   {
   	// Error 처리 
   	...
   }
   char* command = GetParameter(queryStr, COMMAND_PARAM);
   if (!strcmp(command, GET_USER_INFO_CMD))
   {
   	const char* USER_ID_PARAM = "user_id";
   	const  char* PASSWORD_PARAM = "password";
   	const char* userId = GetParameter(queryStr, USER_ID_PARAM);
   	const char* password = GetParameter(queryStr, PASSWORD_PARAM);
   	
   	...
   	char* dbUserId, * dbUserPassword;
   	
   	//μ•”ν˜Έν™”λ˜μ§€ μ•Šμ€ μ‚¬μš©μž 정보λ₯Ό κ·ΈλŒ€λ‘œ DB연결에 μ‚¬μš©ν•˜κ³  μžˆμ–΄μ„œ μ•ˆμ „ν•˜μ§€ λͺ»ν•˜λ‹€. 
   	loadDbUserInfo(&dbUserId, &dbUserPassword);
   	SQLRETURN   retcode = SQLConnect(hdbc, (SQLCHAR*)"173.234.56.78", SQL_NTS, (SQLCHAR*)dbUserId, strlen(dbUserId), dbUserPassword, strlen(dbUserPassword));
   	...
   	free(userId);
   	free(password);
   }
   return EXIT_SUCCESS; 
}
void  loadDbUserInfo(char** userId, char** password)    
{
   const int MAX_USER_LENGTH = 8;
   const int MAX_PASSWORD_LENGTH = 16;
   *userId = (char*)malloc(MAX_USER_LENGTH);
   *password = (char*)malloc(MAX_PASSWORD_LENGTH);
   FILE * fp = fopen("dbUserInfo.cfg", "r");
   fscanf(fp, "%s", *userId);
   fscanf(fp, "%s", *password);
}


  • μ•ˆμ „ν•œ μ½”λ“œ : μ™ΈλΆ€μ—μ„œ μž…λ ₯된 μ‚¬μš©μžλͺ…κ³Ό νŒ¨μŠ€μ›Œλ“œλ₯Ό loadDbUserInfo ν•¨μˆ˜μ—μ„œ OAEPνŒ¨λ”©μ„ μ‚¬μš©ν•œ RSA μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ μ•”ν˜Έν™”ν•œ ν›„ DB연결에 μ‚¬μš©ν•˜κ³  μžˆλ‹€.
const char  * GetParameter(const char  * queryString,  const char  * key);
const Key  decryptPassword="we37kor$^jkl315!#^!";  //private Key

int main(void)
{
	const  char  *  COMMAND_PARAM  =  "command";
	const  char *  GET_USER_INFO_CMD = "get_user_info";
	
	char * queryStr;
	queryStr = getenv("QUERY_STRING");
	if (queryStr == NULL) 
	{
		// Error  
		...
	}
	char * command = GetParameter(queryStr, COMMAND_PARAM);
	if (!strcmp(command, GET_USER_INFO_CMD)) 
	{
		const char * USER_ID_PARAM = "user_id";
		const  char  *  PASSWORD_PARAM  =  "password";
		const char * userId  =  GetParameter(queryStr, USER_ID_PARAM);
		const char * password = GetParameter(queryStr, PASSWORD_PARAM);
		...
		char * dbUserId, * dbUserPassword;
		
		//loadDbUserInfoλ₯Ό 톡해 μ•”ν˜Έν™”λœ μ‚¬μš©μž 정보λ₯Ό DB연결에 μ‚¬μš©ν•˜κ³  μžˆλ‹€. 
		loadDbUserInfo(&dbUserId, &dbUserPassword);
		SQLRETURN   retcode    =    SQLConnect(hdbc,    (SQLCHAR*)    "173.234.56.78",    SQL_NTS, (SQLCHAR*) dbUserId, strlen(dbUserId), dbUserPassword, strlen(dbUserPassword));
		...
		free(userId);
		free(password);
	}
	return EXIT_SUCCESS; 32:     
}
void loadDbUserInfo(char  **  userId, char ** password)
{
	const int MAX_USER_LENGTH = 8;
	const int MAX_PASSWORD_LENGTH  = 16;
	*userId = (char *)malloc(MAX_USER_LENGTH);
	*password = (char *)malloc(MAX_PASSWORD_LENGTH);
	
	FILE * fp = fopen("dbUserInfo.cfg","r");
	fscanf(fp, "%s", *userId);
	fscanf(fp, "%s", *password);
        //RSA μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ μ•”ν˜Έν™”
	RSA_private_decrypt(strlen(decryptPassword),      decryptPassword,       *password, 
	RSA_PKCS1_OAEP_PADDDING);
}
πŸ’šμ‚¬μš©λœ ν•¨μˆ˜πŸ’š

πŸ’šRSA μ•”ν˜Έν™” μ•Œκ³ λ¦¬μ¦˜πŸ’š
  • μ•”ν˜Έν™”μ— μ‚¬μš©ν•˜λŠ” 킀와 λ³΅ν˜Έν™”μ— μ‚¬μš©ν•˜λŠ” ν‚€κ°€ λ‹€λ₯Έ λΉ„λŒ€μΉ­ν‚€ μ•Œκ³ λ¦¬μ¦˜

  • κ³΅κ°œν‚€μ™€ κ°œμΈν‚€λ₯Ό 쌍으둜 μ‚¬μš©

    • κ³΅κ°œν‚€ : 외뢀에 κ³΅κ°œν•  수 μžˆλŠ” ν‚€
    • κ°œμΈν‚€ : ν‚€μ˜ μ†Œμœ μžλ§Œ μ•Œκ³  μžˆμ–΄μ•Ό ν•˜λŠ” ν‚€
    • 본인 인증의 λͺ©μ μ„ κ°€μ§ˆ λ•ŒλŠ” κ°œμΈν‚€λ‘œ μ•”ν˜Έν™”ν•˜κ³  κ³΅κ°œν‚€λ‘œ λ³΅ν˜Έν™”ν•œλ‹€.
    • 기밀성을 λͺ©μ μœΌλ‘œ ν•  λ•ŒλŠ” κ³΅κ°œν‚€λ‘œ μ•”ν˜Έν™”ν•˜κ³  κ°œμΈν‚€λ‘œ λ³΅ν˜Έν™”ν•œλ‹€.
  • κ³΅κ°œν‚€μ™€ κ°œμΈν‚€λ₯Ό λ§Œλ“œλŠ” κ³Όμ •κ³Ό λͺ¨λ“ˆλŸ¬ 연산을 톡해 μ•”ν˜Έν™”, λ³΅ν˜Έν™”ν•˜λŠ” 과정이 ν•„μš”ν•˜λ‹€.



좜처
γ€Žμ „μžμ •λΆ€ SW 개발, 운영자λ₯Ό μœ„ν•œ C μ‹œνμ–΄ μ½”λ”© κ°€μ΄λ“œγ€, ν–‰μ •μžμΉ˜λΆ€, ν•œκ΅­ 인터넷진ν₯원
γ€Žμ „μžμ •λΆ€ SW 개발, 운영자λ₯Ό μœ„ν•œ μ†Œν”„νŠΈμ›¨μ–΄ κ°œλ°œλ³΄μ•ˆ κ°€μ΄λ“œγ€, ν–‰μ •μ•ˆμ „λΆ€, ν•œκ΅­ 인터넷진ν₯원
https://docs.oracle.com/javaee/7/api/overview-summary.html
https://docs.microsoft.com/ko-kr/documentation/
https://seed.kisa.or.kr/kisa/Board/21/detailView.do
https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html
https://m.blog.naver.com/ka28/221985380809