Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要关于AES CTR密码python与Java的建议吗_Java_Aes_Pycrypto_Python Simple Crypt - Fatal编程技术网

需要关于AES CTR密码python与Java的建议吗

需要关于AES CTR密码python与Java的建议吗,java,aes,pycrypto,python-simple-crypt,Java,Aes,Pycrypto,Python Simple Crypt,我正在进行一个项目,使用Python(源代码)对一些任意数据进行加密,然后在java应用程序中使用相同的加密数据 我想了解JSSE和Pycrypto在概念上的区别 这是python的加密部分(): 这是我对java重新实现相同操作的尝试: SecretKeySpec key = new SecretKeySpec(cipher_key, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(salt, 0, HALF_BLOCK / 8); C

我正在进行一个项目,使用Python(源代码)对一些任意数据进行加密,然后在java应用程序中使用相同的加密数据

我想了解JSSE和Pycrypto在概念上的区别

这是python的加密部分():

这是我对java重新实现相同操作的尝试:

SecretKeySpec key = new SecretKeySpec(cipher_key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(salt, 0, HALF_BLOCK / 8);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
这里的问题是java Cipher的初始化引发异常:

java.security.InvalidAlgorithmParameterException: IV must be 16 bytes long.
    at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)
    at javax.crypto.Cipher.init(Cipher.java:1394)
    at javax.crypto.Cipher.init(Cipher.java:1327)
半块的值为64

所以问题是,python的AES实现如何使用半块/8键大小而java不使用

谢谢

nonce(IV的“左侧”,“右侧”是顺序计数器)应与密码文本一起作为IV传输。无需对nonce保密。它只是不能被用同一密钥加密的另一封邮件重复使用

Python代码似乎正在生成一个新的
计数器
,其长度为
64位,并将
前缀
(我假设
nonce
值)设置为
salt
变量的第一个
8
字节。很可能(这里的假设很大,因为我无法访问Python代码)会在
0x00
*8处启动实际的计数器值,因此您的初始IV为:

salt = '#Eg����' # => UTF-8 encoding of 0x0123456789ABCDEF (not familiar enough with Python for the actual expression)
# Really may be misunderstanding, but as the AES IV must be 16 bytes, I imagine the terminology here is prefix = 8 bytes, sequence = 8 bytes
counter = Counter.new(HALF_BLOCK, prefix=salt[:HALF_BLOCK]) # => '0x01234567 89ABCDEF 00000000 00000000'
# Perform one encryption
counter # => '0x01234567 89ABCDEF 00000000 00000001'
# etc.
要在Java中执行相同的操作,应该简单到将
IvParameterSpec
初始化为与上面相同的值(即用
0
右键填充salt的前8个字节到16个字节)

这里有一个完整的测试用例,它断言加密和解密是内部兼容的;您还可以使用来自Python端的数据运行此程序以进行验证

    @Test
    public void testPythonCompatibility() {
        // Arrange
        byte[] cipher_key = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEFFEDCBA9876543210");
        final int HALF_BLOCK = 64;
        byte[] salt = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEF");
        byte[] nonceAndCounter = new byte[16];
        System.arraycopy(salt, 0, nonceAndCounter, 0, ((int) (HALF_BLOCK / 8)));
        IvParameterSpec iv = new IvParameterSpec(nonceAndCounter);
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
        SecretKeySpec key = new SecretKeySpec(cipher_key, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final String plaintext = "This is a plaintext message.";

        // Act
        byte[] cipherBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

        // Assert
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        byte[] recoveredBytes = cipher.doFinal(cipherBytes);
        String recovered = new String(recoveredBytes, StandardCharsets.UTF_8);
        assert recovered.equals(plaintext);
    }

通常最好不要使用CTR模式,因为它很容易出错。问题是,同一个密钥和计数器决不能重复使用。通常,CBC模式与随机IV一起使用,PKCS#7填充用于容纳不是块大小倍数的输入。@zaph:没错。不幸的是,这是所用python库给出的要求。注意:PyCrypto的
计数器的默认初始值。new
为1,您需要根据java中使用的值对其进行设置。
Cipher.getInstance
中的
“BC”
是什么,表明它正在用作安全提供程序。您还可以使用本机Sun JCE等。有关更多信息,请参阅文档。
// Intentionally verbose for demonstration; this can obviously be compacted
byte[] salt = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEF");
byte[] nonceAndCounter = new byte[16];
System.arraycopy(salt, 0, nonceAndCounter, 0, ((int) (HALF_BLOCK / 8)));
IvParameterSpec iv = new IvParameterSpec(nonceAndCounter);
    @Test
    public void testPythonCompatibility() {
        // Arrange
        byte[] cipher_key = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEFFEDCBA9876543210");
        final int HALF_BLOCK = 64;
        byte[] salt = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEF");
        byte[] nonceAndCounter = new byte[16];
        System.arraycopy(salt, 0, nonceAndCounter, 0, ((int) (HALF_BLOCK / 8)));
        IvParameterSpec iv = new IvParameterSpec(nonceAndCounter);
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
        SecretKeySpec key = new SecretKeySpec(cipher_key, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final String plaintext = "This is a plaintext message.";

        // Act
        byte[] cipherBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

        // Assert
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        byte[] recoveredBytes = cipher.doFinal(cipherBytes);
        String recovered = new String(recoveredBytes, StandardCharsets.UTF_8);
        assert recovered.equals(plaintext);
    }