2012-10-09 54 views
1

我必須在數據庫表中存儲到另一個數據庫的連接細節,我必須將密碼加密到這些數據庫,並且必須能夠「手動」插入數據爲通過SQL腳本,表...加密一個字符串,將其保存到數據庫,加載它並解密它

我需要進行加密和解密,因爲我的應用程序必須能夠使用這些數據,並連接到其它數據庫,所以MD5和類似的是沒有用的..

我想到Blowfish,AES等......但是如果我將密碼作爲VARCHAR存儲在數據庫中,則解密部分不起作用......所以我將它存儲爲BYTE,但是如果我這樣做了,則沒有人可以編寫腳本預加載桌面上的數據..

也許我缺少的東西在這裏...

這裏的時候在表中的註冊表被定義爲VARCHAR我使用的代碼:

package main; 

import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.SecretKeySpec; 


public class Prueba { 

    private static final String keyValue = "fd<[;.7e/OC0W!d|"; 
    private static final String ALG = "Blowfish"; 

    public static void main(String[] args) { 
     String text = "some random text"; 

     try { 
      SecretKeySpec key = new SecretKeySpec(keyValue.getBytes(), ALG); 
      Cipher cipher = Cipher.getInstance(ALG); 
      cipher.init(Cipher.ENCRYPT_MODE, key); 
      byte[] encryptedBytes = cipher.doFinal(text.getBytes()); 
      String encrypted = new String(encryptedBytes); 

      cipher.init(Cipher.DECRYPT_MODE, key); 
      byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes()); 
      String recovered = new String(recoveredBytes); 

     } catch (NoSuchAlgorithmException nsa) { 
      nsa.printStackTrace(); 
     } catch (NoSuchPaddingException nspe) { 
      nspe.printStackTrace(); 
     } catch (InvalidKeyException ike) { 
      ike.printStackTrace(); 
     } catch (BadPaddingException bpe) { 
      bpe.printStackTrace(); 
     } catch (IllegalBlockSizeException ibse) { 
      ibse.printStackTrace(); 
     } 
    } 


} 

我得到異常:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher 
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275) 
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275) 
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA12275) 
    at javax.crypto.Cipher.doFinal(DashoA12275) 
    at main.Prueba.main(Prueba.java:30) 
如果相反的

byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes()); 

我做

byte[] recoveredBytes = cipher.doFinal(encryptedBytes); 

我沒有得到任何異常,但我必須存儲密碼的byte [] SOOOO沒有腳本更多鈔票...

任何想法?

+1

爲什麼不只是存儲十六進制(或Base64)編碼的字節而不是字節自己的字符串?將會有空間處罰,但是你可以從腳本等預加載。而且它可能更容易在數據庫之間移植。 – maerics

+0

我相信你可能會發現這個有用http://stackoverflow.com/a/4183913/579580 – aviad

+1

Passwors出於安全原因應該總是作爲字節存儲[] –

回答

0

最後,作爲maerics建議,我解決了這種方式:

import org.apache.commons.net.util.Base64; 

public class MyCrypto { 

    /** 
    * Codifica un texto usando Base64. 
    * @param texto <code>String</code> texto a codificar. 
    * @return <code>String</code> texto codificado. 
    */ 
    public static String encrypt(String texto) { 
     return new String(Base64.encodeBase64(texto.getBytes())); 
    } 

    /** 
    * Decodifica un texto usando Base64. 
    * @param texto <code>String</code> texto a decodificar. 
    * @return <code>String</code> texto decodificado. 
    */ 
    public static String decrypt(String texto) { 
     return new String(Base64.decodeBase64(texto.getBytes())); 
    } 
} 
1

它看起來像當你把密鑰存儲爲字節時,某處某處正在解釋它不正確。這可能是一個字符編碼問題。

如果您想將密鑰存儲爲文本,您可能需要首先對其進行base64編碼。然後,您可以將base64解碼文本回密鑰。

+2

這是註定要在它到達數據庫之前,一個源於'encrypted.getBytes()'的問題不同於'encryptedBytes'(這本身就是一個由轉換一個字節數組轉換爲字符串) – NullUserException

0
String encrypted = new BASE64Encoder().encodeBuffer (encryptedBytes);    
cipher.init(Cipher.DECRYPT_MODE, key); 
byte[] recoveredBytes = cipher.doFinal(new BASE64Decoder().decodeBuffer ( encrypted));