2017-06-21 196 views
1

所以我认为我已经加密了我的密钥和字符串,但解密对我来说已成为问题。下面是我的代码:加密密钥和加密字符串的解密

package ReadFileExample; 


import java.io.BufferedOutputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.util.Base64; 
import javax.crypto.Cipher; 
import javax.crypto.KeyGenerator; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 

import java.security.KeyStore; 



public class generatekey { 


    static Cipher cipher; 
    public static void main(String[] args) throws Exception { 






    // generating a symmetric key using the AES algorithm 
    KeyGenerator generator = KeyGenerator.getInstance("AES"); 
    // 128 bit key 
    generator.init(256); 
    //generates a secret key 
    SecretKey secretkey = generator.generateKey(); 
    // returns an AES cipher 
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    //print key 
    System.out.println("Key: " + cipher); 








    String plainText = "Hello World"; 
    // call to method encrypt 
    String hexEncryptedByteText = encrypt(plainText, secretkey); 
    // print orignial text and encrypted text 
    System.out.println("Plain Text: " + plainText); 
    System.out.println("Encrypted Text: " + hexEncryptedByteText); 

    int plainTextlength = plainText.length(); 
    System.out.println("length of text: " + plainTextlength); 


    // allows to write data to a file 
    FileOutputStream fos = null; 
    // write bytes to file 
    BufferedOutputStream bos = null; 
    // create file to which data needs to be written 
    String fileName = "C:/Users/******/newFile.txt"; 

    try{ 
     // allows written data to go into the written path 
     fos = new FileOutputStream(fileName); 
     // converts written data into bytes 
     bos = new BufferedOutputStream(fos); 


     // writes the encrypted text into file 
     bos.write(hexEncryptedByteText.length());     


     System.out.println("encryptedText has been written successfully in " 
        +fileName); 

     // allows to catch bug in code 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try{ 
      // check for null exception 
      if (bos != null){ 
       bos.close(); 

      } 
      // check for null exception 
      if (fos != null){ 
       fos.close(); 
      } 
     } catch (IOException e){ 
      e.printStackTrace(); 

     } 



    } 






    // creates a file input stream by opening a path to the file needed 
    FileInputStream fin = new FileInputStream("C:/Users/*****/public.cert"); 
    // implements the X509 certificate type 
    CertificateFactory f = CertificateFactory.getInstance("X.509"); 
    // initalizes data found in the file 
    X509Certificate certificate = (X509Certificate)f.generateCertificate(fin); 
    // gets public key from this certificate 
    PublicKey pk = certificate.getPublicKey(); 
    System.out.println(pk); 

    String hexEncryptedByteKey = encryptedKey(pk, secretkey); 
    System.out.println("Encrypted Key: " + hexEncryptedByteKey); 
    System.out.println("Encrypted Key length: " + hexEncryptedByteKey.length()); 

    // allows to write data to a file 
    FileOutputStream newFos = null; 
    // write bytes to file 
    BufferedOutputStream newBos = null; 
    // create file to which data needs to be written 
    String fileNameKey = "C:/Users/****/symmetric.txt"; 

    try{ 
     // allows written data to go into the written path 
     newFos = new FileOutputStream(fileNameKey); 
     // converts written data into bytes 
     newBos = new BufferedOutputStream(newFos); 



     // writes the encrypted text into file 
     newBos.write(hexEncryptedByteKey.length());     


     System.out.println("encryptedKey has been written successfully in " 
        +fileNameKey); 






     // allows to catch bug in code 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try{ 
      // check for null exception 
      if (newBos != null){ 
       newBos.close(); 

      } 
      // check for null exception 
      if (newFos != null){ 
       newFos.close(); 
      } 
     } catch (IOException e){ 
      e.printStackTrace(); 

     } 
    } 

    // load keystore to get private key 
    KeyStore ks = KeyStore.getInstance("JKS"); 
    String password = "*****"; 
    char[] passwordChar = password.toCharArray(); 
    System.out.println("password: " + passwordChar); 
    // locate file 
    try (FileInputStream fis = new FileInputStream("C:/Users/*****/keystore.jks")) { 
     ks.load(fis, passwordChar); 
    } 

    // protect password for keystore 
    KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(passwordChar); 

    // get private key from keystore 
    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) 
      ks.getEntry("*****", protParam); 

    PrivateKey myPrivateKey = pkEntry.getPrivateKey(); 

    System.out.println("private key: " + myPrivateKey); 
    //method declaration 
    String decryptedKey = decryptedKey(myPrivateKey, hexEncryptedByteKey); 

    System.out.println("decrypted Key: " + decryptedKey); 

    String hexDecryptedByteText = decryptedTextHex(decryptedKey, hexEncryptedByteText); 
    System.out.println("key: " + hexDecryptedByteText); 

} 




public static String encrypt(String plainText, SecretKey secretkey) throws Exception { 
    //Encodes the string into a sequence of bytes 
    byte[] plainTextByte = plainText.getBytes(); 
    //intialize cipher to encryption mode 
    cipher.init(Cipher.ENCRYPT_MODE, secretkey); 
    //data is encrypted 
    byte[] encryptedByte = cipher.doFinal(plainTextByte); 
    //Base64.Encoder encoder = Base64.getEncoder(); 
    //encodes bytes into a string using Base64 
    byte[] encryptedByteText = Base64.getEncoder().encode(plainTextByte); 
    String hexEncryptedByteText = DatatypeConverter.printHexBinary(plainTextByte); 
    // return the string encrypted text to the main method 
    return hexEncryptedByteText; 

} 

public static String encryptedKey(PublicKey pk, SecretKey secretkey) throws Exception { 
    // data written to byte array 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    // writes data types to the output stream 
    ObjectOutputStream writter = new ObjectOutputStream(baos); 
    //specific object of secretkey is written to the output stream 
    writter.writeObject(secretkey); 

    //creates a byte array 
    byte[] plainTextByteKey = baos.toByteArray(); 

    //creates a cipher using the RSA algorithm 
    Cipher cipher = Cipher.getInstance("RSA"); 
    // initalizes cipher for encryption using the public key 
    cipher.init(Cipher.ENCRYPT_MODE, pk); 
    //encrypts data 
    //byte[] encryptedByteKey = Base64.getEncoder().encode(plainTextByteKey); 

    String hexEncryptedByteKey = DatatypeConverter.printHexBinary(plainTextByteKey); 
    //Base64.Encoder encoderKey = Base64.getEncoder(); 
    // encodes the byte array into a string. 
    //String encryptedTextKey = new String(encryptedByteKey); 
    return hexEncryptedByteKey; 

} 

private static String decryptedKey(PrivateKey myPrivateKey, String hexEncryptedByteKey) throws Exception { 

    //ByteArrayOutputStream baosDecrypt = new ByteArrayOutputStream(); 
    //ObjectOutputStream writterDecrypt = new ObjectOutputStream(baosDecrypt); 
    //writterDecrypt.writeObject(hexEncryptedByteKey); 
    //byte[] byteKeyDecrypt = baosDecrypt.toByteArray(); 


    Cipher cipher; 
    cipher = Cipher.getInstance("RSA"); 
    cipher.init(Cipher.DECRYPT_MODE, myPrivateKey); 
    //cipher.doFinal(); 

    //byte [] decryptedKey = Base64.getDecoder().decode(byteKeyDecrypt); 
    //String decryptedTextKey = new String(byteKeyDecrypt); 

    byte[] decodedHex = DatatypeConverter.parseHexBinary(hexEncryptedByteKey); 
    System.out.println("decoded hex key: " + decodedHex); 
    String decryptedKey = new String(decodedHex, "UTF-8"); 
    return decryptedKey; 





} 

private static String decryptedTextHex(String decryptedKey, String hexEncryptedByteText) throws Exception { 

    byte[] decryptedTextByte = decryptedKey.getBytes(); 
    byte[] textString = hexEncryptedByteText.getBytes(); 
    SecretKey key = new SecretKeySpec(decryptedTextByte, 0, decryptedTextByte.length, "AES"); 


    Cipher cipher; 
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    //IvParameterSpec iv = new IvParameterSpec(cipher.getIV()); 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] decodedTextHex = cipher.doFinal(textString); 

    byte[] decoded = Base64.getDecoder().decode(decodedTextHex); 

    String hexDecryptedByteText = DatatypeConverter.printHexBinary(decoded); 


    return hexDecryptedByteText; 



} 

}

这是我收到的错误:

Exception in thread "main" java.security.InvalidKeyException: Parameters missing 
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:469) 
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:313) 
at javax.crypto.Cipher.implInit(Cipher.java:802) 
at javax.crypto.Cipher.chooseProvider(Cipher.java:864) 
at javax.crypto.Cipher.init(Cipher.java:1249) 
at javax.crypto.Cipher.init(Cipher.java:1186) 
at ReadFileExample.generatekey.decryptedTextHex(generatekey.java:289) 
at ReadFileExample.generatekey.main(generatekey.java:202) 

我不知道什么是错的。如果我的密钥解密不正确或只是解密字符串。但是,在解密密钥时我没有任何错误。

有关更多信息:我生成一个密钥,用密钥加密一个字符串,然后用生成的公钥加密密钥。然后我用私钥解密密钥,最后我需要用解密的密钥解密字符串。

非常感谢帮助。我一直在研究这么久,我只是不知道该做什么。 ]

编辑:其他问题与我的问题无关。我甚至没有那样的错误信息,并且我已经下载了该解决方案所述的JCE。

+0

可能重复的[Java安全:非法密钥大小或默认参数?](https://stackoverflow.com/questions/6481627/java-security-illegal密钥大小或默认参数) –

+0

实际上,您并没有对工作密钥(DEK)进行加密,只能以任何有能力的对手在几秒钟内破解的方式进行编码;并且你解码不正确(在两个级别!),所以解密数据将失败。加上你的文件写入是错误的,但是你不用这些文件。但是这种例外是因为你使用了CBC模式,它需要在加密过程中使用的初始化矢量(IV)也用于解密,通过将它传递给第三个参数到'Cipher.init'参见https://stackoverflow.com/q/15554296 https://stackoverflow.com/q/29575024 https://stackoverflow.com/q/35907877 –

回答

0

你必须小心使用密钥大小,AES是一个128位分组密码,支持128位,192位和256位密钥,所以如果你的密钥大小不同,你会得到异常,如果你的密钥大小是大于128那么代码将无法工作,除非你有无限制的策略文件。基本上有很多细节。如果你想看到一些工作代码检查出这个链接:https://github.com/Jsondb/jsondb-core/blob/master/src/main/java/io/jsondb/crypto/DefaultAESCBCCipher.java

+0

OP使用'KeyGenerator'用于'.init(256)',这几乎是他们做的唯一一件事_right_。 –