Midnight Coder's Lounge

[번역][Java] 패스워드에 String이 아닌 char[]를 사용해야 하는 이유 본문

Language

[번역][Java] 패스워드에 String이 아닌 char[]를 사용해야 하는 이유

AtomicLiquors 2022. 8. 27. 19:32

요약

보안상 비밀번호 / 패스워드의 타입은 String이 아닌 char[]을 사용하는 것이 좋습니다.
- String의 데이터는 char[]보다 오랫동안 남기 때문입니다.
- String의 데이터는 콘솔 등에 직접 출력될 우려가 크기 때문입니다.

 


 

상세 


왜 String이 아닌 char[]를 사용하는가?

 

이어질 내용들은 패스워드의 타입과 관하여 Stackoverflow에 작성된 게시글과 그 답변 내용을 가공한 것입니다.

 

 

"why is char[] preferred over String for passwords?"

질문자 :

Ahamed, 2012.01.16.

수정/보완 : Rakete1111

 

 

"Java Swing에서,
비밀번호 입력 필드는 getText() 메소드(반환타입 String)가 아니라 getPassword()메소드(반환타입 char[])를 갖지요.
비슷한 맥락으로, 비밀번호를 다룰 때 String을 쓰지 말라는 얘기를 들었습니다.

왜 String이 비밀번호 보안에 문제가 되는 건가요? char[]를 쓰려니 불편한데요."

 

 

 

- String의 데이터는 char[]보다 오랫동안 남는다

답변자 : Jon Skeet, 2012.01.16.

수정/보완 : Neuron

 

"String은 불변Immutable입니다.

불변이란 String을 생성하고 난 뒤에, 만일 다른 프로세스가 메모리를 덤프할 수 있다면,

String에 저장된 데이터는 리플렉션을 하지 않는 이상 제거할 수가 없고,

가비지 컬렉션이 실행될 때까지 남아있을 수밖에 없다는 의미입니다.

 

(char[]과 같은) 배열의 경우, 하던 작업이 끝나면 수동으로 데이터를 지워버릴 수가 있지요.

어떤 방식으로든 배열을 덮어써 버리면 되고, 그러면 비밀번호는 시스템 내부에서 완전히 사라져 버립니다.

가비지 콜렉션을 기다릴 필요도 없습니다.

 

말씀하신 대로 이건 보안 문제가 맞아요.

다만 char[]을 쓴다는 것도 해커가 침투할 여지를 줄여줄 뿐이고,

그마저도 특정 침투 방식에 한해서만 효과가 있습니다.

 

댓글에서 지적하는 대로,

가비지 컬렉터가 제거해 버린 배열이라 할지라도 메모리에 데이터 사본을 남길 가능성이 있어요.

(중략) 가비지 컬렉터가 매번 모든 메모리를 제거해서 이런 일을 예방할 수 있을지도 모르죠.

그렇다 할지라도, char[]에 실제 문자 데이터가 들어있는 순간은 엄연히 존재하고,

이는 보안 취약점으로 악용될 수가 있죠."

 

 

 

- String의 데이터는 콘솔 등에 출력될 우려가 크다

답변자 : Konrad Garus, 2012.01.16.

수정/보완 : Kyle Rosendo

 

"또 하나 이유를 들자면,
별다른 조치 없이 String을 사용한다면
로그든, 모니터든 보안성이 낮은 공간에 실수로 패스워드를 출력해 버릴 가능성이 훨씬 커요.

char[]는 그럴 위험이 적죠.

 

다음 예시를 보고 생각해 보세요."

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);
    //"Password"라는 문자열을 String 타입으로 저장 후 출력.

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
    //"Password"라는 문자열을 char[]로 변환 후 출력.
}

출력 결과 :

String: Password //문자열 'Password'가 그대로 출력됨.
Array: [C@5829428e //문자열 'Password'가 아닌 배열의 주솟값이 출력됨.

 

[역주] 왜 String과 char[]의 출력 결과가 서로 다를까요?

String과 char[]은 모두 ‘참조형 변수'입니다.
참조형 변수에는 배열과 같은 ‘객체'의 주솟값이 저장이 되며,
따라서 char[] 타입 변수를 출력하면 배열에 들어있는 문자가 아니라 배열의 주소가 출력됩니다.

하지만 String 타입 변수를 출력하면, 다른 ‘참조형 변수'들과 다르게
배열의 주소가 아니라 배열에 들어있는 문자들이 출력되죠.
String은 char[]타입을 편하게 활용할 수 있도록 특별하게 가공하여 만든 타입인데,
그 목적에 맞게 String 타입 변수를 출력할 때는 배열 내부의 문자를 직접 출력하도록 설계되었기 때문입니다.

 

 

 

 

[관련 자료]

답변자 : Bruno, 2012.01.17.

 

"관련 내용을 공식 문서에서 가져왔으니 참고해 보시기 바랍니다."

 

 

'상식적으로 패스워드를 java.lang.Stirng의 객체에 저장하는게 맞다고 생각할 수도 있겠지만,
String은 불변Immutable이라는 점을 유념하시기 바랍니다.
String에는 사용이 끝난 String의 내용물을 덮어쓰거나, 지워버릴 수 있는 메서드가 정의되어 있지 않습니다.
이런 특징 때문에, String 객체는 이용자 패스워드와 같이 보안상 민감한 정보를 저장하기에 부적절합니다.
보안상 민감한 정보는 언제나 char배열에 저장해야 합니다.'

 

- 자바 암호화 설계 가이드 中 발췌 Java Cryptography Architecture guide 

 

Java Cryptography Architecture (JCA)

The term "Cryptographic Service Provider" (used interchangeably with "provider" in this document) refers to a package or set of packages that supply a concrete implementation of a subset of the JDK Security API cryptography features. The Provider class is

docs.oracle.com

 

 

 

'가이드라인 2-2 : 민감한 정보를 로그로 남기지 않을 것

사회보장번호(SSN, 주민등록번호와 유사한 미국의 개인 식별 번호)나 비밀번호 같은 정보는 상당히 민감합니다.
이런 정보는 필요 이상으로 오래 저장해 둬서는 안됩니다. 외부에 노출될 우려가 있는 공간은 물론이고, 관리자에게도 마찬가지입니다.
예를 들자면, 데이터가 로그 파일에 전송되어선 안 되고, 데이터의 존재가 검색창에 노출되어선 안 됩니다.
일부 일시적인 데이터는 char[]와 같이 가변적인 자료구조에 저장될 수 있고, 또 사용하자마자 지워지도록 할 수 있습니다.'

 

- 자바 시큐어 코딩 가이드라인 ver 4.0 中 발췌

Guideline 2-2 of the Secure Coding Guidelines for the Java Programming Language, Version 4.0

 

Secure Coding Guidelines for Java SE

Introduction Java's architecture and components include security mechanisms that can help to protect against hostile, misbehaving, or unsafe code. However, following secure coding best practices is still necessary to avoid bugs that could weaken security a

www.oracle.com

 

Comments