728x90
반응형
728x90
반응형

ERP와 연동하는 기능이 있는데 ERP를 고도화하면서 DB 버전이 업그레이드 되었습니다.

(window server 2008 -> SQL Server 2017, ERP는 mssql을 사용)

아래와 같은 문제가 발생하여 기존 연동하는 기능이 안되는 증상이 발생했습니다.

 

오류 내용

com.microsoft.sqlserver.jdbc.SQLServerException: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Sever로 보안 연결을 설정할 수 없습니다. 원인: java.lang.RuntimeException: Could not generate DH keypair

상세 오류

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Sever로 보안 연결을 설정할 수 없습니다. 원인: java.lang.RuntimeException: Could not generate DH keypair
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(Unknown Source)
	at com.microsoft.sqlserver.jdbc.TDSChannel.throwSSLConnectionFailed(Unknown Source)
	at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.loginWithoutFailover(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(Unknown Source)
	at com.caucho.sql.DriverConfig.createDriverConnection(DriverConfig.java:596)
	at com.caucho.sql.ManagedConnectionImpl.initDriverConnection(ManagedConnectionImpl.java:242)
	at com.caucho.sql.ManagedConnectionImpl.<init>(ManagedConnectionImpl.java:131)
	at com.caucho.sql.ManagedFactoryImpl.createManagedConnection(ManagedFactoryImpl.java:121)
	at com.caucho.jca.ConnectionPool.create(ConnectionPool.java:780)
	at com.caucho.jca.ConnectionPool.allocatePool(ConnectionPool.java:649)
	at com.caucho.jca.ConnectionPool.allocate(ConnectionPool.java:608)
	at com.caucho.jca.ConnectionPool.allocateConnection(ConnectionPool.java:505)
	at com.caucho.sql.DataSourceImpl.getConnection(DataSourceImpl.java:65)
	at com.caucho.sql.DBPool.getConnection(DBPool.java:624)

원인은 구글링해보니 JDBC호환 문제라고 하네요.

기존에 사용하는 sqljdbc4.jar를 jtds-1.2.5.jar파일로 변경하였습니다.

JDBC 드라이버를 변경했으니 was config설정도 변경해주어야 합니다.

 

MSSQL JDBC 드라이버 설정 방법

Driver [com.microsoft.sqlserver.jdbc.SQLServerDriver]
URL [jdbc:sqlserver://localhost:1433;DatabaseName=DBNAME]
* JDBC드라이버 : sqljdbc.jar 또는 sqljdbc4.jar (MS-SQL 2008까지 지원)

 
Driver [net.sourceforge.jtds.jdbc.Driver]
Driver [net.sourceforge.jtds.jdbcx.JtdsDataSource]
URL [jdbc:jtds:sqlserver://localhost:1433/DBNAME;tds=8.0;lastupdatecount=true]
* JDBC드라이버 : jtds-1.2.jar
728x90
반응형
728x90
반응형

패스워드를 SHA256으로 암호화하는 방법에 대해 알아보겠습니다.


1) 패스워드를 암호화하는 KsShaEncrypt.java 파일을 프로젝트에 적절한 위치에 추가해줍니다.

public class KsShaEncrypt {
	
	private static int ENDIAN = Common.BIG_ENDIAN;

	private static final int SHA256_DIGEST_BLOCKLEN = 64;
	private static final int SHA256_DIGEST_VALUELEN = 32;

	private static final int SHA256_K[] =
	{
		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
		0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
		0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
		0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
		0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
		0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
		0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
		0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
		0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
	};

	private static final int ROTL_ULONG(int x, int n) {
		return (x << n) | Common.URShift(x, 32 - n);
	}

	private static final int ROTR_ULONG(int x, int n) {
		return Common.URShift(x, n) | (x << (32 - (n)));
	}

	private static final int ENDIAN_REVERSE_ULONG(int dwS) {
		return ( (ROTL_ULONG((dwS),  8) & 0x00ff00ff) | (ROTL_ULONG((dwS), 24) & 0xff00ff00) );
	}

	private static final void BIG_D2B(int D, byte[] B, int B_offset) {
		Common.int_to_byte_unit(B, B_offset, D, ENDIAN);
	}

	private static final int RR(int x, int n) { return ROTR_ULONG(x, n); }
	private static final int SS(int x, int n) { return Common.URShift(x, n); }

	private static final int Ch(int x, int y, int z) { return ((x & y) ^ ((~x) & z)); }
	private static final int Maj(int x, int y, int z) { return ((x & y) ^ (x & z) ^ (y & z)); }
	private static final int Sigma0(int x) { return (RR(x,  2) ^ RR(x, 13) ^ RR(x, 22)); }
	private static final int Sigma1(int x) { return (RR(x,  6) ^ RR(x, 11) ^ RR(x, 25)); }

	private static final int RHO0(int x) { return (RR(x,  7) ^ RR(x, 18) ^ SS(x,  3)); }
	private static final int RHO1(int x) { return (RR(x, 17) ^ RR(x, 19) ^ SS(x, 10)); }

	private static final int abcdefgh_a = 0;
	private static final int abcdefgh_b = 1;
	private static final int abcdefgh_c = 2;
	private static final int abcdefgh_d = 3;
	private static final int abcdefgh_e = 4;
	private static final int abcdefgh_f = 5;
	private static final int abcdefgh_g = 6;
	private static final int abcdefgh_h = 7;

	private static final void FF(int[] abcdefgh, int a, int b, int c, int d, int e, int f, int g, int h, int[] X, int j) {
		long T1;

		T1 = Common.intToUnsigned(abcdefgh[h]) + Common.intToUnsigned(Sigma1(abcdefgh[e])) + Common.intToUnsigned(Ch(abcdefgh[e], abcdefgh[f], abcdefgh[g])) + Common.intToUnsigned(SHA256_K[j]) + Common.intToUnsigned(X[j]);
		abcdefgh[d] += T1;
		abcdefgh[h] = (int)(T1 + Common.intToUnsigned(Sigma0(abcdefgh[a])) + Common.intToUnsigned(Maj(abcdefgh[a], abcdefgh[b], abcdefgh[c])));
	}

	private static final int GetData(byte[] x, int x_offset) {
		return Common.byte_to_int(x, x_offset, ENDIAN);
	}
	
	//*********************************************************************************************************************************
	// o SHA256_Transform() : 512 비트 단위 블록의 메시지를 입력 받아 연쇄변수를 갱신하는 압축 함수로써
	//	                      4 라운드(64 단계)로 구성되며 8개의 연쇄변수(a, b, c, d, e, f, g, h)를 사용
	// o 입력                               : Message               - 입력 메시지의 포인터 변수
	//	                      ChainVar              - 연쇄변수의 포인터 변수
	// o 출력                               :
	//*********************************************************************************************************************************
	private static void SHA256_Transform(byte[] Message, int[] ChainVar) {
		int abcdefgh[] = new int[8];
		int T1[] = new int[1];
		int X[] = new int[64];
		int j;

		for (j = 0; j < 16; j++)
			X[j] = GetData(Message, j*4);

		for (j = 16; j < 64; j++)
			X[j] = (int)(Common.intToUnsigned(RHO1(X[j - 2])) + Common.intToUnsigned(X[j - 7]) + Common.intToUnsigned(RHO0(X[j - 15])) + Common.intToUnsigned(X[j - 16]));

		abcdefgh[abcdefgh_a] = ChainVar[0];
		abcdefgh[abcdefgh_b] = ChainVar[1];
		abcdefgh[abcdefgh_c] = ChainVar[2];
		abcdefgh[abcdefgh_d] = ChainVar[3];
		abcdefgh[abcdefgh_e] = ChainVar[4];
		abcdefgh[abcdefgh_f] = ChainVar[5];
		abcdefgh[abcdefgh_g] = ChainVar[6];
		abcdefgh[abcdefgh_h] = ChainVar[7];

		for (j = 0; j < 64; j += 8)
		{
			FF(abcdefgh, abcdefgh_a, abcdefgh_b, abcdefgh_c, abcdefgh_d, abcdefgh_e, abcdefgh_f, abcdefgh_g, abcdefgh_h, X, j + 0);
			FF(abcdefgh, abcdefgh_h, abcdefgh_a, abcdefgh_b, abcdefgh_c, abcdefgh_d, abcdefgh_e, abcdefgh_f, abcdefgh_g, X, j + 1);
			FF(abcdefgh, abcdefgh_g, abcdefgh_h, abcdefgh_a, abcdefgh_b, abcdefgh_c, abcdefgh_d, abcdefgh_e, abcdefgh_f, X, j + 2);
			FF(abcdefgh, abcdefgh_f, abcdefgh_g, abcdefgh_h, abcdefgh_a, abcdefgh_b, abcdefgh_c, abcdefgh_d, abcdefgh_e, X, j + 3);
			FF(abcdefgh, abcdefgh_e, abcdefgh_f, abcdefgh_g, abcdefgh_h, abcdefgh_a, abcdefgh_b, abcdefgh_c, abcdefgh_d, X, j + 4);
			FF(abcdefgh, abcdefgh_d, abcdefgh_e, abcdefgh_f, abcdefgh_g, abcdefgh_h, abcdefgh_a, abcdefgh_b, abcdefgh_c, X, j + 5);
			FF(abcdefgh, abcdefgh_c, abcdefgh_d, abcdefgh_e, abcdefgh_f, abcdefgh_g, abcdefgh_h, abcdefgh_a, abcdefgh_b, X, j + 6);
			FF(abcdefgh, abcdefgh_b, abcdefgh_c, abcdefgh_d, abcdefgh_e, abcdefgh_f, abcdefgh_g, abcdefgh_h, abcdefgh_a, X, j + 7);
		}

		ChainVar[0] += abcdefgh[abcdefgh_a];
		ChainVar[1] += abcdefgh[abcdefgh_b];
		ChainVar[2] += abcdefgh[abcdefgh_c];
		ChainVar[3] += abcdefgh[abcdefgh_d];
		ChainVar[4] += abcdefgh[abcdefgh_e];
		ChainVar[5] += abcdefgh[abcdefgh_f];
		ChainVar[6] += abcdefgh[abcdefgh_g];
		ChainVar[7] += abcdefgh[abcdefgh_h];
	}

	/**
	@brief 연쇄변수와 길이변수를 초기화하는 함수
	@param Info : SHA256_Process 호출 시 사용되는 구조체
	*/
	public static void SHA256_Init( SHA256_INFO Info ) {
		Info.uChainVar[0] = 0x6a09e667;
		Info.uChainVar[1] = 0xbb67ae85;
		Info.uChainVar[2] = 0x3c6ef372;
		Info.uChainVar[3] = 0xa54ff53a;
		Info.uChainVar[4] = 0x510e527f;
		Info.uChainVar[5] = 0x9b05688c;
		Info.uChainVar[6] = 0x1f83d9ab;
		Info.uChainVar[7] = 0x5be0cd19;

		Info.uHighLength = Info.uLowLength = 0;
	}

	/**
	@brief 연쇄변수와 길이변수를 초기화하는 함수
	@param Info : SHA256_Init 호출하여 초기화된 구조체(내부적으로 사용된다.)
	@param pszMessage : 사용자 입력 평문
	@param inLen : 사용자 입력 평문 길이
	*/
	public static void SHA256_Process( SHA256_INFO Info, byte[] pszMessage, int uDataLen ) {
		int pszMessage_offset;

		if((Info.uLowLength += (uDataLen << 3)) < 0) {
			Info.uHighLength++;
		}

		Info.uHighLength += Common.URShift(uDataLen,29);

		pszMessage_offset = 0;
		while (uDataLen >= SHA256_DIGEST_BLOCKLEN) {
			Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, SHA256_DIGEST_BLOCKLEN);
			SHA256_Transform(Info.szBuffer, Info.uChainVar);
			pszMessage_offset += SHA256_DIGEST_BLOCKLEN;
			uDataLen -= SHA256_DIGEST_BLOCKLEN;
		}

		Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, uDataLen);
	}

	/**
	@brief 메시지 덧붙이기와 길이 덧붙이기를 수행한 후 마지막 메시지 블록을 가지고 압축함수를 호출하는 함수
	@param Info : SHA256_Init 호출하여 초기화된 구조체(내부적으로 사용된다.)
	@param pszDigest : 암호문
	*/
	public static void SHA256_Close( SHA256_INFO Info, byte[] pszDigest ) {
		int i, Index;

		Index = Common.URShift(Info.uLowLength, 3) % SHA256_DIGEST_BLOCKLEN;
		Info.szBuffer[Index++] = (byte)0x80;

		if (Index > SHA256_DIGEST_BLOCKLEN - 8) {
			Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index);
			SHA256_Transform(Info.szBuffer, Info.uChainVar);
			Common.arrayinit(Info.szBuffer, (byte)0, SHA256_DIGEST_BLOCKLEN - 8);
		}
		else {
			Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index - 8);
		}

		if(ENDIAN == Common.LITTLE_ENDIAN) {
			Info.uLowLength = ENDIAN_REVERSE_ULONG(Info.uLowLength);
			Info.uHighLength = ENDIAN_REVERSE_ULONG(Info.uHighLength);
		}

		Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 2))*4, Info.uHighLength, ENDIAN);
		Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 1))*4, Info.uLowLength, ENDIAN);

		SHA256_Transform(Info.szBuffer, Info.uChainVar);

		for (i = 0; i < SHA256_DIGEST_VALUELEN; i += 4)
			BIG_D2B((Info.uChainVar)[i / 4], pszDigest, i);
	}

	/**
	@brief 사용자 입력 평문을 한번에 처리
	@param pszMessage : 사용자 입력 평문
	@remarks 내부적으로 SHA256_Init, SHA256_Process, SHA256_Close를 호출한다.
	*/
	public static synchronized String encrypt( String pMessage) throws Exception{
		SHA256_INFO info = new SHA256_INFO();
		byte[] pszMessage = pMessage.getBytes("utf-8");
		byte pszDigest[]   = new byte[32];
		SHA256_Init( info );
		SHA256_Process( info, pszMessage, pszMessage.length );
		SHA256_Close( info, pszDigest );
		return getString(pszDigest);
	}


	public static class SHA256_INFO {
		public int uChainVar[] = new int[SHA256_DIGEST_VALUELEN / 4];
		public int uHighLength;
		public int uLowLength;
		public byte szBuffer[] = new byte[SHA256_DIGEST_BLOCKLEN];
	}
	
	public static class Common {
		
		public static final int BIG_ENDIAN = 0;
		public static final int LITTLE_ENDIAN = 1;

		public static void arraycopy(byte[] dst, byte[] src, int length) {
			for(int i=0; i<length; i++)="" {="" dst[i]="src[i];" }="" public="" static="" void="" arraycopy_offset(byte[]="" dst,="" int="" dst_offset,="" byte[]="" src,="" src_offset,="" length)="" for(int="" i="0;" i> shift_value;
				return (byte)value;
			} else {
				int shift_value = (b_offset%4)*8;
				int mask_value =  0x0ff << shift_value;
				int value = (src[b_offset/4] & mask_value) >> shift_value;
				return (byte)value;
			}
			
		}
		
		public static byte[] get_bytes_for_ints(int[] src, int offset, int ENDIAN) {
			int iLen = src.length-offset;
			byte[] result = new byte[(iLen)*4];
			for(int i=0; i> 24) & 0x0ff);
				dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff);
				dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff);
				dst[dst_offset+3] = (byte)((src) & 0x0ff);
			} else {
				dst[dst_offset] = (byte)((src) & 0x0ff);
				dst[dst_offset+1] = (byte)((src >> 8) & 0x0ff);
				dst[dst_offset+2] = (byte)((src >> 16) & 0x0ff);
				dst[dst_offset+3] = (byte)((src >> 24) & 0x0ff);
			}
			
		}

		public static void int_to_byte_unit_big_endian(byte[] dst, int dst_offset, int src){
			dst[dst_offset] = (byte)((src>> 24) & 0x0ff);
			dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff);
			dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff);
			dst[dst_offset+3] = (byte)((src) & 0x0ff);
		}

		public static int URShift(int x, int n){
			if(n == 0)
				return x;
			if(n >= 32)
				return 0;
			int v = x >> n;
			int v_mask = ~(0x80000000 >> (n-1));
			return v & v_mask;
		}
		
		public static final long INT_RANGE_MAX = (long)Math.pow(2, 32);

		public static long intToUnsigned(int x){
			if(x >= 0)
				return x;
			return x + INT_RANGE_MAX;
		}
	}
	public static String getString(byte[] data){
		String result = "";
		for(int i=0; i<data.length; i++)="" {="" result="result" +="" tohex(data[i]);="" }="" return="" result;="" public="" static="" string="" tohex(int="" b){="" char="" c[]="new" char[2];="" c[0]="toHexNibble((b">>4) & 0x0f);
		c[1] = toHexNibble(b & 0x0f);
		return new String(c);
	}

	public static char toHexNibble(int b){
		if(b >= 0 && b <= 9)
			return (char)(b + '0');
		if(b >= 0x0a && b <= 0x0f)
			return (char)(b + 'A' - 10);
		return '0';
	}

}



2) 패스워드를 넘겨받는 부분에서 password를 암호화 시켜줍니다.

이때 

KsShaPassword = KsShaPassword.toUpperCase();  //모두 대문자로 바꾸기

KsShaPassword = KsShaPassword.toLowerCase();  //모두 소문자로 바꾸기

상황에 맞게 이용해 주시면 되겠습니다.

//평문이 아닌 KsSha암호화방식 암호를 전달
String KsShaPassword = "";
try {
	KsShaPassword = KsShaEncrypt.encrypt(password);
	KsShaPassword = KsShaPassword.toLowerCase();
} catch (Exception e) {
	log.error("login is failed by KsShaEncrypt - " + e.toString());
	e.printStackTrace();
}

 알면 쉽고 모르면 어려운 SHA256 암호화하는 방법에 대해 설명해드렸습니다.


* 추가로 SHA256암호화 시켜주는 해시생성기 링크 남깁니다.


http://www.convertstring.com/ko/Hash/SHA256



a 를 암호화한 값 : 112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB 

이 값을 대,소문자로 DB에 저장해주고 싶다면 toUpperCase(); 함수를 사용하시면 됩니다.


KsShaEncrypt.java


728x90
반응형
728x90
반응형

SSO(Single Sign-On)


통합 인증, Single Sign-On의 약자로 한 번의 인증과정으로 로그인을 공유하는 기능입니다.



이미지를 통해서 예를 들어 보겠습니다.

네이버, 페이스북, 카카오톡 등의 계정으로 원하고자 하는 서비스를 이용할 수 있습니다.

하나의 계정으로 여러 서비스를 이용할 수 있는 장점이 있습니다.


SSL(Secure Sockey Layer)


개인 정보를 암호화하여 전송하는 웹서버 또는 프로토콜을 의미합니다. 웹상에서 개인정보를 취급하는 모든 기관이나 개인 등은 개인정보보호법 제 24조 고유식별정보의 처리제한 항목에 의거하여 암호화 통신을 적용하여 개인정보를 보호해야 할 의무가 있다. SSL이 설치된 웹 사이트의 경우 https로 접속이 가능합니다. 

하단 이미지는 SSL을 이용하는 사이트입니다. 개인정보를 이용하는 사이트라면 ssl인증이 필수입니다. 그렇지 못하다면 이용하지 않는 것을 추천드립니다. 



SSH(Secure Shell)


네트워크를 통해 원격으로 다른 호스트에 보안 접속하는 응용프로그램 또는 프로토콜을 의미합니다. 세션이 암호화 되기 때문에 액세스가 보호됩니다.

PuTTY 프로그램을 이용하면 SSH 연결을 사용할 수 있습니다.








728x90
반응형
728x90
반응형

31. 로그인 없이 로그인 하기(SSH Key)

31.1 Loginless : ssh public private key

SSH, rsync, git과 같은 기술을 사용할 때 로그인이 번거롭고 보다 안전한 방법으로 인증하고 싶다면 SSH공개키를 이용하면 됩니다. 

SSH공개키를 이용하면 편의성과 보안성 모두를 높일 수 있다고 하네요.

linux1컴퓨터

 · ssh-keygen -> enter -> y : id_rsa파일의 형태로 저장됩니다. 공개키와 비공개키를 만드는 것이죠.

 · cd ~ : 홈 디렉토리로 이동합니다

 · ls -al : .ssh디렉토리가 생성되어 있습니다.

 · cd ~/.ssh -> ls -al : authorized_keys파일 안에 id_rsa.pub키의 값을 파일 끝에 붙여주면 됩니다.

 · ssh-copy-id egoing@192.168.0.67 : 로그인하고자 하는 컴퓨터의 IP주소를 입력하여 linux1의 아이디를 복사를 하는 명령어입니다. 즉 linux1에 있던 is_rsa.pub에 값이 linux2 authorized_keys파일에 공개키가 저장됩니다.

linux1의 사용자를 linux2컴퓨터에 로그인하는 것을 허용한다는 의미로 해석됩니다.


linux2컴퓨터

 · cat authorized_keys : authorized_keys파일의 내용을 읽습니다.




31.2 Loginless2 : rsync

rsync는 컴퓨터와 컴퓨터 사이 동기화를 시키는 것인데요. 동기화를 위해서는 기본적으로 로그인 필요합니다.

linux1 컴퓨터

 · mkdir rsync3 -> cd rsync3 : rsync3디렉토리로 이동합니다.

 · touch test{1..100} : 100개의 비어 있는 파일이 생성됩니다.

 · rsync -avz .egoing@192.168.0.67:~/rsync_welcome : 현재 디렉토리에 있는 내용을 IP주소의 홈 디렉토리 밑 rsync_welcome의 디렉토리에 100개 파일을 동기화 시키는 명령어입니다.

linux2 컴퓨터

 · mkdir rsync_welcome: rsync_welcome디렉토리를 생성


rsync기능은 실행에 있어 편리합니다. cron은 정기적으로 명령을 실행시키는 것인데요.

rsync로 자동로그인하여 cron을 이용하여 정기적으로 백업을 자동화 처리할 수 있습니다.


31.3 Loginless3 : RSA

정보를 아무도 모르게 알아야 하는 사람만 알도록 이해할 수 없는 정보로 바꾸는 것을 암호화(encrypt)

암호화된 상태를 원래의 상태로 돌리는 것을 복호화(decrypt)라고 합니다.

Key를 이용해 암호화와 복호화를 하는데요. 키를 가진 사람만이 암호를 읽을 수 있겠죠.

암호화를 할 때와 복호화를 할 때 똑같은 키를 사용하는 것을 대칭적인 방식이라고 부릅니다.

예를 들면 정보를 암호화할 때 private키를 통해 암호화를 하는 것이죠.

private키를 public키로 돌릴 수 있는데 각각의 키가 달라지는 방식을 비대칭 방식이라고 합니다.

예를 들면 ssh키젠을 이용해 키를 만들 때 id_rsa(private키), id_rsa.pub(public키)가 짝을 이루어 다닙니다.

암호화할 때 private키를 썼다면 복호화 할 때 반드시 public키를 사용해야 합니다.

비대칭 방식의 대표 주자가 바로 RSA인데요

RSA방식은 SSH client가 SSH server에게 접속한다면 서버는 클라이언트에게 랜덤키를 줍니다. 랜덤키를 받은 클라이언트는 id_rsa파일이 있는 지 확인하고 서버가 전송한 랜덤키를 암호화(정보를 알아야하는 사람만 알도록 정보로 바꾸는 것) 시킵니다. 암호화된 결과를 다시 서버에게 전송합니다. SSH server는 암호화된 정보를 authorized_keys에 저장된 공개키를 이용해 다시 복호화(암호화된 상태를 원래의 상태로 돌리는 것)합니다. 복호화된 결과(클라이언트가 보내준 암호화된 키)가 SSH server가 랜덤키의 결과와 같다면 로그인을 허용하는 것입니다.

RSA방식은 아이디, 패스워드를 입력하는 것보다 복잡한 패스워드를 파일에 저장하여 파일을 갖고 로그인하는 것이 훨씬 안전하다고 하네요.



linux1컴퓨터

 · ls ~/.ssh/ : id_ras(private키), id_rsa(public키) 등의 파일 목록이 있습니다.

 · ssh egoing@192.168.0.67 : linux2 컴퓨터로 로그인합니다.

linux2컴퓨터

 · ls ~/.ssh : authorized_keys파일에 id_rsa_pub값을 가진다면 컴퓨터에 접속을 허용하겠다는 의미입니다.


32. 연속적으로 명령 실행시키기(;과 &와 &&의 차이)

CLI를 통해 컴퓨터를 제어하는 이유 중 하나는 해야 할 일을 순서대로 배치해서 자동화된 처리를 할 수 있다는 것입니다. 자동화된 처리를 위해서 명령어와 명령어 간의 연결하는 구분자를 잘 알아야 할 필요가 있습니다. 언어로 치면 접속사와 같은 의미를 갖습니다.

 · ; : 세미콜론 앞의 명령어가 실패해도 다음 명령어를 실행합니다.

 · mkdir test;cd test : test디렉토리를 생성 후 test디렉토리로 이동합니다.

 · && : 앞의 명령어가 성공했을 경우에만 다음 명령어가 실행됩니다. 세미콜론과는 다른 의미를 갖죠

 · mkdir test; cd test; touch abc : 세미콜론은 성공과 실패를 떠나 연속적으로 실행해야 할 명령을 사용할 때 씁니다. test디렉토리는 이미 존재하기에 실패를 하고 test디렉토리를 이동하여 abc파일을 생성합니다.  반면에

 · mkdir test && cd test && touch abc : test디렉토리가 이미 존재하기에 실패하여 cd test와 touch abc가 실행되지 않습니다. 대체로 &&를 쓰는 것이 좋다고 합니다.

&와 &&의 차이

&명령어는 백그라운드로 동작시킬 때 사용합니다.

 · mkdir test & cd test : test디렉토리를 백그라운드로 생성함과 동시에 test디렉토리로 이동하려 했기에 cd test는 존재하지 않는 디렉토리로 진입을 하려 하기에 no such file or directory메시지가 뜨고 test디렉토리는 생성됩니다.

& : 앞의 명령어를 백그라운드로 돌리고 동시에 뒤에 명령어를 실행합니다.

 · mkdir test3 && { cd test3; touch abc; echo 'success!'; } || echo 'there is no dir';

: mkdir test3가 성공했을 때 cd test2; touch abc를 실행하고 success!!를 출력합니다. 실패했을 경우 'There is no dir'이 출력되죠.




생활코딩 리눅스 강의



728x90
반응형
728x90
반응형

+ Recent posts