2011-03-03 5 views
7

मैं जावा में सफलतापूर्वक आरएसए एन्क्रिप्शन/डिक्रिप्शन चला रहा हूं। इस तरह मैंने कुंजी उत्पन्न की।जावा में एक्सएमएल के लिए आरएसए कुंजी ऑब्जेक्ट का निर्यात

 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path)); 
     KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
     kpg.initialize(1024); 
     KeyPair keypair = kpg.generateKeyPair(); 
     oos.writeObject(keypair); 

लेकिन अब मुझे अपने सिस्टम को नेट कोड के साथ एकीकृत करने की आवश्यकता है। क्या यह संभव है निम्नलिखित प्रारूप में XML में इस keypair वस्तु निर्यात करने के लिए (के रूप में है कि नेट कोड केवल XML स्वरूप में चाबियाँ स्वीकार कर सकते हैं):

<RSAKeyValue> 
    <Modulus>.....</Modulus> 
    <Exponent>......</Exponent> 
    <P>.....</P> 
    <Q>....</Q> 
    <DP>.......</DP> 
    <DQ>......</DQ> 
    <InverseQ>.........</InverseQ> 
    <D>........</D> 
</RSAKeyValue> 
+1

एक कुंजी युग्म कोई एन्क्रिप्शन के साथ इस तरह से भंडारण (इस प्रकार अपनी निजी कुंजी उजागर छोड़कर) एक सच में, सच बुरा विचार है। – Hut8

+0

कुंजीपटल के लिए अपना स्वयं का रैपर क्लास बनाएं जो Serializable इंटरफ़ेस लागू करता है। 'ReadObject()', 'writeObject()', और 'readObjectNoData()' विधियों को ओवरराइड करें। –

+0

@ bowenl2 क्या आप अन्य प्लेटफार्मों के साथ एकीकृत करने के लिए कोई अच्छा तरीका सुझा सकते हैं? – dvl

उत्तर

11

इस प्रयास करें:

// key pair is in 'kp' 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
RSAPrivateCrtKeySpec ks = kf.getKeySpec(
    kp.getPrivate(), RSAPrivateCrtKeySpec.class); 
System.out.println("<RSAKeyValue>"); 
System.out.println(" <Modulus>" + ks.getModulus() + "</Modulus>"); 
System.out.println(" <Exponent>" + ks.getPublicExponent() + "</Exponent>"); 
System.out.println(" <P>" + ks.getPrimeP() + "</P>"); 
System.out.println(" <Q>" + ks.getPrimeQ() + "</Q>"); 
System.out.println(" <DP>" + ks.getPrimeExponentP() + "</DP>"); 
System.out.println(" <DQ>" + ks.getPrimeExponentQ() + "</DQ>"); 
System.out.println(" <InverseQ>" + ks.getCrtCoefficient() + "</InverseQ>"); 
System.out.println(" <D>" + ks.getPrivateExponent() + "</D>"); 
System.out.println("</RSAKeyValue>"); 

यह जो आंतरिक रूप से 'सीआरटी' प्रतिनिधित्व का उपयोग सभी RSA कुंजी जोड़े के लिए काम करेंगे, और निर्यात अनुमति देते हैं; यह कुंजी जोड़े के लिए मामला है कि जेडीके आपके द्वारा दिखाए गए कोड के साथ डिफ़ॉल्ट रूप से जेनरेट करेगा।

(यहाँ मैं बजाय एक फ़ाइल में लिखने की System.out पर कुंजी प्रिंट आउट, लेकिन आप विचार मिलता है।)

+1

जब मैंने टेक्स्ट को एन्क्रिप्ट करने के लिए सी # में इस कोड का उपयोग किया, तो मुझे मिला: ** क्रिप्टोग्राफिक एक्सेप्शन (खराब डेटा) ** –

0

आप इस तरह है कि यह बजाय एक्सएमएल के लिए आउटपुट XMLObjectOutputStream के कुछ फार्म हो सकता है here में एक स्वामित्व बाइनरी प्रारूप का।

3

थॉमस Pornin के समाधान अनिवार्य रूप से सही है लेकिन मेरे लिए काम नहीं किया क्योंकि तरीकों, जैसे getModulus(), BigInteger को वापस करें जिसके परिणामस्वरूप एक संख्यात्मक स्ट्रिंग होती है, जबकि मानक .NET XML प्रारूप बेस 64 एन्कोडेड बाइट्स का उपयोग करता है।

मैंने बाइट प्राप्त करने के लिए "getModulus()। ToByteArray()" का उपयोग किया। तब मुझे सरणी के पहले तत्व को ट्रिम करने की आवश्यकता थी (एक्सपोनेंट को छोड़कर) क्योंकि वहां एक अवांछित शून्य बाइट है। (मुझे लगता है क्योंकि BigInteger पर हस्ताक्षर किए गए हैं, यह एक अतिरिक्त बाइट जोड़ता है ताकि अग्रणी बिट संकेत इंगित कर सके)।

मैंने गिटहब पर the code पोस्ट किया है।

मुख्य सा है:

static String getPrivateKeyAsXml(PrivateKey privateKey) throws Exception{ 
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
    RSAPrivateCrtKeySpec spec = keyFactory.getKeySpec(privateKey, RSAPrivateCrtKeySpec.class); 
    StringBuilder sb = new StringBuilder(); 

    sb.append("<RSAKeyValue>" + NL); 
    sb.append(getElement("Modulus", spec.getModulus())); 
    sb.append(getElement("Exponent", spec.getPublicExponent())); 
    sb.append(getElement("P", spec.getPrimeP())); 
    sb.append(getElement("Q", spec.getPrimeQ())); 
    sb.append(getElement("DP", spec.getPrimeExponentP())); 
    sb.append(getElement("DQ", spec.getPrimeExponentQ())); 
    sb.append(getElement("InverseQ", spec.getCrtCoefficient())); 
    sb.append(getElement("D", spec.getPrivateExponent())); 
    sb.append("</RSAKeyValue>"); 

    return sb.toString(); 
} 

static String getElement(String name, BigInteger bigInt) throws Exception { 
    byte[] bytesFromBigInt = getBytesFromBigInt(bigInt); 
    String elementContent = getBase64(bytesFromBigInt); 
    return String.format(" <%s>%s</%s>%s", name, elementContent, name, NL); 
} 

static byte[] getBytesFromBigInt(BigInteger bigInt){ 
    byte[] bytes = bigInt.toByteArray(); 
    int length = bytes.length; 

    // This is a bit ugly. I'm not 100% sure of this but I presume 
    // that as Java represents the values using BigIntegers, which are 
    // signed, the byte representation contains an 'extra' byte that 
    // contains the bit which indicates the sign. 
    // 
    // In any case, it creates arrays of 129 bytes rather than the 
    // expected 128 bytes. So if the array's length is odd and the 
    // leading byte is zero then trim the leading byte. 
    if(length % 2 != 0 && bytes[0] == 0) { 
     bytes = Arrays.copyOfRange(bytes, 1, length); 
    } 

    return bytes; 
} 

static String getBase64(byte[] bytes){ 
    return Base64.getEncoder().encodeToString(bytes); 
} 
+0

क्या इसे मैन्युअल रूप से करने के अलावा RSAKeyValue टैग के बीच में रखने का कोई तरीका नहीं है, उदाहरण के लिए स्वचालित रूप से कनवर्ट करें। नेट प्रारूप या कुछ समान है? – Gravity

+0

@ गुरुत्वाकर्षण मुझे एक नहीं मिला। पूरे अभ्यास ने मुझे महसूस किया कि मुझे कुछ स्पष्ट याद आ रही है। – codybartfast

+0

मुझे कोई भी नहीं मिला, मैंने आपके कोड को जिथब पर देखा, मुझे उम्मीद है कि यह काम करता है, मैं वही काम करने की कोशिश कर रहा हूं जैसा कि आप – Gravity

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