studio spec rsapublickey programacion privatekey invalidkeyspecexception invalidkeyexception invalid from begin java openssl rsa

java - spec - rsapublickey from string



Cargar clave pública RSA desde el archivo (4)

He generado una clave privada con:

openssl genrsa [-out file] –des3

Después de esto, he generado una clave pública con:

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

Quiero firmar algunos mensajes con mi clave privada y verificar algunos otros mensajes con mi clave pública, usando un código como este:

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

Encontré una solución para convertir mi clave privada al formato PKCS8 y cargarla. Funciona con un código como este:

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

Y finalmente mi pregunta es: ¿cómo cargo mi clave pública RSA desde un archivo?

Creo que tal vez necesito convertir mi archivo de clave pública al formato x509 y usar X509EncodedKeySpec . ¿Pero cómo puedo hacer esto?


A continuación se muestra la información relevante del codeartisan.blogspot.com/2009/05/… que Zaki proporcionó.

Generar una clave privada RSA de 2048 bits

$ openssl genrsa -out private_key.pem 2048

Convertir clave privada al formato PKCS # 8 (para que Java pueda leerlo)

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

Parte de la clave pública de salida en formato DER (para que Java pueda leerlo)

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

Llave privada

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

Llave pública

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


El código siguiente funciona absolutamente bien para mí y funciona. Este código leerá claves privadas y públicas de RSA a través del código java. Puede consultar 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()); } }


Este programa está haciendo casi todo con claves públicas y privadas. Se puede obtener el formato der, pero guardando datos brutos (sin codificación base64). Espero que esto ayude a los programadores.

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


Una vez que tenga su clave almacenada en un archivo PEM, puede leerla fácilmente usando las clases PemObject y PemReader provistas por BouncyCastle, como se muestra en este tutorial .

Cree una clase PemFile que encapsule el manejo de archivos:

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

A continuación, crea las claves privadas y públicas de la forma habitual:

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

Espero que esto ayude.