2011-03-08 8 views
11

ठीक है, यह उन लोगों में से एक है "मेरे पास कोई वास्तविक विचार नहीं है कि प्रश्न कहां से शुरू करें", इसलिए उम्मीद है कि उत्तर सरल है। हालांकि, मुझे वास्तव में पता नहीं है कि क्या खोजना है, और मेरे प्रयासों ने अब तक बहुत अधिक उपयोग नहीं किया है।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 कुंजी बहुत पहले टूट गए हालांकि, काम करने के लिए एपीआई प्राप्त करने की कोशिश के लिए, मैं प्रणाली निकास का कोई कारण नहीं देखते हैं एन्ट्रापी की आपूर्ति बेकार में)

कोड इस प्रकार दूर है:।

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 मानक जावा से हिस्सा नहीं है; मुझे लगता है कि आप OpenSAML से org.opensaml.xml.security.x509.BasicX509Credential के बारे में बात कर रहे हैं।

आप PrivateKey चाहते हैं जिसे आप credential.setPrivateKey() के साथ सेट करेंगे। फिर, जावा से

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

: एक PrivateKey पाने के लिए आपको पहले निजी कुंजी को एक प्रारूप है कि जावा, पढ़ सकते हैं अर्थात् PKCS # 8 में परिवर्तित करना होगा

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 अपने स्वयं के प्रारूप में लिखते हैं कुंजी, और यह पीईएम में उन्हें encodes, (आरएसए चाबी के लिए, PKCS # 8 उस प्रारूप के चारों ओर एक आवरण होता है) एक शीर्ष लेख और पाद लेख के साथ जो Base64। दोनों विशेषताएं सादे जावा द्वारा असमर्थित हैं, इसलिए पीकेसीएस # 8 में रूपांतरण। -nocrypt विकल्प इसलिए है क्योंकि PKCS # 8 निजी कुंजी के वैकल्पिक पासवर्ड-आधारित एन्क्रिप्शन का समर्थन करता है।

चेतावनी: तुम सच में वास्तव में एक लंबे समय तक RSA कुंजी का उपयोग करना चाहते। 512 बिट कमजोर हैं; 1 999 में कुछ सौ कंप्यूटरों के साथ 512-बिट आरएसए कुंजी टूट गई थी। 2011 में, तकनीकी प्रगति के 12 वर्षों के साथ, किसी को यह मानना ​​चाहिए कि लगभग 512-बिट आरएसए कुंजी लगभग किसी के द्वारा तोड़ दी जा सकती है। इसलिए, 1024-बिट आरएसए कुंजी कम से कम (अधिमानतः, 2048-बिट; कुंजी का उपयोग करते समय कम्प्यूटेशनल ओवरहेड का उपयोग करना बुरा नहीं है, फिर भी आप प्रति सेकेंड हस्ताक्षर करने में सक्षम होंगे)।

+0

हाँ, BasicX509Credential OpenSAML से है, कि निरीक्षण के बारे में खेद है। मैं निश्चित रूप से यह कोशिश करूँगा। और हाँ, मुझे पूरी तरह से पता है कि 512-बिट आरएसए कुंजी किसी भी माध्यम से सुरक्षित नहीं हैं, लेकिन यह विशेष सेटअप * सख्ती से * चीजों को काम करने की कोशिश करने के लिए * है, इसलिए मुख्य लंबाई एक गैर-मुद्दा है। –

+0

एक आकर्षण की तरह काम करने लगता है, बहुत बहुत धन्यवाद! बेशक, मेरा हस्ताक्षर कोड टूटा हुआ प्रतीत होता है, लेकिन कम से कम डीबगर के अनुसार, मुझे डिस्क पर दो फाइलों से उचित 'प्रमाण पत्र' मिलता है। दौरे के साथ ... –

+0

धन्यवाद। विंडोज़ में < and > को रीडायरेक्ट करने के साथ मुझे रहस्यमय परेशानी थी, इसलिए कोई उन्हें इन-आउट और आउट स्विच के साथ बदलना चाहता है। –

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 पर पाने के लिए कोशिश कर रहे हैं लग रहा है।

धन्यवाद, योगेश

संबंधित मुद्दे