2013-08-14 2 views
41

표준 JDK를 사용하여 Java에서 안전한 무작위 AES 키를 생성하는 권장 방법은 무엇입니까? 다른 게시물에서 Java에서 보안 무작위 AES 키를 만드는 방법은 무엇입니까?

, 나는이를 발견하지만, SecretKeyFactory을 사용하는 것이 더 좋은 생각이 될 수 있습니다 대답은 그것이를 생성하는 좋은 방법입니다 이유에 대한 설명을 포함하는 경우

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey(); 

그것은 좋은 것입니다 무작위 키. 감사!

+0

이 mighth 도움 http://stackoverflow.com/questions와 랜드를 대체 : 이것은 내가 무엇을 사용/10252449/is-aes-key-random – Tala

+0

@Tala 이것이 내가 [인용 된 코드] (http://stackoverflow.com/a/10252662/1005481)를 발견 한 곳입니다. 그러나 그 글에서 무작위 키를 만드는 법에 대한 합의를 결정할 수 없었고, 왜 그것이 안전한 방법인지를 결정할 수 없었습니다. –

답변

53

나는 당신의 제안 코드를 사용,하지만 약간의 단순화와 함께 :

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
keyGen.init(256); // for example 
SecretKey secretKey = keyGen.generateKey(); 

는 공급자가 랜덤 획득 할 계획이다 방법을 선택하자 - 무엇을 제공 떨어질 수 있습니다 뭔가를 정의하지 않습니다를 이미 선택되었습니다.

이 코드 예에서는 java.security 파일이 기본 설정 공급자를 목록 맨 위에 포함하도록 구성했다고 가정합니다 (as Maarten points out below). 공급자를 직접 지정하려면 KeyGenerator.getInstance("AES", "providerName");으로 전화하십시오. 진정한 보안 키를 들면

, 당신은 생성하고 키를 보호하기 위해 hardware security module (HSM)을 사용해야합니다. HSM 제조업체는 일반적으로 위의 코드를 사용하여 모든 핵심 세대를 수행 할 JCE 제공 업체를 제공합니다.

+1

일반적으로 공급자 이름도 생략합니다. 플랫폼을 설정합니다 (예 :'java.security' 파일을 사용하거나'Security.addProvider()'를 사용하여 프로그래밍 방식으로'Provider'를 구성하는 것과 마찬가지로). 그렇지 않으면 코드의 이식성이 떨어지며 사용자가 예를 들어 응용 프로그램 코드를 변경하지 않고 HSM. –

+0

공급자를 지정해야하는 이유는 무엇입니까? 기본 동작은 알고리즘을 지원하는 가장 우선 순위가 높은 설치된 제공 업체를 사용하는 것으로 충분합니다. –

+2

모든 키 생성 방법이 동일하게 생성되는 것은 아니며 예를 들어 프로 바이더의 열쇠 생성 메소드 이것은 특히 보안 토큰 제공자에게 유용합니다. 하지만 AES의 경우 난수 생성기가 더 중요 할 수 있습니다. 예를 들어 기본값보다 더 느리고 안전하며 FIPS 인증 난수 생성기를 사용할 수 있습니다. –

19

선호하는 방법이 될 것입니다 KeyGenerator 사용. 던컨 (Duncan)이 지적했듯이 초기화하는 동안 키 크기를 확실히 지정합니다. KeyFactory은 기존 키에 사용해야하는 방법입니다.

좋아, 그럼이의 핵심적 껄끄 러운 얻을 수 있습니다. 원칙적으로 AES 키는 모든 값을 가질 수 있습니다. (3) DES와 같이 "약한 열쇠"는 없습니다. 또한 (3) DES 패리티 비트와 같이 특정 의미를 갖는 비트도 없습니다. 따라서 키를 생성하는 것은 임의의 값을 갖는 바이트 배열을 생성하고 그 주위에 SecretKeySpec을 생성하는 것처럼 간단 할 수 있습니다.

그러나 여전히 사용하는 방법에는 장점이 있습니다. KeyGenerator은 특별히 키를 생성하기 위해 만들어졌습니다. 즉, 코드가이 세대에 맞게 최적화 될 수 있습니다. 이 의 효율성과 보안 이점을 가질 수 있습니다. 예를 들어, 키를 노출시키는 타이밍 측면 채널 공격을 피하도록 프로그래밍 될 수 있습니다. 키 정보가 스왑 파일로 누출 될 수 있으므로 byte[]을 지우는 것이 좋습니다. (어쨌든 이런 경우 일 수 있습니다.) 말했듯

또한, 모든 알고리즘은 완전 랜덤 키를 사용한다. 따라서 KeyGenerator을 사용하면 다른 알고리즘으로 쉽게 전환 할 수 있습니다. 보다 현대적인 암호는 완전히 무작위 키만을 받아 들일 것입니다. 이것은 예를 들어 DES.

마지막으로, 내 경우에는 가장 중요한 이유는 KeyGenerator 메서드가 보안 토큰 (스마트 카드, TPM, USB 토큰 또는 HSM) 내에서 AES 키를 처리하는 유일한 유효한 방법이라는 것입니다. 그런 다음 SecretKeySpec으로 byte[]를 만드는 경우 키 메모리에서 가져와야합니다. 즉, 키가 보안 토큰에 포함될 수 있지만 키는 메모리에 관계없이 노출됩니다. 일반적으로 보안 토큰은 보안 토큰에서 생성 된 키로 만 작동하거나 예를 들어 스마트 카드 또는 키 의식. KeyGenerator은 제공자와 함께 제공되어 키가 보안 토큰 내에서 직접 생성 될 수 있습니다.

Duncan's answer에 표시된대로 항상 키 크기 (및 기타 매개 변수)를 명시 적으로 지정하십시오. 일 때 응용 프로그램의 작업 내용이 명확하지 않으며 각 공급자마다 고유 한 기본값이있을 수 있으므로 공급자 기본값을 사용하지 마십시오.

+0

이 우수한 배경 정보를 보내 주셔서 감사합니다! –

+0

더 많은 즐거움. 평소와 같이 훌륭한 답변 :-) –

2

다른 게시물의 장점이 많습니다. 당신은 내가 언젠가 테스트 목적을 위해 할 또 다른 임의성 제공을해야하는 경우

Key key; 
SecureRandom rand = new SecureRandom(); 
KeyGenerator generator = KeyGenerator.getInstance("AES"); 
generator.init(256, rand); 
key = generator.generateKey(); 

, 그냥

MySecureRandom rand = new MySecureRandom(); 
+0

처음으로 무작위 생성기를 지정하면 두 번째로 AES 키의 길이 (256)를 사용합니다. 그들은 별도의 init 메소드입니다. – Andy

관련 문제