2015-08-20 4 views
6

में फ़ाइल से PublicKey ऑब्जेक्ट कैसे उत्पन्न करें मेरे पास एक सार्वजनिक आरएसए कुंजी युक्त फ़ाइल है (ssh-keygen के साथ उत्पन्न)। मैं फ़ाइल को पढ़ना चाहता हूं और PublicKey ऑब्जेक्ट उत्पन्न करना चाहता हूं।जावा

उसके पहले मैं फ़ाइल परिवर्तित, के बाद से मूल फाइलों को पढ़ने के लिए असंभव प्रतीत हो रहा है:

# http://unix.stackexchange.com/questions/220354/how-to-convert-public-key-from-pem-to-der-format/220356#220356 
ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PEM > ~/.ssh/id_rsa.pub.pem 
openssl rsa -RSAPublicKey_in -in ~/.ssh/id_rsa.pub.pem -inform PEM -outform DER -out ~/.ssh/id_rsa.pub.der -RSAPublicKey_out 

Java - Encrypt String with existing public key file मैं समारोह readFileBytes परिभाषित से:

public static byte[] readFileBytes(String filename) throws IOException { 
    Path path = Paths.get(System.getProperty("user.home") + filename); 
    return Files.readAllBytes(path); 
} 

अब मैं चाहते हैं फ़ाइल को पढ़ें और PublicKey ऑब्जेक्ट जेनरेट करें, लेकिन मुझे ऐसा करने का कोई तरीका नहीं मिला; java.security.spec.RSAPublicKeySpec एक उपयुक्त निर्माता प्रदान नहीं करता है और java.security.spec.X509EncodedKeySpec एक त्रुटि java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence फेंकता है:

//RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(readFileBytes("/.ssh/id_rsa.pub.der")); 
// No fitting construktor 

X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes("/.ssh/id_rsa.pub.der")); 
// Gives: "algid parse error, not a sequence" 

उत्तर

5

मैं एक परियोजना है, जिसमें (आरएसए) एन्क्रिप्शन जरूरी हो गया था, यह मैं कैसे पुनर्निर्माण publicKey दिया publicKey के byte सरणी है था, कि बस फाइल से पढ़ा गया था।

public PublicKey reconstruct_public_key(String algorithm, byte[] pub_key) { 
    PublicKey public_key = null; 

    try { 
     KeyFactory kf = KeyFactory.getInstance(algorithm); 
     EncodedKeySpec pub_key_spec = new X509EncodedKeySpec(pub_key); 
     public_key = kf.generatePublic(pub_key_spec); 
    } catch(NoSuchAlgorithmException e) { 
     System.out.println("Could not reconstruct the public key, the given algorithm oculd not be found."); 
    } catch(InvalidKeySpecException e) { 
     System.out.println("Could not reconstruct the public key"); 
    } 

    return public_key; 
} 

तो फिर तुम प्रक्रिया इस कॉल के समान है, reconstruct_public_key("RSA", readFileBytes("path/to/your/publicKey/file"));

संपादित कह सकते हैं: मैं इसे अपने आप करने की कोशिश की (एक फाइल करने के लिए सार्वजनिक कुंजी लिखते हैं, उस फ़ाइल को पढ़ने के लिए और कुंजी को फिर से संगठित)। यह काम करता है:

public static void main(String args[]) { 
    String path = "./pub_key_test.txt"; 

    // Generate a keypair to write to file 
    KeyPair kp = generate_key(); 
    PublicKey pub_key = kp.getPublic(); 
    File file = new File(path); 

    try { 
     // Write to file 
     file.createNewFile(); 
     FileOutputStream out = new FileOutputStream(path); 

     out.write(pub_key.getEncoded()); // Write public key to the file 
     out.close(); 

     // Read from file 
     FileInputStream in = new FileInputStream(path); 
     byte[] pub_key_arr = new byte[in.available()]; 
     in.read(pub_key_arr, 0, in.available()); 
     in.close(); 

     // Reconstruct public key 
     PublicKey reconstructed_pub_key = reconstruct_public_key("RSA", pub_key_arr); 
    } catch(IOException e) { 
     System.out.println("Could not open the file : " + e.getStackTrace()); 
    } 
} 

और यह generate_key प्रक्रिया है:

public KeyPair generate_key() { 
    while(true) { // Else the compiler will complain that this procedure does not always return a "KeyPair" 
     try { 
      final KeyPairGenerator key_generator = KeyPairGenerator.getInstance("RSA"); 
      key_generator.initialize(2048); // Keys of 2048 bits (minimum key length for RSA keys) are safe enough (according to the slides 128bit keys > 16 years to brute force it) 

      final KeyPair keys = key_generator.generateKeyPair(); 
      return keys; 
     } catch(NoSuchAlgorithmException e) { 
      System.out.println("The given encryption algorithm (RSA) does not exist. -- generate_key() - Cryptography."); 
     } 
    } 
} 

आप इस परीक्षण, तो आप उस publicKey सफलतापूर्वक फिर से बनाया गया देखेंगे।

संपादित करें: मैंने ssh-keygen उपकरण का उपयोग करके इसे स्वयं करने का प्रयास किया। यह मैं क्या किया है:

  • सबसे पहले मैं एक RSA निजी कुंजी (.PEM प्रारूप)
  • .DER प्रारूप करने के लिए सार्वजनिक कुंजी भाग outputted उत्पन्न तो यह जावा के द्वारा प्रयोग किया जा सकता है।

    openssl rsa -in private_key_file.pem -pubout -outform DER -out java_readable_file.der 
    

    और मैं जो तुम्हारा बहुत अलग नहीं है फ़ाइल here की तरह पढ़ना, क्या किया:

यह कैसे मैं रूपांतरण है, जो तुम्हारा का एक सा अलग है किया है। मैंने इसका परीक्षण किया और जावा ने सफलतापूर्वक सार्वजनिक कुंजी का पुनर्निर्माण किया।

+0

ठीक है, की तुलना में मैं हमेशा मिलता है "सार्वजनिक कुंजी को फिर से संगठित नहीं किया जा सका" - लेकिन मैं अभी भी नहीं जानता कि क्यों सार्वजनिक कुंजी का पुनर्निर्माण नहीं किया जा सकता, ... हो सकता है कि कुछ conversion- दौरान गलत हो गया प्रक्रिया, लेकिन क्या? टर्मिनल में मैन्युअल रूपांतरण के बिना सीधे 'ssh-keygen'- जेनरेट की गई फ़ाइलों को पढ़ने का तरीका भी अच्छा होगा। – Edward

+0

@Edward मैंने आपके प्रश्न का उत्तर देने के लिए अपना उत्तर संपादित किया। – HyperZ

+0

मैं 'ssh-keygen'' (आमतौर पर '~/.ssh/id_rsa.pub' में) के साथ जेनरेट की गई मौजूदा कुंजी को पढ़ने का प्रयास करता हूं। वे 'पीईएम' प्रारूप में प्रतीत होते हैं। मैं '~/.ssh/id_rsa' से निजी कुंजी को पढ़ने में कामयाब रहा, लेकिन सार्वजनिक कुंजी पढ़ना काम नहीं करता है। यह वास्तव में 'ssh-keygen' से उत्पन्न फ़ाइलों के साथ एक समस्या प्रतीत होता है (उम्मीद है कि अब यह स्पष्ट है)। [आपके उदाहरण के लिए +1] – Edward

4

आरएसए निजी कुंजी

openssl genrsa -out rsaprivkey.pem 1024

बनाना डीईआर प्रारूप में सार्वजनिक कुंजी उत्पन्न करता है।

openssl rsa -in rsaprivkey.pem -pubout -outform DER -out rsapubkey.der

हम इस कोड X.509 प्रमाणपत्र से सार्वजनिक कुंजी RSA या DSA अर्क का उपयोग करें।

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.PublicKey; 
import java.security.cert.CertificateException; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.X509EncodedKeySpec; 

/** 
* This class is capable of extracting a public key from a X.509 certficate 
* and returning the PublicKey representation from a referenced byte array. 
* 
*/ 
public class ExtractPublicKey { 

    // Certificate Filename (Including Path Info) 
    private static final String certFilename = "cacert.pem"; 

    // Public Key Filename (Including Path Info) 
    private static final String pubKeyFilename = "rsapublic.key"; 

    public static PublicKey generatePublicKey(byte[] encodedKey) 
     throws NoSuchAlgorithmException, InvalidKeySpecException { 

    X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(encodedKey); 
    boolean isSupportedKey = false; 
    KeyFactory factory; 
    PublicKey retKey = null; 

    //first try the DSA alg 
    try { 
     factory = KeyFactory.getInstance("DSA"); 
     retKey = factory.generatePublic(pubSpec); 
     isSupportedKey = true; 
    } catch (InvalidKeySpecException e) { 
     System.out.println("Could not create DSA Public Key: " + e.toString());  
    } 

    //if DSA didnt work, then try RSA  
    if (!isSupportedKey) { 
     try { 
     factory = KeyFactory.getInstance("RSA"); 
     retKey = factory.generatePublic(pubSpec); 
     isSupportedKey = true; 
     } catch (InvalidKeySpecException e) { 
     System.out.println("Could not create RSA Public Key: " + e.toString()); 
     }  
    } 

    // if not DSA or RSA 
    if (!isSupportedKey) { 
     throw new InvalidKeySpecException("Unsupported key spec: Not RSA or DSA"); 
    } 

    return retKey; 
    } 

} 
+0

हम Google ऐप्स के लिए एसएसओ प्रदान करते हैं और x509 से सार्वजनिक कुंजी निकालने के लिए हम उपरोक्त कोड का उपयोग करते हैं। और इसका जावा कोड Google ऐप विशिष्ट कोड नहीं है, यह हमारे अन्य प्रोजेक्ट में भी ठीक काम करता है। यदि आप अधिक जानकारी चाहते हैं कि कैसे निकालें या कुंजी कैसे उत्पन्न करें इस लिंक को जांचें। https://developers.google.com/google-apps/help/articles/sso-keygen#creating-rsa-key-pairs –