2011-03-08 5 views
11

OK, 이것은 "나는 어디서부터 시작해야 할 지 전혀 모른다"라는 질문 중 하나이기 때문에 대답은 간단합니다. 그러나, 나는 무엇을 검색해야하는지 정말로 모른다. 그리고 나의 시도는 지금까지 많이 사용하지 않았다.OpenSAML에서 사용할 개인 키를 읽는 방법은 무엇입니까?

(현재 디스크에있는) 파일에서 개인 키를 읽으 려합니다. 궁극적으로 키는 데이터베이스에 상주 할 것입니다. 그러나 이것은 잠시 동안 충분히 좋을 것이고 그 차이는 핵심 자료를 분석하는 데 실제적인 영향을 미치지 않아야합니다. 키의 공용 부분 (디버거에 의해 확인 됨)을 보유하는 Credential 인스턴스를 만들 수 있었지만 개인 부분을 읽는 방법을 파악할 수 없습니다. . 같이 키 쌍을 생성되었습니다

openssl genrsa 512 > d:\host.key 
openssl req -new -x509 -nodes -sha1 -days 365 -key d:\host.key > d:\host.cert 

(예, 512 비트 RSA 키는 오래 전에 파괴 된 것을 알고있는 API가 작동하도록 노력을 위해, 그러나, 나는 시스템을 배출 할 이유가 없다 불필요하게 엔트로피 공급)

코드는 지금까지입니다.

import org.opensaml.xml.security.credential.Credential; 
import org.opensaml.xml.security.x509.BasicX509Credential; 

private Credential getSigningCredential() 
throws java.security.cert.CertificateException, IOException { 
    BasicX509Credential credential = new BasicX509Credential(); 

    credential.setUsageType(UsageType.SIGNING); 

    // read public key 
    InputStream inStream = new FileInputStream("d:\\host.cert"); 
    CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
    X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream); 
    inStream.close(); 
    credential.setEntityCertificate(cert); 

    // TODO: read private key 

    // done. 
    return credential; 
} 

하지만 어떻게 credential의 개인 키 부분에 파일 host.key을 읽을 할, 그래서 사용할 수있는생성인스턴스에 데이터 서명 하시겠습니까?

답변

19

BasicX509Credential은 표준 Java의 일부가 아닙니다. OpenSAML의 org.opensaml.xml.security.x509.BasicX509Credential에 대한 이야기입니다.

으로 설정할 PrivateKey을 원하게됩니다. PrivateKey을 얻으려면, 먼저 자바 즉 PKCS 번호 8을 읽을 수있는 형식으로 개인 키를 변환해야합니다 :

openssl pkcs8 -topk8 -nocrypt -outform DER <D:\host.key> D:\host.pk8 

을 그리고, 자바에서 :

RandomAccessFile raf = new RandomAccessFile("d:\\host.pk8", "r"); 
byte[] buf = new byte[(int)raf.length()]; 
raf.readFully(buf); 
raf.close(); 
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(buf); 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
PrivateKey privKey = kf.generatePrivate(kspec); 

봐라을! 당신은 PrivateKey입니다. 기본적으로

openssl 자신의 형식으로 키를 쓰기는 PEM에서 그들을 인코딩, (RSA 키 위해, PKCS # 8가 해당 형식의 주위에 래퍼 될 일) 헤더와 바닥 글에있는 Base64로. 두 특성 모두 일반 Java에서는 지원되지 않으므로 PKCS # 8로 변환됩니다. -nocrypt 옵션은 PKCS # 8이 개인 키의 선택적 암호 기반 암호화를 지원하기 때문입니다.

경고 : 정말로 정말로 더 긴 RSA 키를 사용하고 싶습니다. 512 비트가 약합니다. 1999 년 몇 백 대의 컴퓨터로 512 비트 RSA 키가 깨졌습니다. 2011 년에는 12 년의 기술 발전으로 거의 모든 사람이 512 비트 RSA 키를 손상시킬 수 있다고 가정해야합니다. 따라서 1024 비트 RSA 키 이상 (예 :)을 사용하십시오 (키를 사용할 때 계산상의 오버 헤드가 그렇게 나쁘지 않은 경우 초당 수백 개의 서명을 수행 할 수 있음).

+0

예, BasicX509Credential는 OpenSAML에서, 즉 감독에 대한 죄송합니다. 나는 이것을 분명히 시도 할 것이다. 그리고 예, 저는 512 비트 RSA 키가 결코 안전하지 않다는 것을 잘 알고 있습니다. 그러나이 특정 설정은 일을 전혀 얻지 않으려 고하는 데만 엄격하게 적용되므로 키 길이는 중요하지 않습니다. –

+0

매력처럼 작동하는 것 같습니다, 대단히 감사합니다! 물론, 내 서명 코드가 깨진 것 같지만 최소한 디버거에 따르면 디스크의 두 파일에서 적절한 Credential을 얻습니다. 투어와 함께 ... –

+0

고맙습니다. Windows에서 < and >을 리다이렉션 할 때 신비한 문제가 있었기 때문에 -in 스위치와 -out 스위치로 바꿀 수 있습니다. –

1

이 질문은 SAML과 관련이 있으며 XMLObject 서명을위한 개인 키를 검색하려는 사람에게도 해당됩니다.대답은 위의 좋은 작품과도 가능뿐만 아니라 키 저장소에서 개인 키를 검색하기 위해이 요청 원래 쿼리보다 코드

 Properties sigProperties = new Properties(); 

    sigProperties.put("org.apache.ws.security.crypto.provider","org.apache.ws.security.components.crypto.Merlin"); 
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.type","jks"); 
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.password","keypass"); 
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.alias","keyalias"); 
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.file","keystore.jks"); 

    Crypto issuerCrypto = CryptoFactory.getInstance(sigProperties); 

    String issuerKeyName = (String) sigProperties.get("org.apache.ws.security.crypto.merlin.keystore.alias"); 

    //See http://ws.apache.org/wss4j/xref/org/apache/ws/security/saml/ext/AssertionWrapper.html 'signAssertion' method 
    // prepare to sign the SAML token 
    CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS); 
    cryptoType.setAlias(issuerKeyName); 
    X509Certificate[] issuerCerts = issuerCrypto.getX509Certificates(cryptoType); 
    if (issuerCerts == null) { 
     throw new WSSecurityException(
       "No issuer certs were found to sign the SAML Assertion using issuer name: " 
         + issuerKeyName); 
    } 

    String password = ADSUnitTestUtils.getPrivateKeyPasswordFromAlias(issuerKeyName); 

    PrivateKey privateKey = null; 
    try { 
     privateKey = issuerCrypto.getPrivateKey(issuerKeyName, password); 
    } catch (Exception ex) { 
     throw new WSSecurityException(ex.getMessage(), ex); 
    } 


    BasicX509Credential signingCredential = new BasicX509Credential(); 
    signingCredential.setEntityCertificate(issuerCerts[0]); 
    signingCredential.setPrivateKey(privateKey); 

    signature.setSigningCredential(signingCredential); 

하지만 그들이 BasicX509Credential 얻을려고 보인다.

감사합니다, 인 Yogesh