【问题标题】:Whats is the Java name for openssl's "aes-256-cfb"?openssl 的“aes-256-cfb”的 Java 名称是什么?
【发布时间】:2015-08-04 07:51:30
【问题描述】:

我正在使用 openssl 的 aes-256-cfb 算法(来自 NodeJS 的加密模块)。

虽然 NodeJS 和 Java 代码都成功加密和解密数据,但密文不同,即使 iv、密钥和明文都相同。

openssl/NodeJS cipherText:
05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d

Java cipherText: 
05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D

我猜到 openssl 的 aes-256-cfb 会转换成 Java 的 AES/CFB/NoPadding

密文都共享相同的初始 9 个字节,这很奇怪 - 如果使用的通用模式存在一些差异,我本来希望它们共享前 16 个字节。 (我希望“共模”是CFB/CBC/CTR/等的统称)

  • Java 的 AES/CFB/NoPadding 是 OpenSSL 的 aes-256-cfb 的正确翻译吗?
  • 常见的前九个字节的存在是否意味着 Java 的 AES/CFB/NoPadding 至少使用 AES256,而不是 AES128?
  • 如果是这样,还有什么可以解释不同的密文?

测试用例如下:

OpenSSL/NodeJS:

var assert = require('assert');
var crypto = require('crypto');

describe('crypto', function() {
  it('should work', function () {
    var plainText = new Buffer('a secret plainText which has more than sixteen bytes');
    var key = new Buffer('fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210', 'hex');
    var iv = new Buffer('0123456789abcdef0123456789abcdef', 'hex');      

    var cipher = crypto.createCipheriv('aes-256-cfb', key, iv);
    var decipher = crypto.createDecipheriv('aes-256-cfb', key, iv);

    var cipherText = cipher.update(plainText);
    cipher.final(); // no need to use this value with cfb, it seems to always be empty?

    assert.equal(plainText.length, cipherText.length);

    assert.equal('05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d', cipherText.toString('hex'));

    var deciphered = decipher.update(cipherText);
    decipher.final(); // no need to use value this with cfb, it seems to always be empty?

    assert.equal(plainText, deciphered.toString('utf8'));
  });
});

Java/Android:

import android.test.InstrumentationTestCase;

import com.google.protobuf.ByteString;
import bit.Twiddling;

import java.security.AlgorithmParameters;

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

public class CryptoTest extends InstrumentationTestCase {

    public void test_encrypt_and_decrypt() throws Exception {
        byte[] plainText = "a secret message which has more than sixteen bytes".getBytes();
        byte[] key = Twiddling.hexStringBEToBytes("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
        byte[] iv = Twiddling.hexStringBEToBytes("0123456789abcdef0123456789abcdef");//0123456789abcdef0123456789abcdef");

        SecretKeySpec aesSecret = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
        Cipher decipher = Cipher.getInstance("AES/CFB/NoPadding");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        assertEquals(16, iv.length);

        cipher.init(Cipher.ENCRYPT_MODE, aesSecret, ivps);
        byte[] cipherText = cipher.doFinal(plainText);

        assertEquals(plainText.length, cipherText.length);
        assertEquals("05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D", Twiddling.bytesToHexStringBE(cipherText));

        decipher.init(Cipher.DECRYPT_MODE, aesSecret, ivps);
        byte[] deciphered = decipher.doFinal(cipherText);

        assertEquals(new String(plainText), new String(deciphered));
    }
}

【问题讨论】:

    标签: java node.js encryption openssl cryptography


    【解决方案1】:

    这是一个查找/替换错误 - 两个纯文本在前九个字节之后不同。

    OpenSSL 的aes-256-cfb 的Java 名称​​是 AES/CFB/NoPadding

    【讨论】:

    • 所以如果代码没问题,为什么还要保留这个问题呢?这就是不可复制的定义。
    • @ArtjomB。好吧,你可以试试"AES/CFB128/NoPadding" 作为替代方案:)
    • @ArtjomB。由于可怕的警告而未删除:“重复删除已回答的问题可能会导致您的帐户被阻止提问。您确定要删除吗?”。
    • @chrisdew 也许您应该考虑如何以不同的方式使用 StackOverflow,这样就不会发生这种情况。
    猜你喜欢
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    相关资源
    最近更新 更多