2011-04-12 25 views
11

Ben Bouncy Castles Hafif API aşağıdaki JDK JCE şifreleme kodunu haritalama sorun yaşıyorum:256bit AES/CBC/PKCS5Padding ile Bouncy Kalesi

public String dec(String password, String salt, String encString) throws Throwable { 
    // AES algorithm with CBC cipher and PKCS5 padding 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); 

    // Construct AES key from salt and 50 iterations 
    PBEKeySpec pbeEKeySpec = new PBEKeySpec(password.toCharArray(), toByte(salt), 50, 256); 
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC"); 
    SecretKeySpec secretKey = new SecretKeySpec(keyFactory.generateSecret(pbeEKeySpec).getEncoded(), "AES"); 

    // IV seed for first block taken from first 32 bytes 
    byte[] ivData = toByte(encString.substring(0, 32)); 
    // AES encrypted data 
    byte[] encData = toByte(encString.substring(32)); 

    cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(ivData)); 

    return new String(cipher.doFinal(encData)); 
} 

yukarıdaki harika çalışıyor, ancak dolayı çok taşınabilir Oracle'ın şifreleme gücü kısıtlaması. Bouncy Castles Hafif Ağırlık API'sine taşınmak için birkaç girişimde bulundum, ancak başarılı olamadım. Bir org.bouncycastle.crypto.DataLengthException içinde

public String decrypt1(String password, String salt, String encString) throws Exception { 

    byte[] ivData = toByte(encString.substring(0, 32)); 
    byte[] encData = toByte(encString.substring(32)); 

    PKCS12ParametersGenerator gen = new PKCS12ParametersGenerator(new SHA256Digest()); 
    gen.init(password.getBytes(), toByte(salt), 50); 
    CBCBlockCipher cbcBlockcipher = new CBCBlockCipher(new RijndaelEngine(256)); 
    CipherParameters params = gen.generateDerivedParameters(256, 256); 

    cbcBlockcipher.init(false, params); 

    PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(cbcBlockcipher, new PKCS7Padding()); 
    byte[] plainTemp = new byte[aesCipher.getOutputSize(encData.length)]; 
    int offset = aesCipher.processBytes(encData, 0, encData.length, plainTemp, 0); 
    int last = aesCipher.doFinal(plainTemp, offset); 
    byte[] plain = new byte[offset + last]; 
    System.arraycopy(plainTemp, 0, plain, 0, plain.length); 
    return new String(plain); 
} 

yukarıdaki deneme sonuçları: şifre çözme eksik son blok.

Online örnekleri aradım ancak PKCS5/PKCS7'yi CBD kullanan 256 bit AES için kendi IV verilerinizi doldurma konusunda birçok örnek yok.

NB: toByte işlevi, bir dize base64 veya benzerlerini kullanarak bir bayt dizisine dönüştürür.

cevap

21

Bu sizin için çalışması gerekir:

public String dec(String password, String salt, String encString) 
     throws Exception { 

    byte[] ivData = toByte(encString.substring(0, 32)); 
    byte[] encData = toByte(encString.substring(32)); 

    // get raw key from password and salt 
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), 
      toByte(salt), 50, 256); 
    SecretKeyFactory keyFactory = SecretKeyFactory 
      .getInstance("PBEWithSHA256And256BitAES-CBC-BC"); 
    SecretKeySpec secretKey = new SecretKeySpec(keyFactory.generateSecret(
      pbeKeySpec).getEncoded(), "AES"); 
    byte[] key = secretKey.getEncoded(); 

    // setup cipher parameters with key and IV 
    KeyParameter keyParam = new KeyParameter(key); 
    CipherParameters params = new ParametersWithIV(keyParam, ivData); 

    // setup AES cipher in CBC mode with PKCS7 padding 
    BlockCipherPadding padding = new PKCS7Padding(); 
    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
      new CBCBlockCipher(new AESEngine()), padding); 
    cipher.reset(); 
    cipher.init(false, params); 

    // create a temporary buffer to decode into (it'll include padding) 
    byte[] buf = new byte[cipher.getOutputSize(encData.length)]; 
    int len = cipher.processBytes(encData, 0, encData.length, buf, 0); 
    len += cipher.doFinal(buf, len); 

    // remove padding 
    byte[] out = new byte[len]; 
    System.arraycopy(buf, 0, out, 0, len); 

    // return string representation of decoded bytes 
    return new String(out, "UTF-8"); 
} 

Ben senin kodu (gerekli 16 bayt içerir) IV 32 karakterleri kullanır çünkü aslında toByte() için altıgen kodlama yapıyoruz varsayalım. Şifrelemeyi yaptığınız kod olmasa da, bu kodun kodunuzla aynı şifresi çözülmüş çıktıyı vereceğini doğruladım.

+0

İlk 32 karakterin IV olduğunu farz etmenin doğru olduğuna emin misiniz? Eğer öyleyse, bu temel nedir? –

+1

'SecretKeyFactory keyFactory = SecretKeyFactory .getInstance (" PBEWithSHA256And256BitAES-CBC-BC ");' ve diğer satırlar hafif API değildir, değil mi? – alphakermit