2017-01-09 4 views
-1

작업하고있는 다른 서비스로 SSO 트랜잭션을 수행하기 위해 SAML Payload 준비를위한 OpenSAML 지원을 사용하여 막 다른 골목에 섰습니다. SecurityHelper.prepareSignatureParams() 루틴을 사용하면 throw되는 NullPointerException이 발생합니다. 나는 Stacktrace를 가지고있다. 그러나 추가하기가 꽤 어렵다.java.lang.NullPointerException SecurityHelper.prepareSignatureParams() OpenSAML 호출 중 오류가 발생했습니다.

내가 먼저 내가 할 수 있었던 것을 가정 해 봅시다 ... 기술과 일하는 것이 있는지 확인하는 학습의 목적을 위해

, 나는 성공적하는 SAML 페이로드를 빌드를 사용하여 로그인 할 수 있었다 인증서 및 -genkeypair 옵션과 함께 Keytool 프로그램을 사용하여 워크 스테이션에서 로컬로 생성 한 Java 키 저장소 파일에 저장된 개인 키.

내가 아는 바로, JKS 파일에는 자체 서명 된 인증서와 개인 키가 있습니다. JKS 파일을 열고 인증서와 개인 키를 수집하여 서명 인증서를 만들 수있었습니다. 서명 인증서가 내가 작성한 SAML 페이로드에 서명하는 데 사용되었습니다. 내가 추가 할 코드 샘플을 보면 어떻게되었는지 확인할 수 있습니다. 작동하지 않는 무엇

...

나는 내가 GoDaddy를로부터받은 내 웹 사이트가 신뢰할 수있는 인증서를 사용하여 내 SAML 페이로드에 서명 같은 SAML 지원을 사용하고 싶습니다. 이를 위해 신뢰할 수있는 인증서를 웹 서버의 키 저장소 인 '\ Program Files \ Java \ jre1.8.0_102 \ lib \ security \ cacerts'에 설치했습니다. 저는 cacerts 파일이 웹 서버의 KeyStore라는 것을 알고 있습니다. Keytool -importcert 명령을 사용하여 신뢰할 수있는 인증서를 설치했습니다. 한 가지 큰 차이점은 신뢰할 수있는 인증서에 개인 키가 없다는 점입니다. 따라서 Open SAML 지원을 사용하여 서명 인증서를 준비 할 때 자격 증명 개체에 개인 키를 추가 할 수 없습니다 (권한 키가 없기 때문에).

신뢰할 수있는 인증서를 위와 같이 시도하면 Signature Parms (SecurityHelper.prepareSignatureParams())를 준비하는 부분으로 이동할 수 있습니다. 그것이 Null Pointer를 얻는 곳입니다.

내가 사용중인 코드를 살펴볼 수 있다면. 나는 서버 (두 경우 모두)에서 신뢰할 수있는 인증서를 사용하려고 할 때 로컬 JKS 파일 및 Null 포인터 예외를 가져 오는 코드에서 읽는 코드 (성공적으로 내 페이로드에 서명)를 포함합니다. 두 경우 사이에 큰 차이가 아니다 :

// Signing process using OpenSAML 

// Get instance of an OpenSAML 'KeyStore' object... 
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 

// Read KeyStore as File Input Stream. This is either the local JKS 
// file or the server's cacerts file. 
File ksFile = new File(keyStoreFileName); 

// Open an Input Stream with the Key Store File 
FileInputStream ksfInputStream = new FileInputStream(ksFile); 

// Load KeyStore. The keyStorePassord is the password assigned to the keystore, Usually 'changeit' 
// before being changed. 
keyStore.load(ksfInputStream, keyStorePassword); 

// Close InputFileStream. No longer needed. 
ksfInputStream.close(); 


// Used to get Entry objects from the Key Store 
KeyStore.PrivateKeyEntry pkEntry = null; 
KeyStore.TrustedCertificateEntry tcEntry = null; 

PrivateKey pk     = null; 
X509Certificate x509Certificate = null; 

BasicX509Credential credential = null; 

// The Java Key Store specific code... 
// Get Key Entry From the Key Store. CertificateAliasName identifies the 
// Entry in the KeyStore. KeyPassword is assigned to the Private Key. 
pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(certificateAliasName, new KeyStore.PasswordProtection(keyPassword)); 

// Get the Private Key from the Entry 
pk = pkEntry.getPrivateKey(); 

// Get the Certificate from the Entry 
x509Certificate = (X509Certificate) pkEntry.getCertificate(); 

// Create the Credential. Assign the X509Certificate and the Privatekey 
credential = new BasicX509Credential(); 
credential.setEntityCertificate(x509Certificate); 
credential.setPrivateKey(pk); 


// The Trusted Certificate specific code... 
// Accessing a Certificate that was issued from a trusted source - like GoDaddy.com 
// 
// Get Certificate Entry From the Key Store. CertificateAliasName identifies the Entry in the KeyStore. 
// There is NO password as there is no Private Key associate with this Certificate 

tcEntry = (TrustedCertificateEntry) keyStore.getEntry(certificateAliasName, null); 

// Get the Certificate from the Entry 
x509Certificate = (X509Certificate) tcEntry.getTrustedCertificate(); 

// Create the Credential. There is no Provate Ley to assign into the Credential 
credential = new BasicX509Credential(); 
credential.setEntityCertificate(x509Certificate); 


// Back to code that is not specific to either method... 
// 
// Assign the X509Credential object into a Credential Object. The BasicX509Credential object 
// that has a Certificate and a Private Key OR just a Certificate added to it is now saved as a 
// Cendential object. 
Credential signingCredential = credential; 


// Use the OpenSAML builder to create a signature object. 
Signature signingSignature = (Signature) Configuration.getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME).build Object(Signature.DEFAULT_ELEMENT_NAME); 

// Set the previously created signing credential 
signingSignature.setSigningCredential(signingCredential); 

// Get a Global Security Configuration object. 
SecurityConfiguration secConfig = Configuration.getGlobalSecurityConfiguration(); 

// KeyInfoGenerator. Not sure what this is, but the example I am working from shows 
// this being passed as null. 
String keyInfoGeneratorProfile = "XMLSignature"; 

// Prepare the Signature Parameters. 
// 
// This works fine for the JKS version of the KeyStore, but gets a Null Pointer exception when I run to the cacerts file. 
SecurityHelper.prepareSignatureParams(signingSignature, signingCredential, secConfig, keyInfoGeneratorProfile <or null>); 

// I need to set into the SigningSignature object the signing algorithm. This is required when using the TrustedCertificate 
signingSignature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); 



// This is my code that builds a SAML Response. The SAML Payload contains data 
// about the SSO session that I will be creating... 
Response samlResponse = createSamlResponse.buildSamlResponseMessage(); 

// Sign the Response using the Certificate that was created earlier 
samlResponse.setSignature(signingSignature); 



// Get the marshaller factory to marshall the SamlResponse 
MarshallerFactory marshallerFactory = Configuration.getMarshallerFactory(); 
Marshaller responseMarshaller = marshallerFactory.getMarshaller(samlResponse); 

// Marshall the Response 
Element responseElement = responseElement =  responseMarshaller.marshall(samlResponse); 

// Sign the Object... 
Signer.signObject(signingSignature); 

참고 : https://narendrakadali.wordpress.com/2011/06/05/sign-assertion-using-opensaml/

누군가가 나에게의 오류를 보여줄 수 있다는 기대하십시오 SAML 페이로드에 서명 내 시도가 여기 발견되는 OPENSAML 예를 모델로했다 내 길이나 내가 놓친 것.

의견을 보내 주셔서 감사합니다.

EDIT (2016년 1월 26일)

나는 서명에 Params를 준비하는 동안 수신 된 NULL 포인터 과거를 얻을 수 있었다 (SecurityHelper.prepareSignatureParams()). 코드 변경에는 내 xmlsec.jar 파일을 2.0.8 (xmlsec-2.0.8.jar) 버전으로 업데이트하고 GoDaddy의 신뢰할 수있는 인증서를 사용할 때 서명 알고리즘을 SHA256으로 명시 적으로 설정하는 작업이 포함되었습니다. 의 사용에 대한 내 코드의 예를 참조하십시오

signingSignature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); 

위의 변화는 SAML 페이로드 구축하고 연결 엔드 포인트에 송신 할 수 있습니다.

그러나 아직 내 끝점에 SSO 연결을 설정하지 않았습니다. 처리하는 동안

는 SAML 페이로드가 구축되고 있으며, 구체적으로는 SAML 페이로드의 서명이 서명하는 동안 :

Signer.signObject(signature); 

내가 SAML에서 오류 메시지가 여기에

내가 일어나고 참조 내용은 다음과 같습니다

ERROR: org.opensaml.xml.signature.Signer - An error occured computing the digital signature 

스택 트레이스 (단지 끝 부분)

org.apache.xml.security.signature.XMLSignatureException: Sorry, you supplied the wrong key type for this operation! You supplied a null but a java.security.PrivateKey is needed. 
at org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.engineInitSign(SignatureBaseRSA.java:149) 
at org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.engineInitSign(SignatureBaseRSA.java:165) 
at org.apache.xml.security.algorithms.SignatureAlgorithm.initSign(SignatureAlgorithm.java:238) 
at org.apache.xml.security.signature.XMLSignature.sign(XMLSignature.java:631) 
at org.opensaml.xml.signature.Signer.signObject(Signer.java:77) 

오류 메시지를 검색했지만 많이 개선하지 않았습니다.

오류 메시지의 루트를 이해하지 못합니다. 잘못된 키 유형 (null)이 제공되었고 OpenSAML이 java.Security.PrivateKey를 기다리고있는 것 같습니다.

신뢰할 수있는 인증서를 사용할 때 개인 키가 없습니까? 맞나요? 개인 키를 어떻게 제공 할 수 있습니까? 신뢰할 수있는 인증서의 경우 KeyStore에서 신뢰할 수있는 인증서 (TrustedCertificateEntry)를 읽었습니다. TrustedCertificateEntry 개체를 사용하면 인증서에 액세스 할 수 있지만 비공개 키를 얻을 수있는 방법은 없습니다.

그러나 자체 서명 된 인증서를 사용하여 서명 작업을 수행 할 때 인증서 (공개 키)와 JKS 파일 (키 저장소)에 포함 된 개인 키가 모두 있다는 것을 알고 있습니다. 그 이유는 JKS 파일에서 읽을 때 공개 키 (인증서)와 개인 키 모두에 액세스하기위한 메서드가있는 개인 키 항목 (KeyStore.PrivateKeyEntry)을 읽을 수 있기 때문입니다.

신뢰할 수있는 인증서의 경우에는 무엇이 누락 되었습니까? OpenSAML 지원은 개인 키가 서명을 계산할 수있을 것으로 기대하는 것 같습니다.

신뢰할 수있는 인증서의 경우 신뢰할 수있는 인증서와 함께 원래의 개인 키를 키 저장소에 패키지하는 방법이 있습니까? 이것이 정상적으로 수행되는지 또는 가능한지 확실하지 않습니다.

내가 여기서 뭘하고 있는지에 대한 약간의 지침을 바랍니다.

EDIT (01/26/2017) - 2 자세한 내용을 제공합니다.

내가 보낸 가져옵니다 SAML 페이로드의 일부를 공유 할 ... 인증서 서명 자체의 경우

, 나는 SignatureValue를 태그와 X509Certificate에 태그를 참조하십시오. 둘 다 이진 데이터를 태그 시작과 끝 부분에 포함합니다.

<ds:SignatureValue/> 

인증서 태그가 여전히 존재하고 인증서 바이트를 포함 : 신뢰할 수있는 인증서의 경우

, 나는처럼 보이는 빈 서명 값 태그를 가지고있다.

OpenSAML에서 볼 수있는 오류를 보면 신뢰할 수있는 인증서에서 사용할 수있는 데이터를 사용하여 서명을 계산할 수 없다는 것이 더욱 분명합니다.

+0

제 질문은 Null Pointer 예외를 처리하는 것이 아니라 Null Pointer가 나타나는 OpenSAML 패키지에서 무엇을하는지에 대한 질문이었습니다. 아마도이 질문의 제목을 더 정확하게 지정할 수 있습니까? 질문이 길어 졌음을 알고 있지만 OpenSAML 지원을 사용하는 다른 사람들에게 유용 할 수 있습니다. – SBParks

답변

1

좋습니다. 꽤 긴 질문입니다. 문제의 근본 원인을 알기 때문에 "죄송합니다.이 작업에 잘못된 키 유형을 제공했습니다. null을 제공했지만 java.security.PrivateKey가 필요합니다." 공개 키를 사용하여 메시지에 서명하려고합니다. 이건 불가능 해. 논리적으로 보면 공개 키를 사용하여 서명하는 것은 서명자가 의도 한 증거를 모든 사람이 사용할 수있는대로 제공하지 않습니다.

개인 키를 사용하여 로그인해야합니다. 귀하의 컴퓨터에서 공용 및 개인 키를 생성 한 다음 CSR을 CA에 보내고 CA가 서명 한 인증서를 받았습니다. 로컬 컴퓨터의 privat 키를 사용하여 메시지에 서명하고 CA 서명 된 인증서를받는 사람에게 보내 사용자가 서명을 확인하는 데 사용할 수 있도록해야합니다.

this blog post of mine에는 Java 키 저장소에서 개인 키를 비롯하여 자격 증명을 얻는 방법이 설명되어 있습니다.

+0

스테판, 답장을 보내 주셔서 감사합니다. 죄송합니다, 위의 질문이 길다는 것을 인정합니다. – SBParks

+0

그러나 아직 이해할 수없는 것이 있습니다 ... CA (이 경우 GoDaddy)에서 얻은 신뢰할 수있는 인증서를 사용하여 SAML 페이로드에 서명하려면 어떻게해야합니까? 인증서 (공개 키)와 CA에서 신뢰 인증서 (CSR)를 요청하기 위해 생성 및 사용 된 개인 키가 포함 된 원본 JKS 자체 서명 인증서를 사용해야 할 필요가 있습니까? 이 경우 신뢰할 수있는 인증서 또는 JKS 파일에 포함 된 인증서에 대한 연결을 시도하는 당사자와 어떤 인증서를 공유합니까? – SBParks

+0

업데이트 된 답변 –