2017-05-19 30 views
1

我使用下面的代碼進行加密,並在Java中解密的Postgres解密,似乎工作的罰款:加密Java和(使用pgcrypto模塊)

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 
import java.security.SecureRandom; 

public class MainNew { 

    public static void main(String[] args) { 
     String iv = getEncryptionIV(); 
     System.out.println(" iv = "+iv); 

     String encryptedData= encryptWithIVandKey(iv,encryptionKey,"[email protected]"); 
     System.out.println(encryptedData); 
     String decryptedData = decrypt (iv,encryptionKey,encryptedData); 
     System.out.println(decryptedData); 
    } 


    static final String encryptionKey = "[email protected]"; 


    static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) { 

     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      cipher.init(encryptMode, key, new IvParameterSpec(DatatypeConverter.parseHexBinary(iv))); 
      byte[] data = cipher.doFinal(bytes); 

      return data; 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 
     return null; 

    } 



    static SecretKey generateKey(String passphrase) { 

     SecretKey key = null; 

     try { 

      key = new SecretKeySpec(passphrase.getBytes("UTF-8"), "AES"); 


     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 

     return key; 
    } 




    static String getEncryptionIV() { 
     SecureRandom random = new SecureRandom(); 
     byte[] ivBytes = new byte[16]; 
     random.nextBytes(ivBytes); 
     return DatatypeConverter.printHexBinary(ivBytes); 
    } 

    static String encryptWithIVandKey(String iv, String passphrase, final String strToEncrypt) { 
     String encryptedStr = ""; 

     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      SecretKey key = generateKey(passphrase); 
      cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(DatatypeConverter.parseHexBinary(iv))); 

      encryptedStr = DatatypeConverter.printBase64Binary(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 


     return encryptedStr; 
    } 

    static String decrypt(String iv, String passphrase, String ciphertext) { 
     try { 
      SecretKey key = generateKey(passphrase); 
      byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, DatatypeConverter.parseBase64Binary(ciphertext)); 
      return new String(decrypted, "UTF-8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 
     return ""; 
    } 

} 

但是,當我嘗試解密產生的加密數據Postgres的,得到錯誤:

select convert_from(decrypt_iv('IKMfAng499RNG9viRAreMM5Pmqooidkx76YUBflmzzs=', '[email protected]'::bytea, 'F700FE182F347120F1AE67F5B64E68C2'::bytea, 'aes-cbc/pad:pkcs'),'utf-8') res; 

ERROR: decrypt_iv error: Data not a multiple of block size

回答

0

當然,當你重新運行的Java類,你會得到一個新的IV--正因爲如此,新的加密字符串。我在想,你從上面注入到PostgreSQL例子中的IV和加密字符串是壞的。當我從Java運行類,並獲得新的價值...

輸出:

iv = CE63BC477D1096B6F38CA77964CBD2CB 
pl26CH0sNT8gycZe0FVSVUpwH/moMaFpa6zMtZHcBKQ= 
[email protected] 

但是,這並不是真正的問題......你要記住,你的加密字符串作爲base64編碼的字符串出現。使用解碼(文本,文本)。然後,IV作爲十六進制編碼字符串出現。也使用解碼。

select convert_from(
    decrypt_iv(
    decode('pl26CH0sNT8gycZe0FVSVUpwH/moMaFpa6zMtZHcBKQ=','base64'), 
    '[email protected]'::bytea, 
    decode('CE63BC477D1096B6F38CA77964CBD2CB','hex'), 'aes-cbc/pad:pkcs'),'utf-8') res;