2013-11-04 58 views
1

我想用Java解密AES加密的消息。我一直在尝试standard libraryBouncyCastle的各种算法/模式/填充选项。没有:-(在Java中解密AES编码的消息(用Python加密)

加密实体是用Python编写,并已在生产运气加密邮件已经出去了,所以我不能轻易改变的那部分的Python代码看起来是这样的:

from Crypto.Cipher import AES 
import base64 
import os 
import sys 

BLOCK_SIZE = 16 
PADDING = '\f' 

pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING 

EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s))) 
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING) 

secret = 'XXXXXXXXXXXXXXXX' 

cipher = AES.new(secret) 

clear='test' 
encoded = EncodeAES(cipher, clear) 

print 'Encrypted string:>>{}<<'.format(encoded) 

decoded = DecodeAES(cipher, encoded) 

print 'Decrypted string:>>{}<<'.format(decoded) 

显然使用了AES,我发现我必须使用ECB模式,但是我还没有找到适用于Java端的填充模式,如果输入符合块大小并且没有填充,我可以解密如果消息需要填充,解密失败

解密的Java代码如下所示:

public class AESPaddingTest { 

    private enum Mode { 
     CBC, ECB, CFB, OFB, PCBC 
    }; 

    private enum Padding { 
     NoPadding, PKCS5Padding, PKCS7Padding, ISO10126d2Padding, X932Padding, ISO7816d4Padding, ZeroBytePadding 
    } 

    private static final String ALGORITHM = "AES"; 
    private static final byte[] keyValue = new byte[] { 'X', 'X', 'X', 'X', 
      'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' }; 

    @BeforeClass 
    public static void configBouncy() { 
     Security.addProvider(new BouncyCastleProvider()); 
    } 

    @Test 
    public void testECBPKCS5Padding() throws Exception { 
     decrypt("bEpi03epVkSBTFaXlNiHhw==", Mode.ECB, 
       Padding.PKCS5Padding); 
    } 

    private String decrypt(String valueToDec, Mode modeOption, 
      Padding paddingOption) throws GeneralSecurityException { 
     Key key = new SecretKeySpec(keyValue, ALGORITHM); 

     Cipher c = Cipher.getInstance(ALGORITHM + "/" + modeOption.name() + "/" + paddingOption.name()); 

     c.init(Cipher.DECRYPT_MODE, key); 

     byte[] decValue = c.doFinal(valueToDec.getBytes()); 

     String clear = new String(Base64.encodeBase64(decValue)); 

     return clear; 
    } 

} 

引发的错误是:

javax.crypto.IllegalBlockSizeException:输入长度必须多个16时 的带衬垫的密

任何想法解密?

+0

如果您可以共享解密时收到的错误消息,那么它会加快解决过程。 – lkamal

+0

当然可以。抛出'javax.crypto.IllegalBlockSizeException:当使用填充密码解密时,输入长度必须是16的倍数'异常。 –

+0

在将它传递给解密函数之前,您是首先解码Base64编码的消息吗? – initramfs

回答

1

您正在使用换页符填充(\f)。我不知道这样做的标准填充方案。因此,我建议您在Java端选择NoPadding,并准备从解密后得到的明文中去除\f个字符。

由于您可以解密未填充的明文,因此它表明您在双方都有相同的密钥材料(这是我很高兴能够从列表中删除的一个常见问题)。

the Python documentation,它看起来像默认情况下选择ECB模式。所以确保你在Java端使用它。

+0

你是对的,NoPadding。我的测试代码的主要问题是encodeBase64的顺序和解密。我刚刚意识到,当我尝试了你的建议。正确的工作代码: byte [] decodeBase64 = Base64.decodeBase64(valueToDec.getBytes()); Key key = new SecretKeySpec(keyValue,ALGORITHM); 密码c =密码。的getInstance( “AES/ECB/NoPadding”); c.init(Cipher.DECRYPT_MODE,key); byte [] encValue = c.doFinal(decodeBase64); return new String(encValue).trim(); –

3

感谢您的好问题,答案和意见。 我对代码做了小的修改,现在它对我来说就像是一种魅力。

import java.security.GeneralSecurityException; 
import java.security.Key; 
import java.security.Security; 

import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 

import android.util.Base64; 

public class AESTest { 

    public enum Mode { 
     CBC, ECB, CFB, OFB, PCBC 
    }; 

    public enum Padding { 
     NoPadding, PKCS5Padding, PKCS7Padding, ISO10126d2Padding, X932Padding, ISO7816d4Padding, ZeroBytePadding 
    } 

    private static final String ALGORITHM = "AES"; 

    private static final byte[] keyValue ="myKey".getBytes(); 


    String decrypt(String valueToDec, Mode modeOption, 
      Padding paddingOption) throws GeneralSecurityException { 



     byte[] decodeBase64 = Base64.decode(valueToDec.getBytes(),0); 

     Key key = new SecretKeySpec(keyValue, ALGORITHM); 
     Cipher c = Cipher.getInstance("AES/ECB/NoPadding"); 
     c.init(Cipher.DECRYPT_MODE, key); 
     byte[] encValue = c.doFinal(decodeBase64); 
     return new String(encValue).trim(); 

    } 

} 

然后,我用的类我的Android活动如下:

AESTest aes=new AESTest(); 
String decrypted = aes.decrypt(myCipheredText,Mode.ECB,Padding.NoPadding); 

注意的是Python代码的myKey秘密Java代码是相同里边反。