Java类中RSA加密的问题

public class MyEncrypt { public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException { ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName))); try { oout.writeObject(mod); oout.writeObject(exp); } catch (Exception e) { throw new IOException("Unexpected error", e); } finally { oout.close(); } } public static void main(String[] args) throws Exception { MyEncrypt myEncrypt = new MyEncrypt(); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(128); KeyPair kp = kpg.genKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate(); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class); myEncrypt.saveToFile("public.key", pub.getModulus(), pub.getPublicExponent()); myEncrypt.saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent()); String encString = myEncrypt.bytes2String(myEncrypt.rsaEncrypt("pritesh".getBytes())); System.out.println("encrypted : " + encString); String decString = myEncrypt.bytes2String(myEncrypt.rsaDecrypt(encString.getBytes())); System.out.println("decrypted : " + decString); } PublicKey readKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PublicKey pubKey = fact.generatePublic(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PrivateKey pubKey = fact.generatePrivate(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } public byte[] rsaEncrypt(byte[] data) throws Exception { byte[] src = new byte[] { (byte) 0xbe, (byte) 0xef }; PublicKey pubKey = this.readKeyFromFile("public.key"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] cipherData = cipher.doFinal(data); return cipherData; } public byte[] rsaDecrypt(byte[] data) throws Exception { byte[] src = new byte[] { (byte) 0xbe, (byte) 0xef }; PrivateKey pubKey = this.readPrivateKeyFromFile("private.key"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, pubKey); byte[] cipherData = cipher.doFinal(data); return cipherData; } private String bytes2String(byte[] bytes) { StringBuilder string = new StringBuilder(); for (byte b: bytes) { String hexString = Integer.toHexString(0x00FF & b); string.append(hexString.length() == 1 ? "0" + hexString : hexString); } return string.toString(); } } 

我收到此错误:

 Exception in thread "main" java.security.InvalidParameterException: RSA keys must be at least 512 bits long at sun.security.rsa.RSAKeyPairGenerator.initialize(RSAKeyPairGenerator.java:70) at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:631) at java.security.KeyPairGenerator.initialize(KeyPairGenerator.java:340) at MyEncrypt.main(MyEncrypt.java:42) 

我从http://www.javamex.com/tutorials/cryptography/rsa_encryption_2.shtml示例中创建了这个类。


公共课MyEncrypt {

 static final String HEXES = "0123456789ABCDEF"; byte[] buf = new byte[1024]; public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException { ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName))); try { oout.writeObject(mod); oout.writeObject(exp); } catch (Exception e) { throw new IOException("Unexpected error", e); } finally { oout.close(); } } public static void main(String[] args) throws Exception { MyEncrypt myEncrypt = new MyEncrypt(); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); KeyPair kp = kpg.genKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate(); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class); myEncrypt.saveToFile("public.key", pub.getModulus(), pub.getPublicExponent()); myEncrypt.saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent()); String encString = myEncrypt.rsaEncrypt("pritesh"); System.out.println("encrypted : " + encString); String decString = myEncrypt.rsaDecrypt(encString); System.out.println("decrypted : " + decString); String main_file_path = "resume.doc"; String main_encrypt_file_path = "encrypt.doc"; String main_decrypt_file_path = "decrypt.doc"; myEncrypt.rsaEncrypt(new FileInputStream(main_file_path),new FileOutputStream(main_encrypt_file_path)); // Decrypt myEncrypt.rsaDecrypt(new FileInputStream(main_encrypt_file_path),new FileOutputStream(main_decrypt_file_path)); } PublicKey readKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PublicKey pubKey = fact.generatePublic(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PrivateKey pubKey = fact.generatePrivate(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } public String rsaEncrypt(String plaintext) throws Exception { PublicKey pubKey = this.readKeyFromFile("public.key"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8")); return this.byteToHex(ciphertext); } public void rsaEncrypt(InputStream in, OutputStream out) throws Exception { try { PublicKey pubKey = this.readKeyFromFile("public.key"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); // Bytes written to out will be encrypted out = new CipherOutputStream(out, cipher); // Read in the cleartext bytes and write to out to encrypt int numRead = 0; while ((numRead = in.read(buf)) >= 0){ out.write(buf, 0, numRead); } out.close(); } catch (java.io.IOException e){ e.printStackTrace(); } } public void rsaDecrypt(InputStream in, OutputStream out) throws Exception { try { PrivateKey pubKey = this.readPrivateKeyFromFile("private.key"); Cipher dcipher = Cipher.getInstance("RSA"); dcipher.init(Cipher.DECRYPT_MODE, pubKey); // Bytes read from in will be decrypted in = new CipherInputStream(in, dcipher); // Read in the decrypted bytes and write the cleartext to out int numRead = 0; while ((numRead = in.read(buf)) >= 0) { out.write(buf, 0, numRead); } out.close(); } catch (java.io.IOException e) { e.printStackTrace(); } } public String rsaDecrypt(String hexCipherText) throws Exception { PrivateKey pubKey = this.readPrivateKeyFromFile("private.key"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, pubKey); String plaintext = new String(cipher.doFinal(this.hexToByte(hexCipherText)), "UTF-8"); return plaintext; } public static String byteToHex( byte [] raw ) { if ( raw == null ) { return null; } final StringBuilder hex = new StringBuilder( 2 * raw.length ); for ( final byte b : raw ) { hex.append(HEXES.charAt((b & 0xF0) >> 4)) .append(HEXES.charAt((b & 0x0F))); } return hex.toString(); } public static byte[] hexToByte( String hexString){ int len = hexString.length(); byte[] ba = new byte[len / 2]; for (int i = 0; i < len; i += 2) { ba[i/2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16)); } return ba; } 

}

它适用于文本文件,但在docx和video等文件上出现问题?

错误说明了一切:您使用128的密钥集进行初始化,RSA期望至少为512。

您有多个问题:

  1. Java不支持大小小于512的RSA密钥.2048位是更好的选择。 所以改变密钥长度:

     kpg.initialize(2048); 
  2. String.getBytes()不是bytes2String()的逆操作。 加密后,将字节转换为hex字符串。 但是在解密之前将这个hex字符串转换为ASCII表示forms,这会产生一个太长的字节数组。 相反,使用这样的东西来转换hex字符串:

     private byte[] string2bytes(String s) { int len = s.length(); byte[] res = new byte[len / 2]; for (int i = 0; i < len; i += 2) { res[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return res; } 

    然后调用它而不是String.getBytes():

     // Note, this line is not completely fixed yet String decString = myEncrypt.bytes2String( myEncrypt.rsaDecrypt( myEncrypt.string2bytes(encString) ) ); 
  3. 最后你有相反的问题。 您的bytes2String()方法不会反转String.getBytes()操作。 你加密了“pritesh”.getBytes()的输出,这就是你从解密操作中获得的。 现在你必须将它转换回String。 String(byte []) - 构造函数将为您执行此操作:

     String decString = new String( myEncrypt.rsaDecrypt( myEncrypt.string2bytes(encString) ) ); 

最后的答案

public class MyEncrypt {

 public static final int AES_Key_Size = 128; Cipher pkCipher, aesCipher; byte[] aesKey; SecretKeySpec aeskeySpec; public static void main(String[] args) throws Exception { //MyEncrypt.createRSAKeys(); //call to generated RSA keys MyEncrypt secure = new MyEncrypt(); // to encrypt a file secure.makeKey(); secure.saveKey(new File("keys/ase.key"), "keys/public.key"); secure.encrypt(new File("test/sample.pdf"), new File("test/encrypt_sample.pdf")); // to decrypt it again secure.loadKey(new File("keys/ase.key"), "keys/private.key"); secure.decrypt(new File("test/encrypt_sample.pdf"), new File("test/decrypted_sample.pdf")); } /** * Constructor: creates ciphers */ public MyEncrypt() throws GeneralSecurityException { // create RSA public key cipher pkCipher = Cipher.getInstance("RSA"); // create AES shared key cipher aesCipher = Cipher.getInstance("AES"); } public static void createRSAKeys() throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(512); KeyPair kp = kpg.genKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate(); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class); saveToFile("keys/public.key", pub.getModulus(), pub.getPublicExponent()); saveToFile("keys/private.key", priv.getModulus(), priv.getPrivateExponent()); System.out.println("RSA public & private keys are generated"); } private static void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException { ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName))); try { oout.writeObject(mod); oout.writeObject(exp); } catch (Exception e) { throw new IOException("Unexpected error", e); } finally { oout.close(); } } /** * Creates a new AES key */ public void makeKey() throws NoSuchAlgorithmException { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(AES_Key_Size); SecretKey key = kgen.generateKey(); aesKey = key.getEncoded(); aeskeySpec = new SecretKeySpec(aesKey, "AES"); } /** * Encrypts the AES key to a file using an RSA public key */ public void saveKey(File out, String publicKeyFile) throws IOException, GeneralSecurityException { try { // read public key to be used to encrypt the AES key byte[] encodedKey = new byte[(int)publicKeyFile.length()]; new FileInputStream(publicKeyFile).read(encodedKey); // create public key //X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey); //KeyFactory kf = KeyFactory.getInstance("RSA"); //PublicKey pk = kf.generatePublic(publicKeySpec); PublicKey pk = this.readPublicKeyFromFile(publicKeyFile); // write AES key pkCipher.init(Cipher.ENCRYPT_MODE, pk); CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), pkCipher); os.write(aesKey); os.close(); } catch (Exception e) { //throw new Exception("Saving key exception", e); } } private PublicKey readPublicKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PublicKey pubKey = fact.generatePublic(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } private PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception { InputStream in = new FileInputStream(keyFileName); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PrivateKey pubKey = fact.generatePrivate(keySpec); return pubKey; } catch (Exception e) { throw new RuntimeException("Spurious serialisation error", e); } finally { oin.close(); } } /** * Decrypts an AES key from a file using an RSA private key */ public void loadKey(File in, String privateKeyFile) throws GeneralSecurityException, IOException { try { // read private key to be used to decrypt the AES key byte[] encodedKey = new byte[(int)privateKeyFile.length()]; new FileInputStream(privateKeyFile).read(encodedKey); // create private key //PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey); //KeyFactory kf = KeyFactory.getInstance("RSA"); //PrivateKey pk = kf.generatePrivate(privateKeySpec); PrivateKey pk = this.readPrivateKeyFromFile(privateKeyFile); // read AES key pkCipher.init(Cipher.DECRYPT_MODE, pk); aesKey = new byte[AES_Key_Size/8]; CipherInputStream is = new CipherInputStream(new FileInputStream(in), pkCipher); is.read(aesKey); aeskeySpec = new SecretKeySpec(aesKey, "AES"); } catch (Exception e) { } } /** * Encrypts and then copies the contents of a given file. */ public void encrypt(File in, File out) throws IOException, InvalidKeyException { aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec); FileInputStream is = new FileInputStream(in); CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher); copy(is, os); os.close(); } /** * Decrypts and then copies the contents of a given file. */ public void decrypt(File in, File out) throws IOException, InvalidKeyException { aesCipher.init(Cipher.DECRYPT_MODE, aeskeySpec); CipherInputStream is = new CipherInputStream(new FileInputStream(in), aesCipher); FileOutputStream os = new FileOutputStream(out); copy(is, os); is.close(); os.close(); } /** * Copies a stream. */ private void copy(InputStream is, OutputStream os) throws IOException { int i; byte[] b = new byte[1024]; while((i=is.read(b))!=-1) { os.write(b, 0, i); } } 

}