2015-08-20 16 views
6

Ho un file contenente una chiave RSA pubblica (generata con ssh-keygen). Mi piacerebbe leggere il file e generare un oggetto PublicKey.Come generare l'oggetto PublicKey da un file in Java

Prima di questo ho convertito il file, dal momento che la lettura dei file originali sembra essere impossibile:

# 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 

Da Java - Encrypt String with existing public key file ho definito la funzione readFileBytes:

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

Ora mi piacerebbe leggere il file e generare l'oggetto PublicKey, ma non sono riuscito a trovare un modo per farlo; java.security.spec.RSAPublicKeySpec non fornisce un costruttore di montaggio e java.security.spec.X509EncodedKeySpec genera un errore 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" 

risposta

5

avevo un progetto in cui era necessario (RSA), la crittografia, questo è come ho ricostruito la publicKey dato byte serie s' il publicKey, che è stato appena letto dal file.

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; 
} 

allora si potrebbe chiamare la procedura simile a questa chiamata, reconstruct_public_key("RSA", readFileBytes("path/to/your/publicKey/file"));

EDIT: ho cercato di fare io stesso (scrivere la chiave pubblica in un file, leggere il file e ricostruire la chiave). Questo funziona:

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()); 
    } 
} 

E questa è la procedura 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."); 
     } 
    } 
} 

Se si prova questo, si vedrà che la publicKey viene ricostruito con successo.

EDIT: Ho provato a farlo da solo, utilizzando lo strumento ssh-keygen. Questo è quello che ho fatto:

  • Per prima cosa ho generato una chiave privata RSA (formato .PEM)
  • emesso la parte di chiave pubblica in formato .DER, in modo che possa essere utilizzata da Java.

Ecco come ho fatto la conversione, che è un po 'diverso di vostra:

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

E ho fatto la lettura del file come here, che non differisce molto del tuo. Ho provato questo e Java ha ricostruito con successo la chiave pubblica.

+0

Beh, che ho sempre trovato "Impossibile ricostruire la chiave pubblica" - ma ancora non so perché la chiave pubblica non può essere ricostruito, ... Forse qualcosa è andato storto durante la Conversion- processo, ma cosa? Sarebbe anche bello avere un modo per leggere direttamente i file 'ssh-keygen', senza la conversione manuale nel terminale. – Edward

+0

@Edward Ho modificato la mia risposta per rispondere alla tua domanda. – HyperZ

+0

Provo a leggere le chiavi esistenti che sono state generate con lo strumento 'ssh-keygen' (di solito in' ~/.ssh/id_rsa.pub'). Sembrano essere in formato 'PEM'. Sono riuscito a leggere la chiave privata da '~/.ssh/id_rsa', ma leggere la chiave pubblica non funziona. Sembra davvero essere un problema con i file generati con 'ssh-keygen' (speriamo sia ora chiaro). [+1 per il tuo esempio] – Edward

4

Creazione di RSA chiave privata

openssl genrsa -out rsaprivkey.pem 1024

genera la chiave pubblica in formato DER.

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

Usiamo questo codice estrae la chiave pubblica RSA o DSA dal certificato X.509.

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

Forniamo SSO per le app di Google e per l'estrazione della chiave pubblica da x509 utilizziamo il codice precedente. E 'un codice Java non un codice specifico per l'app di Google. Funziona anche bene con il nostro altro progetto. Se vuoi maggiori informazioni Come estrarre O Come generare la chiave Controlla questo link. https://developers.google.com/google-apps/help/articles/sso-keygen#creating-rsa-key-pairs –

Problemi correlati