2011-07-08 28 views
0

BouncyCastleでStringパスワードを暗号化および復号化する暗号化Javaテストクラスを作成しようとしています。 main()は非常にシンプルで、私はencryptPass()を実行してからdecryptPass()を実行し、コンソールのトレースを見ます。javax.cryptoでのパディング例外の取得

javax.crypto.BadPaddingException: pad block corrupted 
    at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source) 
    at javax.crypto.Cipher.doFinal(DashoA13*..) 
    at com.kiengi.crypto.Crypto.decryptPass(Crypto.java:79) 

私のコードは暗号クラスについては、以下である:それは解読しようとしたとき

問題がある、私はパディング例外が発生しました

// password to be crypted 
public String pass = "password_go_here"; 

// key for encrypt pass 
public String passKey = generateRandomKey(); // generation clef 16 caractere [a-zA-Z0-9] 

// Encrypted pass 
public String cryptedPass; 

public final Logger logger = Logger.getLogger(this.getClass()); 

private final static byte[] IV_BYTES = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 
     0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; 

public Crypto() { 
    super(); 
} 

public void encryptPass(){ 

    Security.addProvider(new BouncyCastleProvider()); 
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES); 

    try{ 
     KeyGenerator _keygen = KeyGenerator.getInstance("AES"); 
     _keygen.init(new SecureRandom(passKey.getBytes())); 
     SecretKey _key = _keygen.generateKey(); 
     logger.trace("Secret key generated"); 

     Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); 
     _cipher.init(Cipher.ENCRYPT_MODE, _key, _ivSpec); 

     cryptedPass = asHex(_cipher.doFinal(pass.getBytes("UTF-8"))); 


     logger.trace("Encrypted pass : "+cryptedPass); 


    }catch (Exception e) { 
     logger.warn("encrypt failed"); 
     e.printStackTrace(); 
    } 
} 

public void decryptPass() { 
    byte[] _passKey = passKey.getBytes(); 
    byte[] _cryptedPass = hexFromString(cryptedPass); 

    Security.addProvider(new BouncyCastleProvider()); 
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES); 

    try {   
     KeyGenerator _keygen = KeyGenerator.getInstance("AES"); 
     _keygen.init(new SecureRandom(_passKey)); 
     SecretKey _key = _keygen.generateKey(); 
     logger.trace("Secret key generated"); 

     Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); 
     _cipher.init(Cipher.DECRYPT_MODE, _key, _ivSpec); 

     String _pass = new String(_cipher.doFinal(_cryptedPass), "UTF-8"); 

     logger.trace("Decrypted pass : "+_pass); 

    } catch (Exception e) { 
     logger.warn("decrypt failed"); 
     e.printStackTrace(); 
    } 

} 

private int fromDigit(char ch) { 
    if ((ch >= '0') && (ch <= '9')) { 
     return ch - '0'; 
    } else if ((ch >= 'A') && (ch <= 'F')) { 
     return ch + 10 - 'A'; 
    } else if ((ch >= 'a') && (ch <= 'f')) { 
     return ch + 10 - 'a'; 
    } else { 
     throw new IllegalArgumentException(String.format(
       "Invalid hex character 0x%04x", 0xff & ch)); 
    } 
} 

private byte[] hexFromString(String hex) { 
    final byte[] buf = new byte[hex.length()/2]; 
    for (int i = 0, j = 0; i < hex.length(); i += 2) { 
     buf[j++] = (byte) (fromDigit(hex.charAt(i)) << 4 | fromDigit(hex 
       .charAt(i + 1))); 
    } 
    return buf; 
} 

private static String asHex(byte buf[]) { 
    final Formatter formatter = new Formatter(new StringBuffer()); 
    for (int i = 0; i < buf.length; i++) { 
     formatter.format("%02x", 0xff & buf[i]); 
    } 
    return formatter.toString(); 
} 

private String generateRandomKey() { 
    String _chars = "abcdefABCDEF1234567890"; 
    StringBuffer _pass = new StringBuffer(); 
    for (int x = 0; x < 32; x++) { 
     int i = (int) Math.floor(Math.random() * (_chars.length() - 1)); 
     _pass.append(_chars.charAt(i)); 
    } 
    return _pass.toString(); 
} 

は誰が何この例外手段を知っています?

答えて

0

このコードにはバグがあります。 new SecureRandom(passKey.getBytes())は、でSecureRandomインスタンスを初期化し、コンストラクタで提供されたバイト数はであることを前提としています。これは間違っています。コンストラクタ内のデータは、を置き換えずにのエントロピーソースSecureRandomを使用します。はそれらを置き換えません。

適切なパスワードベースの暗号化(PBE)スキームを使用する必要があります。

+1

良いキャッチ。はい、暗号化アルゴリズムでうまく動作する鍵長にパスワードをハッシュする必要があります(つまり、SHA256(パスワード)をAES 256キーとして使用します)。現在、暗号化と復号化の両方のためにランダムに鍵を生成しています。 –

0

この例外は、パディングブロックが壊れていることを意味します。 16BブロックのPKCS#7パディングを使用します。このサンプルでは、​​出力も16Bです。したがって、常に0x16の16バイトのブロックを追加する必要があります。
復号化が破損しているため、パディングが壊れています。 SecureRandomの実装では、独自のエントロピーが追加され、間違った復号鍵が生成されます。このSecureRandomコンストラクタは、SecureRandom実装を登録した最初のプロバイダの最初のPRNGアルゴリズムを使用します。

関連する問題