2012-07-10 4 views
72

Mam wygenerowany klucz prywatny z:obciążenia RSA klucz publiczny z pliku

openssl genrsa [-out file] –des3 

Po tym mam wygenerowany klucz publiczny z:

openssl rsa –pubout -in private.key [-out file] 

Chcę podpisać jakieś wiadomości z mój klucz prywatny i sprawdź inne wiadomości za pomocą mojego klucza publicznego, używając następującego kodu:

public String sign(String message) throws SignatureException{ 
    try { 
     Signature sign = Signature.getInstance("SHA1withRSA"); 
     sign.initSign(privateKey); 
     sign.update(message.getBytes("UTF-8")); 
     return new String(Base64.encodeBase64(sign.sign()),"UTF-8"); 
    } catch (Exception ex) { 
     throw new SignatureException(ex); 
    } 
} 

public boolean verify(String message, String signature) throws SignatureException{ 
    try { 
     Signature sign = Signature.getInstance("SHA1withRSA"); 
     sign.initVerify(publicKey); 
     sign.update(message.getBytes("UTF-8")); 
     return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); 
    } catch (Exception ex) { 
     throw new SignatureException(ex); 
    } 
} 

Znalazłem rozwiązanie, aby przekonwertować moje prywatne klucz do formatu PKCS8 i załaduj go. Działa on z jakiegoś kodu:

public PrivateKey getPrivateKey(String filename) throws Exception { 

    File f = new File(filename); 
    FileInputStream fis = new FileInputStream(f); 
    DataInputStream dis = new DataInputStream(fis); 
    byte[] keyBytes = new byte[(int) f.length()]; 
    dis.readFully(keyBytes); 
    dis.close(); 
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); 
    KeyFactory kf = 
      KeyFactory.getInstance("RSA"); 
    return kf.generatePrivate(spec); 
} 

i wreszcie moje pytanie brzmi: Jak mogę załadować mój klucz publiczny RSA z pliku?

Myślę, że może muszę przekonwertować plik klucza publicznego na format x509 i użyć X509EncodedKeySpec. Ale jak mogę to zrobić?

+10

Zobacz http://codeartisan.blogspot.com/2009/05/public-key-cryptography-in-java.html – Zaki

+0

Oh dziękuję bardzo! To rozwiązanie działa! –

Odpowiedz

209

Poniżej przedstawiono istotne informacje z the link, które podano pod następującym numerem: zaki.

wygenerować klucz 2048-bitowy RSA prywatny

$ openssl genrsa -out private_key.pem 2048

Konwersja klucza prywatnego w formacie PKCS # 8 (tak Java może go odczytać)

$ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt

Wyjście klucza publicznego część w formacie DER (aby Java mogła ją odczytać)

$ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der

Klucz prywatny

import java.io.*; 
import java.nio.*; 
import java.security.*; 
import java.security.spec.*; 

public class PrivateKeyReader { 

    public static PrivateKey get(String filename) 
    throws Exception { 

    byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); 

    PKCS8EncodedKeySpec spec = 
     new PKCS8EncodedKeySpec(keyBytes); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    return kf.generatePrivate(spec); 
    } 
} 

klucz

Public
import java.io.*; 
import java.nio.*; 
import java.security.*; 
import java.security.spec.*; 

public class PublicKeyReader { 

    public static PublicKey get(String filename) 
    throws Exception { 

    byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); 

    X509EncodedKeySpec spec = 
     new X509EncodedKeySpec(keyBytes); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    return kf.generatePublic(spec); 
    } 
} 
+4

Dzięki! Zrobiłeś mój dzień, zrobiłbym ci więcej niż 1, gdybym mógł :) –

+0

wielkie dzięki, na przykład! – giozh

+14

Mam wyjątek InvalidKeyException: nieprawidłowy format klucza, jakiś pomysł? Dzięki! – Zennichimaro

16

Ten program robi prawie wszystko z kluczy publicznych i prywatnych. Format der można uzyskać, ale zapisujemy dane surowe (bez kodowania base64). Mam nadzieję, że to pomoże programistom.

import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.PrintStream; 
import java.security.InvalidKeyException; 
import java.security.KeyFactory; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.NoSuchAlgorithmException; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.Signature; 
import java.security.SignatureException; 

import sun.misc.BASE64Decoder; 
import sun.misc.BASE64Encoder; 
import sun.security.pkcs.PKCS8Key; 
import sun.security.pkcs10.PKCS10; 
import sun.security.x509.X500Name; 

import java.security.spec.PKCS8EncodedKeySpec; 
import java.security.spec.X509EncodedKeySpec; 



/** 
* @author Desphilboy 
* DorOd bar shomA barobach 
* 
*/ 
public class csrgenerator { 

    private static PublicKey publickey= null; 
    private static PrivateKey privateKey=null; 
    //private static PKCS8Key privateKey=null; 
    private static KeyPairGenerator kpg= null; 
    private static ByteArrayOutputStream bs =null; 
    private static csrgenerator thisinstance; 
    private KeyPair keypair; 
    private static PKCS10 pkcs10; 
    private String signaturealgorithm= "MD5WithRSA"; 

    public String getSignaturealgorithm() { 
     return signaturealgorithm; 
    } 



    public void setSignaturealgorithm(String signaturealgorithm) { 
     this.signaturealgorithm = signaturealgorithm; 
    } 



    private csrgenerator() { 
     try { 
      kpg = KeyPairGenerator.getInstance("RSA"); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
      System.out.print("No such algorithm RSA in constructor csrgenerator\n"); 
     } 
     kpg.initialize(2048); 
     keypair = kpg.generateKeyPair(); 
     publickey = keypair.getPublic(); 
     privateKey = keypair.getPrivate(); 
    } 



    /** Generates a new key pair 
    * 
    * @param int bits 
    * this is the number of bits in modulus must be 512, 1024, 2048 or so on 
    */ 
    public KeyPair generateRSAkys(int bits) 
    { 
      kpg.initialize(bits); 
      keypair = kpg.generateKeyPair(); 
      publickey = keypair.getPublic(); 
      privateKey = keypair.getPrivate(); 
      KeyPair dup= keypair; 
    return dup; 
    } 

    public static csrgenerator getInstance() { 
      if (thisinstance == null) 
       thisinstance = new csrgenerator(); 
      return thisinstance; 
     } 


    /** 
     * Returns a CSR as string 
     * @param cn Common Name 
     * @param OU Organizational Unit 
     * @param Org Organization 
     * @param LocName Location name 
     * @param Statename State/Territory/Province/Region 
     * @param Country Country 
     * @return  returns csr as string. 
     * @throws Exception 
     */ 
    public String getCSR(String commonname, String organizationunit, String organization,String localname, String statename, String country) throws Exception { 
      byte[] csr = generatePKCS10(commonname, organizationunit, organization, localname, statename, country,signaturealgorithm); 
      return new String(csr); 
     } 

    /** This function generates a new Certificate 
     * Signing Request. 
    * 
    * @param CN 
    *   Common Name, is X.509 speak for the name that distinguishes 
    *   the Certificate best, and ties it to your Organization 
    * @param OU 
    *   Organizational unit 
    * @param O 
    *   Organization NAME 
    * @param L 
    *   Location 
    * @param S 
    *   State 
    * @param C 
    *   Country 
    * @return byte stream of generated request 
    * @throws Exception 
    */ 
    private static byte[] generatePKCS10(String CN, String OU, String O,String L, String S, String C,String sigAlg) throws Exception { 
     // generate PKCS10 certificate request 

     pkcs10 = new PKCS10(publickey); 
     Signature signature = Signature.getInstance(sigAlg); 
     signature.initSign(privateKey); 
     // common, orgUnit, org, locality, state, country 
     //X500Name(String commonName, String organizationUnit,String organizationName,Local,State, String country) 
     X500Name x500Name = new X500Name(CN, OU, O, L, S, C); 
     pkcs10.encodeAndSign(x500Name,signature); 
     bs = new ByteArrayOutputStream(); 
     PrintStream ps = new PrintStream(bs); 
     pkcs10.print(ps); 
     byte[] c = bs.toByteArray(); 
     try { 
      if (ps != null) 
       ps.close(); 
      if (bs != null) 
       bs.close(); 
     } catch (Throwable th) { 
     } 
     return c; 
    } 

    public PublicKey getPublicKey() { 
     return publickey; 
    } 




    /** 
    * @return 
    */ 
    public PrivateKey getPrivateKey() { 
     return privateKey; 
    } 

    /** 
    * saves private key to a file 
    * @param filename 
    */ 
    public void SavePrivateKey(String filename) 
    { 
     PKCS8EncodedKeySpec pemcontents=null; 
     pemcontents= new PKCS8EncodedKeySpec(privateKey.getEncoded()); 
     PKCS8Key pemprivatekey= new PKCS8Key(); 
     try { 
      pemprivatekey.decode(pemcontents.getEncoded()); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     File file=new File(filename); 
     try { 

      file.createNewFile(); 
      FileOutputStream fos=new FileOutputStream(file); 
      fos.write(pemprivatekey.getEncoded()); 
      fos.flush(); 
      fos.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 



    } 



    /** 
    * Saves Certificate Signing Request to a file; 
    * @param filename is a String containing full path to the file which will be created containing the CSR. 
    */ 
    public void SaveCSR(String filename) 
    { 
     FileOutputStream fos=null; 
     PrintStream ps=null; 
     File file; 
     try { 

      file = new File(filename); 
      file.createNewFile(); 
      fos = new FileOutputStream(file); 
      ps= new PrintStream(fos); 
     }catch (IOException e) 
     { 
      System.out.print("\n could not open the file "+ filename); 
     } 

     try { 
      try { 
       pkcs10.print(ps); 
      } catch (SignatureException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      ps.flush(); 
      ps.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      System.out.print("\n cannot write to the file "+ filename); 
      e.printStackTrace(); 

     } 

     } 


    /** 
    * Saves both public key and private key to file names specified 
    * @param fnpub file name of public key 
    * @param fnpri file name of private key 
    * @throws IOException 
    */ 
    public static void SaveKeyPair(String fnpub,String fnpri) throws IOException { 

// Store Public Key. 
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publickey.getEncoded()); 
FileOutputStream fos = new FileOutputStream(fnpub); 
fos.write(x509EncodedKeySpec.getEncoded()); 
fos.close(); 

// Store Private Key. 
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded()); 
fos = new FileOutputStream(fnpri); 
fos.write(pkcs8EncodedKeySpec.getEncoded()); 
fos.close(); 
} 


    /** 
    * Reads a Private Key from a pem base64 encoded file. 
    * @param filename name of the file to read. 
    * @param algorithm Algorithm is usually "RSA" 
    * @return returns the privatekey which is read from the file; 
    * @throws Exception 
    */ 
    public PrivateKey getPemPrivateKey(String filename, String algorithm) throws Exception { 
      File f = new File(filename); 
      FileInputStream fis = new FileInputStream(f); 
      DataInputStream dis = new DataInputStream(fis); 
      byte[] keyBytes = new byte[(int) f.length()]; 
      dis.readFully(keyBytes); 
      dis.close(); 

      String temp = new String(keyBytes); 
      String privKeyPEM = temp.replace("-----BEGIN PRIVATE KEY-----", ""); 
      privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", ""); 
      //System.out.println("Private key\n"+privKeyPEM); 

      BASE64Decoder b64=new BASE64Decoder(); 
      byte[] decoded = b64.decodeBuffer(privKeyPEM); 

      PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded); 
      KeyFactory kf = KeyFactory.getInstance(algorithm); 
      return kf.generatePrivate(spec); 
      } 



    /** 
    * Saves the private key to a pem file. 
    * @param filename name of the file to write the key into 
    * @param key the Private key to save. 
    * @return String representation of the pkcs8 object. 
    * @throws Exception 
    */ 
    public String SavePemPrivateKey(String filename) throws Exception { 
     PrivateKey key=this.privateKey; 
      File f = new File(filename); 
      FileOutputStream fos = new FileOutputStream(f); 
      DataOutputStream dos = new DataOutputStream(fos); 


      byte[] keyBytes = key.getEncoded(); 
      PKCS8Key pkcs8= new PKCS8Key(); 
      pkcs8.decode(keyBytes); 
      byte[] b=pkcs8.encode(); 

      BASE64Encoder b64=new BASE64Encoder(); 
      String encoded = b64.encodeBuffer(b); 

      encoded= "-----BEGIN PRIVATE KEY-----\r\n" + encoded + "-----END PRIVATE KEY-----"; 

     dos.writeBytes(encoded); 
     dos.flush(); 
     dos.close(); 

      //System.out.println("Private key\n"+privKeyPEM); 
     return pkcs8.toString(); 

      } 


    /** 
    * Saves a public key to a base64 encoded pem file 
    * @param filename name of the file 
    * @param key public key to be saved 
    * @return string representation of the pkcs8 object. 
    * @throws Exception 
    */ 
    public String SavePemPublicKey(String filename) throws Exception { 
     PublicKey key=this.publickey; 
     File f = new File(filename); 
      FileOutputStream fos = new FileOutputStream(f); 
      DataOutputStream dos = new DataOutputStream(fos); 


      byte[] keyBytes = key.getEncoded(); 
      BASE64Encoder b64=new BASE64Encoder(); 
      String encoded = b64.encodeBuffer(keyBytes); 

      encoded= "-----BEGIN PUBLIC KEY-----\r\n" + encoded + "-----END PUBLIC KEY-----"; 

     dos.writeBytes(encoded); 
     dos.flush(); 
     dos.close(); 

      //System.out.println("Private key\n"+privKeyPEM); 
     return encoded.toString(); 

      } 





     /** 
    * reads a public key from a file 
    * @param filename name of the file to read 
    * @param algorithm is usually RSA 
    * @return the read public key 
    * @throws Exception 
    */ 
    public PublicKey getPemPublicKey(String filename, String algorithm) throws Exception { 
      File f = new File(filename); 
      FileInputStream fis = new FileInputStream(f); 
      DataInputStream dis = new DataInputStream(fis); 
      byte[] keyBytes = new byte[(int) f.length()]; 
      dis.readFully(keyBytes); 
      dis.close(); 

      String temp = new String(keyBytes); 
      String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----\n", ""); 
      publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", ""); 


      BASE64Decoder b64=new BASE64Decoder(); 
      byte[] decoded = b64.decodeBuffer(publicKeyPEM); 

      X509EncodedKeySpec spec = 
       new X509EncodedKeySpec(decoded); 
      KeyFactory kf = KeyFactory.getInstance(algorithm); 
      return kf.generatePublic(spec); 
      } 




    public static void main(String[] args) throws Exception { 
     csrgenerator gcsr = csrgenerator.getInstance(); 
     gcsr.setSignaturealgorithm("SHA512WithRSA"); 
     System.out.println("Public Key:\n"+gcsr.getPublicKey().toString()); 

     System.out.println("Private Key:\nAlgorithm: "+gcsr.getPrivateKey().getAlgorithm().toString()); 
     System.out.println("Format:"+gcsr.getPrivateKey().getFormat().toString()); 
     System.out.println("To String :"+gcsr.getPrivateKey().toString()); 
     System.out.println("GetEncoded :"+gcsr.getPrivateKey().getEncoded().toString()); 
     BASE64Encoder encoder= new BASE64Encoder(); 
     String s=encoder.encodeBuffer(gcsr.getPrivateKey().getEncoded()); 
     System.out.println("Base64:"+s+"\n"); 

     String csr = gcsr.getCSR("[email protected]","baxshi az xodam", "Xodam","PointCook","VIC" ,"AU"); 
     System.out.println("CSR Request Generated!!"); 
     System.out.println(csr); 
     gcsr.SaveCSR("c:\\testdir\\javacsr.csr"); 
     String p=gcsr.SavePemPrivateKey("c:\\testdir\\java_private.pem"); 
     System.out.print(p); 
     p=gcsr.SavePemPublicKey("c:\\testdir\\java_public.pem"); 
     privateKey= gcsr.getPemPrivateKey("c:\\testdir\\java_private.pem", "RSA"); 
     BASE64Encoder encoder1= new BASE64Encoder(); 
     String s1=encoder1.encodeBuffer(gcsr.getPrivateKey().getEncoded()); 
     System.out.println("Private Key in Base64:"+s1+"\n"); 
     System.out.print(p); 


    } 

    } 
+0

To bardzo pomocne, dzięki! –

4

Po klucz przechowywany w pliku PEM, można go odczytać z powrotem łatwo za pomocą PemObject i PemReader klas przedstawionych przez BouncyCastle, jak pokazano w tym this tutorial.

Utwórz klasę PemFile która zamyka obsługę plików:

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 

import org.bouncycastle.util.io.pem.PemObject; 
import org.bouncycastle.util.io.pem.PemReader; 

public class PemFile { 

    private PemObject pemObject; 

    public PemFile(String filename) throws FileNotFoundException, IOException { 
     PemReader pemReader = new PemReader(new InputStreamReader(
       new FileInputStream(filename))); 
     try { 
      this.pemObject = pemReader.readPemObject(); 
     } finally { 
      pemReader.close(); 
     } 
    } 

    public PemObject getPemObject() { 
     return pemObject; 
    } 
} 

Następnie instancję klucze prywatne i publiczne, jak zwykle:

import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.Security; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.PKCS8EncodedKeySpec; 
import java.security.spec.X509EncodedKeySpec; 

import org.apache.log4j.Logger; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 

public class Main { 

    protected final static Logger LOGGER = Logger.getLogger(Main.class); 

    public final static String RESOURCES_DIR = "src/main/resources/rsa-sample/"; 

    public static void main(String[] args) throws FileNotFoundException, 
      IOException, NoSuchAlgorithmException, NoSuchProviderException { 
     Security.addProvider(new BouncyCastleProvider()); 
     LOGGER.info("BouncyCastle provider added."); 

     KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); 
     try { 
      PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR 
        + "id_rsa"); 
      LOGGER.info(String.format("Instantiated private key: %s", priv)); 

      PublicKey pub = generatePublicKey(factory, RESOURCES_DIR 
        + "id_rsa.pub"); 
      LOGGER.info(String.format("Instantiated public key: %s", pub)); 
     } catch (InvalidKeySpecException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static PrivateKey generatePrivateKey(KeyFactory factory, 
      String filename) throws InvalidKeySpecException, 
      FileNotFoundException, IOException { 
     PemFile pemFile = new PemFile(filename); 
     byte[] content = pemFile.getPemObject().getContent(); 
     PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content); 
     return factory.generatePrivate(privKeySpec); 
    } 

    private static PublicKey generatePublicKey(KeyFactory factory, 
      String filename) throws InvalidKeySpecException, 
      FileNotFoundException, IOException { 
     PemFile pemFile = new PemFile(filename); 
     byte[] content = pemFile.getPemObject().getContent(); 
     X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content); 
     return factory.generatePublic(pubKeySpec); 
    } 
} 

nadzieję, że to pomaga.

+0

Wygląda na to, że kod ma zależność od BouncyCastle. – jww

+0

@jww Tak. Pierwszy akapit tego wpisu zawiera następujące stwierdzenie: _możesz go łatwo odczytać za pomocą klas PemObject i PemReader dostarczonych przez * BouncyCastle * _ – Cheeso

+0

W jaki sposób używałbyś strumienia wejściowego do pliku przy użyciu tego klucza prywatnego? – 2Big2BeSmall

1

Poniższy kod działa absolutnie dobrze dla mnie i działa. Ten kod odczytuje prywatny i publiczny klucz RSA za pomocą kodu java. Można odwołać się do http://snipplr.com/view/18368/

import java.io.DataInputStream; 
    import java.io.File; 
    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.security.KeyFactory; 
    import java.security.NoSuchAlgorithmException; 
    import java.security.interfaces.RSAPrivateKey; 
    import java.security.interfaces.RSAPublicKey; 
    import java.security.spec.InvalidKeySpecException; 
    import java.security.spec.PKCS8EncodedKeySpec; 
    import java.security.spec.X509EncodedKeySpec; 

    public class Demo { 

     public static final String PRIVATE_KEY="/home/user/private.der"; 
     public static final String PUBLIC_KEY="/home/user/public.der"; 

     public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { 
      //get the private key 
      File file = new File(PRIVATE_KEY); 
      FileInputStream fis = new FileInputStream(file); 
      DataInputStream dis = new DataInputStream(fis); 

      byte[] keyBytes = new byte[(int) file.length()]; 
      dis.readFully(keyBytes); 
      dis.close(); 

      PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); 
      KeyFactory kf = KeyFactory.getInstance("RSA"); 
      RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(spec); 
      System.out.println("Exponent :" + privKey.getPrivateExponent()); 
      System.out.println("Modulus" + privKey.getModulus()); 

      //get the public key 
      File file1 = new File(PUBLIC_KEY); 
      FileInputStream fis1 = new FileInputStream(file1); 
      DataInputStream dis1 = new DataInputStream(fis1); 
      byte[] keyBytes1 = new byte[(int) file1.length()]; 
      dis1.readFully(keyBytes1); 
      dis1.close(); 

      X509EncodedKeySpec spec1 = new X509EncodedKeySpec(keyBytes1); 
      KeyFactory kf1 = KeyFactory.getInstance("RSA"); 
      RSAPublicKey pubKey = (RSAPublicKey) kf1.generatePublic(spec1); 

      System.out.println("Exponent :" + pubKey.getPublicExponent()); 
      System.out.println("Modulus" + pubKey.getModulus()); 
     } 
    }