首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要关于AES、CTR密码、python和Java的建议

需要关于AES、CTR密码、python和Java的建议
EN

Stack Overflow用户
提问于 2016-11-15 17:10:07
回答 1查看 1.3K关注 0票数 1

当使用Python (源简单地窖 )加密一些任意数据,然后在java应用程序中使用相同的加密数据时,我正在进行项目工作。

我想了解JSSE和Pycrypto之间的概念区别。

这是完成加密(来源)的python部分:

代码语言:javascript
复制
counter = Counter.new(HALF_BLOCK, prefix=salt[:HALF_BLOCK//8])
cipher = AES.new(cipher_key, AES.MODE_CTR, counter=counter)

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

代码语言:javascript
复制
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密码的初始化抛出异常:

代码语言:javascript
复制
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)

HALF_BLOCK值为64。

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

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-07 04:28:00

现在( IV的“左边”;“右”是顺序计数器)应该像IV一样与密码文本一起传送。没有必要保守这个现在的秘密。它只是,不能将重新用于使用同一密钥加密的另一条消息。

看起来Python代码正在生成一个新的Counter,它是64位长,并将prefix (我假设nonce值)设置为salt变量的第一个8字节。它很有可能(这里有很大的假设,因为我无法访问Python代码)在* 8处启动实际的0x00计数器值,所以您的初始IV是:

代码语言:javascript
复制
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个字节)。

代码语言:javascript
复制
// 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);

这里有一个完整的测试用例,它断言加密和解密是内部兼容的;您也可以使用Python端的数据来验证这一点。

代码语言:javascript
复制
    @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);
    }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40615753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档