3월, 2019의 게시물 표시

[Security] HSTS(Http Strict Transport Security)란 무엇인가?

좋은 글이 있어 아래 링크. https://rsec.kr/?p=315

[Cryptography] Java AES 128 암호화 예제

AES 128bit 임으로 string length 16인(16 * 8 = 128bit) key를 넣어 준다. public String encryptByAES ( String plain , String key ) { try { SecretKeySpec spec = new SecretKeySpec ( key . getBytes (), "AES" ); Cipher cipher = Cipher . getInstance ( "AES" ); cipher . init ( Cipher . ENCRYPT_MODE , spec ); byte [] encTxt = cipher . doFinal ( plain . getBytes ()); return Base64 . getEncoder (). encodeToString ( encTxt ); } catch ( Exception e ) { e . printStackTrace (); throw new RuntimeException ( "Cipher exception: " + e . getMessage ()); } } // encTxt: base64 encoded. public String decryptByAES ( String b64EncTxt , String key ) { try { SecretKeySpec spec = new SecretKeySpec ( key . getBytes (), "AES" ); Cipher cipher = Cipher . getInstance ( "AES" ); cipher . init ( Cipher . DECRYPT_MODE ,

[Protocol] WIEGAND 통신

이미지
1. WIEGAND 통신 방식이란? 두 개의 D0, D1 라인을 이용해 소량의 데이터를 전송 하는 방식으로 , 주로 출입통제 장치의 리더와 컨트롤러 간의 통신 방식에 사용 됩니다. 물론 리더는 RS-485, RS-232, ABA-Track II 와 같이 다양한 통신 방식을 취하기도 하지만, 주로 WIEGAND 방식을 많이 사용 합니다. 그 이유는 .. 개인적으로 생각했을때 구현이 쉽고, 별도의 PHY 칩을 사용 하지 않기 때문에 생산 단가를 좀더 줄일 수 있어서가 아닌가.. 생각해 봅니다.  2. WIEGAND 통신 타이밍도 위 그림과 같이 D0, D1  두 신호선으로 통신 합니다. D0, D1 이 각각 의미 하는 것은, D0 가 LOW 이면 그 비트 값이 '0' 이고, D1 이 LOW 이면 그 비트 값이 '1' 임을 의미 합니다. 따라서 D0 와 D1 은 동시에 LOW 가 되지 않으며, 정해진 타이밍이 있습니다. 예를 들어 위 그림의 신호를 데이터로 변환해 보자면, 4 번 LOW 값이 있으므로 4 비트 임을 알 수 있고, 값은 1101 임을 알 수 있습니다. 3. WIEGAND 신호 구현 실제 WIEGAND 통신 방식으로 데이터를 전송 할때는  데이터가 손상될 수 있으므로, 앞뒤에 패리티비트를 추가 하거나, 복잡한 계산방법을 적용해 데이터를 암호화 하는 경우도  있습니다. 하지만 생성된 데이터는 약 20 ~ 40 Bit 이내의 데이터이고, 이를 0 번 비트 부터 차례대로 전송 하면 됩니다. 해당 비트가 0 이면 D0 가 연결된 PIN 을 LOW 로 하고, 비트 값이 1 이면 D1 이 연결된 PIN 을 LOW 로 해주면 그만 입니다. 물론 회로적으로 GPIO 의 출력을 그대로 내보내지는 않고 트랜지스터 등을 이용해 힘을 실어 주어야 겠지요. 그럼 받는 쪽은 어떻게 해야 할까요? 위 회로의 좌측이 리더에서 들어온 WIEGAND 신호이고, 우측이 C

[Maven] Package without test

mvn - Dmaven . test . skip = true package

[Jackson] Alphanumeric Pattern

아래와 같이 1~32자 내의 Alphanumeric 문자만 받는 패턴을 적용할 수 있다. @Pattern ( regexp = "^[A-Za-z0-9]{1,32}$" )

[GitHub] One PC Multi Account

배경) 회사에서 private github를 사용하고 있음. 계정은 회사 email. 집 PC에서 이 private github를 clone하여 작업하고 싶음. 그러나 집 PC에는 이미 다른 github 계정이 있음. 두 계정을 집 PC에서 어떻게 다 사용할까? 요점) github url 당 ssh key를 연결해 주는게 핵심. 이미 사용중인 계정은 하나 있고 추가 연결을 위해 아래와 같이 한다. 1. ssh key 생성 $>  ssh-keygen -t rsa -C "user@email.com" -f "id_rsa_work" 2. ~/.ssh/id_rsa_user 생성 되었는지 확인 $> ls -al ~/.ssh ~/.ssh/id_rsa_work ~/.ssh/id_rsa_work.pub 3. ssh key 추가 $> ssh-add ~/.ssh/id_rsa_work 4. 추가하고 싶은 github 계정에 접속하여 Settings -> SSH and GPG keys -> 위에서 만든 SSH key 추가 5. ~/.ssh 폴더에 아래 config 파일 추가 $> touch ~/.ssh/config 6. config 파일 아래처럼 수정 # Default Account Host github.com     HostName github.com     User git     IdentityFile ~/.ssh/id_rsa # Work Account Host work.github.com        # <- 해당 url이면 id_rsa_work를 사용하겠다는 것임.     HostName github.com     User git     IdentityFile ~/.ssh/id_rsa_work 7. clone의 경우 $> git clone git@ work.github.com :repo_name/repo_name.git

[Java] 다중 정렬

아래와 같은 코드로 price에 대해 먼저 정렬하고 같은 price 내에서 name으로 다시 정렬. package exercise ; import java.util.ArrayList ; import java.util.Collections ; import java.util.Comparator ; import java.util.List ; public class MultiConditionSort { public static void main ( String [] args ) { List < Item > items = new ArrayList <>(); items . add ( new Item ( 20 , "c" )); items . add ( new Item ( 15 , "z" )); items . add ( new Item ( 11 , "a" )); items . add ( new Item ( 19 , "b" )); items . add ( new Item ( 20 , "b" )); items . add ( new Item ( 10 , "z" )); items . add ( new Item ( 20 , "a" )); items . add ( new Item ( 10 , "x" )); items . add ( new Item ( 30 , "b" )); System . out . println ( "Origin: " + items ); Collections . sort ( items

[JPA] Inheritance Entity Multi Repository

이미지
Entity 상속의 경우 다중의 JPA 인터페이스를 구현해야 할 경우가 있다. 예로, 이럴 경우 아래와 같이 인터페이스를 구현해서 사용 할 수 있다. public interface BaseRepository extends JpaRepository<Base, Long> { ... } public interface AImplRepository extends JpaRepository<Base, Long> { ... } public interface BImplRepository extends JpaRepository<Base, Long> { ... } 이처럼 사용할 시에 여러 인터페이스에 공통된 메소드가 추가 되어야 한다. 이럴땐 아래와 같은 방법을 사용해 보자. 우선 최상위 repository를 아래와 같이 만들고, @NoRepositoryBean public interface CommonBaseRepository<T extends Base> extends JpaRepository<T, Long> { ... } 이를 상속받아 인터페이스를 만들자. public interface BaseRepository extends CommonBaseRepository<Base> { ... } public interface AImplRepository extends CommonBaseRepository<AImpl> { ... } public interface BImplRepository extends CommonBaseRepository<BImpl> { ... } 공통적으로 사용할 수 있는 인터페이스는 최상위 단에 정의 함으로써 아래와 같이 중복된 코드를 줄일 수 있다. @NoRepositoryBean public interface CommonBaseRepository<T ex

[JPA] Custom JPA Repository

JPA 리포지토리는 인터페이스만 정의하여 사용한다. 그런데 메소드를 직접 구현해야 할 때도 있다. 그런데 리포지토리를 직접 구현해 버리면 공통 인터페이스가 제공하는 기능까지 모두 구현해야 하기 때문에 이럴때 우회할 수 있는 방법이 있다. 아래 처럼 인터페이스를 하나 작성 한다. public interface MemberRepositoryCustom {     public List<Member> findMemberCustom(); } 다음으로 이를 구현 한다. 그런데 여기서 주의 할 점은 클래스 이름을 리포지토리 인터페이스 이름 + Impl로 꼭 지어야 한다. 이렇게 하면 스프링 데이터 JPA가 사용자 정의 구현 클래스로 인식한다. public class MemberRepositoryImpl implements MemberRepositoryCustom {     @Override     public List<Member> findMemberCustom() {         .... // 사용자 정의 구현     } } 마지막으로 리포지토리 인터페이스에서 사용자 정의 인터페이스를 상속 받으면 된다. public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom { } 만약 Impl 대신 다른 이름을 붙이고 싶으면 repository-impl-postfix 속성을 변경하면 된다. Impl이 default. <repositories base-package="~~" repository-impl-postfix="Impl" /> JavaConfig 설정은 아래와 같다. @EnableJpaRepositories(basePackages = "~~", repositoryImplementationPostfix = "Im

[Recursion] 재귀호출 기법

재귀 호출의 형태는 아래와 같다. 잘 생각해 보자. type recursiveMethod(args) {     if leaf condition {         문제를 풀고         return 답;     } else {         Divide problem to subproblem1 and subproblem2         type sol1 = recursiveMethod(subproblem1);         type sol2 = recursiveMethod(subproblem2);         return sol1 과 sol2를 조합하여 답을 구함;     } }

[URL] 대소문자를 구분하나?

URL 샘플 http://www.example.com/mypage?param=1 1. http는 프로토콜 2. www.example.com은 도메인 네임(DNS) 3. mypage는 resource 위치 4. param=1은 query parameter Conclusion 1은 대소문자 상관없고, 2도 DNS 서버가 대소문자 구분하지 않으므로 상관 없음. 3은 운영되고 있는 서버의 특성을 탐. 윈도우의 경우는 파일명에 대소문자 구분을 하지 않으므로 상관없고, 유닉스 계열의 경우 파일명 대소문자 구분하니 대소문자 잘 맞춰 줘야함. 4는 웹 서비스의 스크립트 언어 특성에 따름. asp를 제외한 대부분의 스크립트는 대소문자를 구분하는 편이다.

[AWS] Amazon Linux에 Oracle Java 설치

1. 기존 openjdk 제거 $> sudo yum -y remove java* 2. Oracle Java 1.8.0_201 받기 $>  wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie"  https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.rpm 3. Execute mode 추가 $> sudo chmod +x jdk-8u201-linux-x64.rpm 4. Install $> sudo yum install -y jdk-8u201-linux-x64.rpm

[JPA] Entity equals() & hashCode() Override 시 주의할 점

JPA Entity의 equals()와 hashCode()를 IDE(ex. IntelliJ)로 기본 자동 생성할때 아래와 같이 getClass()로 비교되는 것으로 생성된다. public class User {     @Id     @GeneratedValue(strategy = GenerationType.IDENTITY)     private Long Id;     private String name;     ....     @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass()) return false;         User u = (User) o;         return id != null ? id.equals(u.id) : u.id == null;     } } 그러나 위의 equals() 코드는 Fetch 전략을 lazy로 했을때 Proxy로 인한 문제가 발생한다. lazy fetch는 해당 entity를 상속하는 Proxy 객체를 반환하기 때문에 getClass()가 User 객체가 될수 없어 equals 비교가 실패하게 된다. 해결책은 아래와 같이 instanceof로 override 해주는 것. 또한 id 필드가 private 임으로 proxy에서 getter를 사용해서 접근하는 것도 눈여겨 볼만 하다.     ....     @Override     public boolean equals(Object o) {         if (this == o) return true;         if (!(o instanceof User)) return false;         User u = (User) o;         return Objects.equals(getId()); }